UNPKG

6.3 kBJavaScriptView Raw
1import { BUFFER_TYPE } from '@pixi/constants';
2import { Runner } from '@pixi/runner';
3import { getBufferType } from '@pixi/utils';
4import { Attribute } from './Attribute.mjs';
5import { Buffer } from './Buffer.mjs';
6import { interleaveTypedArrays } from './utils/interleaveTypedArrays.mjs';
7
8const byteSizeMap = { 5126: 4, 5123: 2, 5121: 1 };
9let UID = 0;
10const map = {
11 Float32Array,
12 Uint32Array,
13 Int32Array,
14 Uint8Array,
15 Uint16Array
16};
17class Geometry {
18 constructor(buffers = [], attributes = {}) {
19 this.buffers = buffers;
20 this.indexBuffer = null;
21 this.attributes = attributes;
22 this.glVertexArrayObjects = {};
23 this.id = UID++;
24 this.instanced = false;
25 this.instanceCount = 1;
26 this.disposeRunner = new Runner("disposeGeometry");
27 this.refCount = 0;
28 }
29 addAttribute(id, buffer, size = 0, normalized = false, type, stride, start, instance = false) {
30 if (!buffer) {
31 throw new Error("You must pass a buffer when creating an attribute");
32 }
33 if (!(buffer instanceof Buffer)) {
34 if (buffer instanceof Array) {
35 buffer = new Float32Array(buffer);
36 }
37 buffer = new Buffer(buffer);
38 }
39 const ids = id.split("|");
40 if (ids.length > 1) {
41 for (let i = 0; i < ids.length; i++) {
42 this.addAttribute(ids[i], buffer, size, normalized, type);
43 }
44 return this;
45 }
46 let bufferIndex = this.buffers.indexOf(buffer);
47 if (bufferIndex === -1) {
48 this.buffers.push(buffer);
49 bufferIndex = this.buffers.length - 1;
50 }
51 this.attributes[id] = new Attribute(bufferIndex, size, normalized, type, stride, start, instance);
52 this.instanced = this.instanced || instance;
53 return this;
54 }
55 getAttribute(id) {
56 return this.attributes[id];
57 }
58 getBuffer(id) {
59 return this.buffers[this.getAttribute(id).buffer];
60 }
61 addIndex(buffer) {
62 if (!(buffer instanceof Buffer)) {
63 if (buffer instanceof Array) {
64 buffer = new Uint16Array(buffer);
65 }
66 buffer = new Buffer(buffer);
67 }
68 buffer.type = BUFFER_TYPE.ELEMENT_ARRAY_BUFFER;
69 this.indexBuffer = buffer;
70 if (!this.buffers.includes(buffer)) {
71 this.buffers.push(buffer);
72 }
73 return this;
74 }
75 getIndex() {
76 return this.indexBuffer;
77 }
78 interleave() {
79 if (this.buffers.length === 1 || this.buffers.length === 2 && this.indexBuffer)
80 return this;
81 const arrays = [];
82 const sizes = [];
83 const interleavedBuffer = new Buffer();
84 let i;
85 for (i in this.attributes) {
86 const attribute = this.attributes[i];
87 const buffer = this.buffers[attribute.buffer];
88 arrays.push(buffer.data);
89 sizes.push(attribute.size * byteSizeMap[attribute.type] / 4);
90 attribute.buffer = 0;
91 }
92 interleavedBuffer.data = interleaveTypedArrays(arrays, sizes);
93 for (i = 0; i < this.buffers.length; i++) {
94 if (this.buffers[i] !== this.indexBuffer) {
95 this.buffers[i].destroy();
96 }
97 }
98 this.buffers = [interleavedBuffer];
99 if (this.indexBuffer) {
100 this.buffers.push(this.indexBuffer);
101 }
102 return this;
103 }
104 getSize() {
105 for (const i in this.attributes) {
106 const attribute = this.attributes[i];
107 const buffer = this.buffers[attribute.buffer];
108 return buffer.data.length / (attribute.stride / 4 || attribute.size);
109 }
110 return 0;
111 }
112 dispose() {
113 this.disposeRunner.emit(this, false);
114 }
115 destroy() {
116 this.dispose();
117 this.buffers = null;
118 this.indexBuffer = null;
119 this.attributes = null;
120 }
121 clone() {
122 const geometry = new Geometry();
123 for (let i = 0; i < this.buffers.length; i++) {
124 geometry.buffers[i] = new Buffer(this.buffers[i].data.slice(0));
125 }
126 for (const i in this.attributes) {
127 const attrib = this.attributes[i];
128 geometry.attributes[i] = new Attribute(attrib.buffer, attrib.size, attrib.normalized, attrib.type, attrib.stride, attrib.start, attrib.instance);
129 }
130 if (this.indexBuffer) {
131 geometry.indexBuffer = geometry.buffers[this.buffers.indexOf(this.indexBuffer)];
132 geometry.indexBuffer.type = BUFFER_TYPE.ELEMENT_ARRAY_BUFFER;
133 }
134 return geometry;
135 }
136 static merge(geometries) {
137 const geometryOut = new Geometry();
138 const arrays = [];
139 const sizes = [];
140 const offsets = [];
141 let geometry;
142 for (let i = 0; i < geometries.length; i++) {
143 geometry = geometries[i];
144 for (let j = 0; j < geometry.buffers.length; j++) {
145 sizes[j] = sizes[j] || 0;
146 sizes[j] += geometry.buffers[j].data.length;
147 offsets[j] = 0;
148 }
149 }
150 for (let i = 0; i < geometry.buffers.length; i++) {
151 arrays[i] = new map[getBufferType(geometry.buffers[i].data)](sizes[i]);
152 geometryOut.buffers[i] = new Buffer(arrays[i]);
153 }
154 for (let i = 0; i < geometries.length; i++) {
155 geometry = geometries[i];
156 for (let j = 0; j < geometry.buffers.length; j++) {
157 arrays[j].set(geometry.buffers[j].data, offsets[j]);
158 offsets[j] += geometry.buffers[j].data.length;
159 }
160 }
161 geometryOut.attributes = geometry.attributes;
162 if (geometry.indexBuffer) {
163 geometryOut.indexBuffer = geometryOut.buffers[geometry.buffers.indexOf(geometry.indexBuffer)];
164 geometryOut.indexBuffer.type = BUFFER_TYPE.ELEMENT_ARRAY_BUFFER;
165 let offset = 0;
166 let stride = 0;
167 let offset2 = 0;
168 let bufferIndexToCount = 0;
169 for (let i = 0; i < geometry.buffers.length; i++) {
170 if (geometry.buffers[i] !== geometry.indexBuffer) {
171 bufferIndexToCount = i;
172 break;
173 }
174 }
175 for (const i in geometry.attributes) {
176 const attribute = geometry.attributes[i];
177 if ((attribute.buffer | 0) === bufferIndexToCount) {
178 stride += attribute.size * byteSizeMap[attribute.type] / 4;
179 }
180 }
181 for (let i = 0; i < geometries.length; i++) {
182 const indexBufferData = geometries[i].indexBuffer.data;
183 for (let j = 0; j < indexBufferData.length; j++) {
184 geometryOut.indexBuffer.data[j + offset2] += offset;
185 }
186 offset += geometries[i].buffers[bufferIndexToCount].data.length / stride;
187 offset2 += indexBufferData.length;
188 }
189 }
190 return geometryOut;
191 }
192}
193
194export { Geometry };
195//# sourceMappingURL=Geometry.mjs.map