1 | import { BUFFER_TYPE } from '@pixi/constants';
|
2 | import { Runner } from '@pixi/runner';
|
3 | import { getBufferType } from '@pixi/utils';
|
4 | import { Attribute } from './Attribute.mjs';
|
5 | import { Buffer } from './Buffer.mjs';
|
6 | import { interleaveTypedArrays } from './utils/interleaveTypedArrays.mjs';
|
7 |
|
8 | const byteSizeMap = { 5126: 4, 5123: 2, 5121: 1 };
|
9 | let UID = 0;
|
10 | const map = {
|
11 | Float32Array,
|
12 | Uint32Array,
|
13 | Int32Array,
|
14 | Uint8Array,
|
15 | Uint16Array
|
16 | };
|
17 | class 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 |
|
194 | export { Geometry };
|
195 |
|