@loaders.gl/ply 3.1.0-alpha.4 → 3.1.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/bundle.d.ts +2 -0
  2. package/dist/bundle.d.ts.map +1 -0
  3. package/dist/bundle.js +1249 -0
  4. package/dist/es5/bundle.js +1 -1
  5. package/dist/es5/bundle.js.map +1 -1
  6. package/dist/es5/index.js +5 -37
  7. package/dist/es5/index.js.map +1 -1
  8. package/dist/es5/lib/get-ply-schema.js +3 -3
  9. package/dist/es5/lib/get-ply-schema.js.map +1 -1
  10. package/dist/es5/lib/normalize-ply.js +15 -15
  11. package/dist/es5/lib/normalize-ply.js.map +1 -1
  12. package/dist/es5/lib/parse-ply-in-batches.js +107 -247
  13. package/dist/es5/lib/parse-ply-in-batches.js.map +1 -1
  14. package/dist/es5/lib/parse-ply.js +52 -55
  15. package/dist/es5/lib/parse-ply.js.map +1 -1
  16. package/dist/es5/ply-loader.js +3 -3
  17. package/dist/es5/ply-loader.js.map +1 -1
  18. package/dist/esm/ply-loader.js +1 -1
  19. package/dist/esm/ply-loader.js.map +1 -1
  20. package/dist/index.d.ts +30 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +22 -0
  23. package/dist/lib/get-ply-schema.d.ts +10 -0
  24. package/dist/lib/get-ply-schema.d.ts.map +1 -0
  25. package/dist/lib/get-ply-schema.js +36 -0
  26. package/dist/lib/normalize-ply.d.ts +8 -0
  27. package/dist/lib/normalize-ply.d.ts.map +1 -0
  28. package/dist/lib/normalize-ply.js +58 -0
  29. package/dist/lib/parse-ply-in-batches.d.ts +8 -0
  30. package/dist/lib/parse-ply-in-batches.d.ts.map +1 -0
  31. package/dist/lib/parse-ply-in-batches.js +253 -0
  32. package/dist/lib/parse-ply.d.ts +8 -0
  33. package/dist/lib/parse-ply.d.ts.map +1 -0
  34. package/dist/lib/parse-ply.js +350 -0
  35. package/dist/lib/ply-types.d.ts +29 -0
  36. package/dist/lib/ply-types.d.ts.map +1 -0
  37. package/dist/lib/ply-types.js +2 -0
  38. package/dist/ply-loader.d.ts +24 -0
  39. package/dist/ply-loader.d.ts.map +1 -0
  40. package/dist/ply-loader.js +28 -0
  41. package/dist/ply-worker.js +1257 -2
  42. package/dist/workers/ply-worker.d.ts +2 -0
  43. package/dist/workers/ply-worker.d.ts.map +1 -0
  44. package/dist/workers/ply-worker.js +5 -0
  45. package/package.json +10 -8
  46. package/dist/dist.min.js +0 -2
  47. package/dist/dist.min.js.map +0 -1
  48. package/dist/ply-worker.js.map +0 -1
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const schema_1 = require("@loaders.gl/schema");
4
+ const get_ply_schema_1 = require("./get-ply-schema");
5
+ /**
6
+ * @param header
7
+ * @param attributes
8
+ * @returns data and header
9
+ */
10
+ function normalizePLY(plyHeader, plyAttributes, options) {
11
+ const attributes = getMeshAttributes(plyAttributes);
12
+ const boundingBox = (0, schema_1.getMeshBoundingBox)(attributes);
13
+ const vertexCount = plyAttributes.indices.length || plyAttributes.vertices.length / 3;
14
+ // TODO - how to detect POINT CLOUDS vs MESHES?
15
+ // TODO - For Meshes, PLY quadrangles must be split?
16
+ const isTriangles = plyAttributes.indices && plyAttributes.indices.length > 0;
17
+ const mode = isTriangles ? 4 : 0; // TRIANGLES vs POINTS
18
+ const topology = isTriangles ? 'triangle-list' : 'point-list';
19
+ const schema = (0, get_ply_schema_1.getPLYSchema)(plyHeader, attributes);
20
+ const plyMesh = {
21
+ loader: 'ply',
22
+ loaderData: plyHeader,
23
+ header: {
24
+ vertexCount,
25
+ boundingBox
26
+ },
27
+ schema,
28
+ attributes,
29
+ indices: { value: new Uint32Array(0), size: 0 },
30
+ mode,
31
+ topology
32
+ };
33
+ if (plyAttributes.indices.length > 0) {
34
+ plyMesh.indices = { value: new Uint32Array(plyAttributes.indices), size: 1 };
35
+ }
36
+ return plyMesh;
37
+ }
38
+ exports.default = normalizePLY;
39
+ /**
40
+ * @param attributes
41
+ * @returns accessors []
42
+ */
43
+ function getMeshAttributes(attributes) {
44
+ const accessors = {};
45
+ accessors.POSITION = { value: new Float32Array(attributes.vertices), size: 3 };
46
+ // optional attributes data
47
+ if (attributes.normals.length > 0) {
48
+ accessors.NORMAL = { value: new Float32Array(attributes.normals), size: 3 };
49
+ }
50
+ if (attributes.uvs.length > 0) {
51
+ accessors.TEXCOORD_0 = { value: new Float32Array(attributes.uvs), size: 2 };
52
+ }
53
+ if (attributes.colors.length > 0) {
54
+ // TODO - normalized shoud be based on `uchar` flag in source data?
55
+ accessors.COLOR_0 = { value: new Uint8Array(attributes.colors), size: 3, normalized: true };
56
+ }
57
+ return accessors;
58
+ }
@@ -0,0 +1,8 @@
1
+ import { PLYMesh } from './ply-types';
2
+ /**
3
+ * PARSER
4
+ * @param iterator
5
+ * @param options
6
+ */
7
+ export default function parsePLYInBatches(iterator: AsyncIterable<ArrayBuffer> | Iterable<ArrayBuffer>, options: any): AsyncIterable<PLYMesh>;
8
+ //# sourceMappingURL=parse-ply-in-batches.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-ply-in-batches.d.ts","sourceRoot":"","sources":["../../src/lib/parse-ply-in-batches.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAC,OAAO,EAAyC,MAAM,aAAa,CAAC;AAI5E;;;;GAIG;AACH,wBAA+B,iBAAiB,CAC9C,QAAQ,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,EAC5D,OAAO,EAAE,GAAG,GACX,aAAa,CAAC,OAAO,CAAC,CAexB"}
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+ // PLY Loader, adapted from THREE.js (MIT license)
3
+ //
4
+ // Attributions per original THREE.js source file:
5
+ //
6
+ // @author Wei Meng / http://about.me/menway
7
+ //
8
+ // Description: A loader for PLY ASCII files (known as the Polygon File Format
9
+ // or the Stanford Triangle Format).
10
+ //
11
+ // Limitations: ASCII decoding assumes file is UTF-8.
12
+ //
13
+ // If the PLY file uses non standard property names, they can be mapped while
14
+ // loading. For example, the following maps the properties
15
+ // “diffuse_(red|green|blue)” in the file to standard color names.
16
+ //
17
+ // parsePLY(data, {
18
+ // propertyNameMapping: {
19
+ // diffuse_red: 'red',
20
+ // diffuse_green: 'green',
21
+ // diffuse_blue: 'blue'
22
+ // }
23
+ // });
24
+ // @ts-nocheck
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const core_1 = require("@loaders.gl/core");
30
+ const normalize_ply_1 = __importDefault(require("./normalize-ply"));
31
+ let currentElement;
32
+ /**
33
+ * PARSER
34
+ * @param iterator
35
+ * @param options
36
+ */
37
+ async function* parsePLYInBatches(iterator, options) {
38
+ const lineIterator = (0, core_1.makeLineIterator)((0, core_1.makeTextDecoderIterator)(iterator));
39
+ const header = await parsePLYHeader(lineIterator, options);
40
+ let attributes;
41
+ switch (header.format) {
42
+ case 'ascii':
43
+ attributes = await parseASCII(lineIterator, header);
44
+ break;
45
+ default:
46
+ throw new Error('Binary PLY can not yet be parsed in streaming mode');
47
+ // attributes = await parseBinary(lineIterator, header);
48
+ }
49
+ yield (0, normalize_ply_1.default)(header, attributes, options);
50
+ }
51
+ exports.default = parsePLYInBatches;
52
+ /**
53
+ * Parses header
54
+ * @param lineIterator
55
+ * @param options
56
+ * @returns
57
+ */
58
+ async function parsePLYHeader(lineIterator, options) {
59
+ const header = {
60
+ comments: [],
61
+ elements: []
62
+ // headerLength
63
+ };
64
+ // Note: forEach does not reset iterator if exiting loop prematurely
65
+ // so that iteration can continue in a second loop
66
+ await (0, core_1.forEach)(lineIterator, (line) => {
67
+ line = line.trim();
68
+ // End of header
69
+ if (line === 'end_header') {
70
+ return true; // Returning true cancels `forEach`
71
+ }
72
+ // Ignore empty lines
73
+ if (line === '') {
74
+ // eslint-disable-next-line
75
+ return false; // Returning false does not cancel `forEach`
76
+ }
77
+ const lineValues = line.split(/\s+/);
78
+ const lineType = lineValues.shift();
79
+ line = lineValues.join(' ');
80
+ switch (lineType) {
81
+ case 'ply':
82
+ // First line magic characters, ignore
83
+ break;
84
+ case 'format':
85
+ header.format = lineValues[0];
86
+ header.version = lineValues[1];
87
+ break;
88
+ case 'comment':
89
+ header.comments.push(line);
90
+ break;
91
+ case 'element':
92
+ if (currentElement) {
93
+ header.elements.push(currentElement);
94
+ }
95
+ currentElement = {
96
+ name: lineValues[0],
97
+ count: parseInt(lineValues[1], 10),
98
+ properties: []
99
+ };
100
+ break;
101
+ case 'property':
102
+ const property = makePLYElementProperty(lineValues, options.propertyNameMapping);
103
+ currentElement.properties.push(property);
104
+ break;
105
+ default:
106
+ // eslint-disable-next-line
107
+ console.log('unhandled', lineType, lineValues);
108
+ }
109
+ return false;
110
+ });
111
+ if (currentElement) {
112
+ header.elements.push(currentElement);
113
+ }
114
+ return header;
115
+ }
116
+ function makePLYElementProperty(propertValues, propertyNameMapping) {
117
+ const property = {
118
+ type: propertValues[0]
119
+ };
120
+ if (property.type === 'list') {
121
+ property.name = propertValues[3];
122
+ property.countType = propertValues[1];
123
+ property.itemType = propertValues[2];
124
+ }
125
+ else {
126
+ property.name = propertValues[1];
127
+ }
128
+ if (propertyNameMapping && property.name in propertyNameMapping) {
129
+ property.name = propertyNameMapping[property.name];
130
+ }
131
+ return property;
132
+ }
133
+ // ASCII PARSING
134
+ /**
135
+ * @param lineIterator
136
+ * @param header
137
+ * @returns
138
+ */
139
+ async function parseASCII(lineIterator, header) {
140
+ // PLY ascii format specification, as per http://en.wikipedia.org/wiki/PLY_(file_format)
141
+ const attributes = {
142
+ indices: [],
143
+ vertices: [],
144
+ normals: [],
145
+ uvs: [],
146
+ colors: []
147
+ };
148
+ let currentElement = 0;
149
+ let currentElementCount = 0;
150
+ for await (let line of lineIterator) {
151
+ line = line.trim();
152
+ if (line !== '') {
153
+ if (currentElementCount >= header.elements[currentElement].count) {
154
+ currentElement++;
155
+ currentElementCount = 0;
156
+ }
157
+ const element = parseASCIIElement(header.elements[currentElement].properties, line);
158
+ handleElement(attributes, header.elements[currentElement].name, element);
159
+ currentElementCount++;
160
+ }
161
+ }
162
+ return attributes;
163
+ }
164
+ /**
165
+ * Parses ASCII number
166
+ * @param n
167
+ * @param type
168
+ * @returns ASCII number
169
+ */
170
+ // eslint-disable-next-line complexity
171
+ function parseASCIINumber(n, type) {
172
+ switch (type) {
173
+ case 'char':
174
+ case 'uchar':
175
+ case 'short':
176
+ case 'ushort':
177
+ case 'int':
178
+ case 'uint':
179
+ case 'int8':
180
+ case 'uint8':
181
+ case 'int16':
182
+ case 'uint16':
183
+ case 'int32':
184
+ case 'uint32':
185
+ return parseInt(n, 10);
186
+ case 'float':
187
+ case 'double':
188
+ case 'float32':
189
+ case 'float64':
190
+ return parseFloat(n);
191
+ default:
192
+ throw new Error(type);
193
+ }
194
+ }
195
+ /**
196
+ * Parses ASCII element
197
+ * @param properties
198
+ * @param line
199
+ * @returns element
200
+ */
201
+ function parseASCIIElement(properties, line) {
202
+ const values = line.split(/\s+/);
203
+ const element = {};
204
+ for (let i = 0; i < properties.length; i++) {
205
+ if (properties[i].type === 'list') {
206
+ const list = [];
207
+ const n = parseASCIINumber(values.shift(), properties[i].countType);
208
+ for (let j = 0; j < n; j++) {
209
+ list.push(parseASCIINumber(values.shift(), properties[i].itemType));
210
+ }
211
+ element[properties[i].name] = list;
212
+ }
213
+ else {
214
+ element[properties[i].name] = parseASCIINumber(values.shift(), properties[i].type);
215
+ }
216
+ }
217
+ return element;
218
+ }
219
+ /**
220
+ * @param buffer
221
+ * @param elementName
222
+ * @param element
223
+ */
224
+ // HELPER FUNCTIONS
225
+ // eslint-disable-next-line complexity
226
+ function handleElement(buffer, elementName, element = {}) {
227
+ switch (elementName) {
228
+ case 'vertex':
229
+ buffer.vertices.push(element.x, element.y, element.z);
230
+ if ('nx' in element && 'ny' in element && 'nz' in element) {
231
+ buffer.normals.push(element.nx, element.ny, element.nz);
232
+ }
233
+ if ('s' in element && 't' in element) {
234
+ buffer.uvs.push(element.s, element.t);
235
+ }
236
+ if ('red' in element && 'green' in element && 'blue' in element) {
237
+ buffer.colors.push(element.red / 255.0, element.green / 255.0, element.blue / 255.0);
238
+ }
239
+ break;
240
+ case 'face':
241
+ const vertexIndices = element.vertex_indices || element.vertex_index; // issue #9338
242
+ if (vertexIndices.length === 3) {
243
+ buffer.indices.push(vertexIndices[0], vertexIndices[1], vertexIndices[2]);
244
+ }
245
+ else if (vertexIndices.length === 4) {
246
+ buffer.indices.push(vertexIndices[0], vertexIndices[1], vertexIndices[3]);
247
+ buffer.indices.push(vertexIndices[1], vertexIndices[2], vertexIndices[3]);
248
+ }
249
+ break;
250
+ default:
251
+ break;
252
+ }
253
+ }
@@ -0,0 +1,8 @@
1
+ import type { PLYMesh } from './ply-types';
2
+ /**
3
+ * @param data
4
+ * @param options
5
+ * @returns
6
+ */
7
+ export default function parsePLY(data: ArrayBuffer | string, options?: {}): PLYMesh;
8
+ //# sourceMappingURL=parse-ply.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-ply.d.ts","sourceRoot":"","sources":["../../src/lib/parse-ply.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EACV,OAAO,EAMR,MAAM,aAAa,CAAC;AAGrB;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,EAAE,OAAO,KAAK,GAAG,OAAO,CAclF"}
@@ -0,0 +1,350 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const normalize_ply_1 = __importDefault(require("./normalize-ply"));
7
+ /**
8
+ * @param data
9
+ * @param options
10
+ * @returns
11
+ */
12
+ function parsePLY(data, options = {}) {
13
+ let header;
14
+ let attributes;
15
+ if (data instanceof ArrayBuffer) {
16
+ const text = new TextDecoder().decode(data);
17
+ header = parseHeader(text, options);
18
+ attributes = header.format === 'ascii' ? parseASCII(text, header) : parseBinary(data, header);
19
+ }
20
+ else {
21
+ header = parseHeader(data, options);
22
+ attributes = parseASCII(data, header);
23
+ }
24
+ return (0, normalize_ply_1.default)(header, attributes);
25
+ }
26
+ exports.default = parsePLY;
27
+ /**
28
+ * @param data
29
+ * @param options
30
+ * @returns header
31
+ */
32
+ function parseHeader(data, options) {
33
+ const PLY_HEADER_PATTERN = /ply([\s\S]*)end_header\s/;
34
+ let headerText = '';
35
+ let headerLength = 0;
36
+ const result = PLY_HEADER_PATTERN.exec(data);
37
+ if (result !== null) {
38
+ headerText = result[1];
39
+ headerLength = result[0].length;
40
+ }
41
+ const lines = headerText.split('\n');
42
+ const header = parseHeaderLines(lines, headerLength, options);
43
+ return header;
44
+ }
45
+ /**
46
+ * @param lines
47
+ * @param headerLength
48
+ * @param options
49
+ * @returns header
50
+ */
51
+ function parseHeaderLines(lines, headerLength, options) {
52
+ const header = {
53
+ comments: [],
54
+ elements: [],
55
+ headerLength
56
+ };
57
+ let lineType;
58
+ let lineValues;
59
+ let currentElement = null;
60
+ for (let i = 0; i < lines.length; i++) {
61
+ let line = lines[i];
62
+ line = line.trim();
63
+ if (line === '') {
64
+ // eslint-disable-next-line
65
+ continue;
66
+ }
67
+ lineValues = line.split(/\s+/);
68
+ lineType = lineValues.shift();
69
+ line = lineValues.join(' ');
70
+ switch (lineType) {
71
+ case 'format':
72
+ header.format = lineValues[0];
73
+ header.version = lineValues[1];
74
+ break;
75
+ case 'comment':
76
+ header.comments.push(line);
77
+ break;
78
+ case 'element':
79
+ if (currentElement) {
80
+ header.elements.push(currentElement);
81
+ }
82
+ currentElement = {
83
+ name: lineValues[0],
84
+ count: parseInt(lineValues[1], 10),
85
+ properties: []
86
+ };
87
+ break;
88
+ case 'property':
89
+ if (!currentElement) {
90
+ break;
91
+ }
92
+ currentElement.properties.push(makePLYElementProperty(lineValues, options.propertyNameMapping));
93
+ break;
94
+ default:
95
+ // eslint-disable-next-line
96
+ console.log('unhandled', lineType, lineValues);
97
+ }
98
+ }
99
+ if (currentElement !== undefined) {
100
+ header.elements.push(currentElement);
101
+ }
102
+ return header;
103
+ }
104
+ /**
105
+ * @param propertValues
106
+ * @param propertyNameMapping
107
+ * @returns property of ply element
108
+ */
109
+ function makePLYElementProperty(propertValues, propertyNameMapping) {
110
+ const property = {
111
+ type: propertValues[0]
112
+ };
113
+ if (property.type === 'list') {
114
+ property.name = propertValues[3];
115
+ property.countType = propertValues[1];
116
+ property.itemType = propertValues[2];
117
+ }
118
+ else {
119
+ property.name = propertValues[1];
120
+ }
121
+ if (propertyNameMapping && property.name in propertyNameMapping) {
122
+ property.name = propertyNameMapping[property.name];
123
+ }
124
+ return property;
125
+ }
126
+ /**
127
+ * Parses ASCII number
128
+ * @param n
129
+ * @param type
130
+ * @returns
131
+ */
132
+ // eslint-disable-next-line complexity
133
+ function parseASCIINumber(n, type) {
134
+ switch (type) {
135
+ case 'char':
136
+ case 'uchar':
137
+ case 'short':
138
+ case 'ushort':
139
+ case 'int':
140
+ case 'uint':
141
+ case 'int8':
142
+ case 'uint8':
143
+ case 'int16':
144
+ case 'uint16':
145
+ case 'int32':
146
+ case 'uint32':
147
+ return parseInt(n, 10);
148
+ case 'float':
149
+ case 'double':
150
+ case 'float32':
151
+ case 'float64':
152
+ return parseFloat(n);
153
+ default:
154
+ throw new Error(type);
155
+ }
156
+ }
157
+ /**
158
+ * @param properties
159
+ * @param line
160
+ * @returns ASCII element
161
+ */
162
+ function parseASCIIElement(properties, line) {
163
+ const values = line.split(/\s+/);
164
+ const element = {};
165
+ for (let i = 0; i < properties.length; i++) {
166
+ if (properties[i].type === 'list') {
167
+ const list = [];
168
+ const n = parseASCIINumber(values.shift(), properties[i].countType);
169
+ for (let j = 0; j < n; j++) {
170
+ list.push(parseASCIINumber(values.shift(), properties[i].itemType));
171
+ }
172
+ element[properties[i].name] = list;
173
+ }
174
+ else {
175
+ element[properties[i].name] = parseASCIINumber(values.shift(), properties[i].type);
176
+ }
177
+ }
178
+ return element;
179
+ }
180
+ /**
181
+ * @param data
182
+ * @param header
183
+ * @returns [attributes]
184
+ */
185
+ function parseASCII(data, header) {
186
+ // PLY ascii format specification, as per http://en.wikipedia.org/wiki/PLY_(file_format)
187
+ const attributes = {
188
+ indices: [],
189
+ vertices: [],
190
+ normals: [],
191
+ uvs: [],
192
+ colors: []
193
+ };
194
+ let result;
195
+ const patternBody = /end_header\s([\s\S]*)$/;
196
+ let body = '';
197
+ if ((result = patternBody.exec(data)) !== null) {
198
+ body = result[1];
199
+ }
200
+ const lines = body.split('\n');
201
+ let currentElement = 0;
202
+ let currentElementCount = 0;
203
+ for (let i = 0; i < lines.length; i++) {
204
+ let line = lines[i];
205
+ line = line.trim();
206
+ if (line !== '') {
207
+ if (currentElementCount >= header.elements[currentElement].count) {
208
+ currentElement++;
209
+ currentElementCount = 0;
210
+ }
211
+ const element = parseASCIIElement(header.elements[currentElement].properties, line);
212
+ handleElement(attributes, header.elements[currentElement].name, element);
213
+ currentElementCount++;
214
+ }
215
+ }
216
+ return attributes;
217
+ }
218
+ /**
219
+ * @param buffer
220
+ * @param elementName
221
+ * @param element
222
+ */
223
+ // eslint-disable-next-line complexity
224
+ function handleElement(buffer, elementName, element = {}) {
225
+ if (elementName === 'vertex') {
226
+ buffer.vertices.push(element.x, element.y, element.z);
227
+ if ('nx' in element && 'ny' in element && 'nz' in element) {
228
+ buffer.normals.push(element.nx, element.ny, element.nz);
229
+ }
230
+ if ('s' in element && 't' in element) {
231
+ buffer.uvs.push(element.s, element.t);
232
+ }
233
+ if ('red' in element && 'green' in element && 'blue' in element) {
234
+ buffer.colors.push(element.red, element.green, element.blue);
235
+ }
236
+ }
237
+ else if (elementName === 'face') {
238
+ const vertexIndices = element.vertex_indices || element.vertex_index; // issue #9338
239
+ if (vertexIndices.length === 3) {
240
+ buffer.indices.push(vertexIndices[0], vertexIndices[1], vertexIndices[2]);
241
+ }
242
+ else if (vertexIndices.length === 4) {
243
+ buffer.indices.push(vertexIndices[0], vertexIndices[1], vertexIndices[3]);
244
+ buffer.indices.push(vertexIndices[1], vertexIndices[2], vertexIndices[3]);
245
+ }
246
+ }
247
+ }
248
+ /**
249
+ * Reads binary data
250
+ * @param dataview
251
+ * @param at
252
+ * @param type
253
+ * @param littleEndian
254
+ * @returns [number, number]
255
+ */
256
+ // eslint-disable-next-line complexity
257
+ function binaryRead(dataview, at, type, littleEndian) {
258
+ switch (type) {
259
+ // corespondences for non-specific length types here match rply:
260
+ case 'int8':
261
+ case 'char':
262
+ return [dataview.getInt8(at), 1];
263
+ case 'uint8':
264
+ case 'uchar':
265
+ return [dataview.getUint8(at), 1];
266
+ case 'int16':
267
+ case 'short':
268
+ return [dataview.getInt16(at, littleEndian), 2];
269
+ case 'uint16':
270
+ case 'ushort':
271
+ return [dataview.getUint16(at, littleEndian), 2];
272
+ case 'int32':
273
+ case 'int':
274
+ return [dataview.getInt32(at, littleEndian), 4];
275
+ case 'uint32':
276
+ case 'uint':
277
+ return [dataview.getUint32(at, littleEndian), 4];
278
+ case 'float32':
279
+ case 'float':
280
+ return [dataview.getFloat32(at, littleEndian), 4];
281
+ case 'float64':
282
+ case 'double':
283
+ return [dataview.getFloat64(at, littleEndian), 8];
284
+ default:
285
+ throw new Error(type);
286
+ }
287
+ }
288
+ /**
289
+ * Reads binary data
290
+ * @param dataview
291
+ * @param at
292
+ * @param properties
293
+ * @param littleEndian
294
+ * @returns [object, number]
295
+ */
296
+ function binaryReadElement(dataview, at, properties, littleEndian) {
297
+ const element = {};
298
+ let result;
299
+ let read = 0;
300
+ for (let i = 0; i < properties.length; i++) {
301
+ if (properties[i].type === 'list') {
302
+ const list = [];
303
+ result = binaryRead(dataview, at + read, properties[i].countType, littleEndian);
304
+ const n = result[0];
305
+ read += result[1];
306
+ for (let j = 0; j < n; j++) {
307
+ result = binaryRead(dataview, at + read, properties[i].itemType, littleEndian);
308
+ // @ts-ignore
309
+ list.push(result[0]);
310
+ read += result[1];
311
+ }
312
+ element[properties[i].name] = list;
313
+ }
314
+ else {
315
+ result = binaryRead(dataview, at + read, properties[i].type, littleEndian);
316
+ element[properties[i].name] = result[0];
317
+ read += result[1];
318
+ }
319
+ }
320
+ return [element, read];
321
+ }
322
+ /**
323
+ * Parses binary data
324
+ * @param data
325
+ * @param header
326
+ * @returns [attributes] of data
327
+ */
328
+ function parseBinary(data, header) {
329
+ const attributes = {
330
+ indices: [],
331
+ vertices: [],
332
+ normals: [],
333
+ uvs: [],
334
+ colors: []
335
+ };
336
+ const littleEndian = header.format === 'binary_little_endian';
337
+ const body = new DataView(data, header.headerLength);
338
+ let result;
339
+ let loc = 0;
340
+ for (let currentElement = 0; currentElement < header.elements.length; currentElement++) {
341
+ const count = header.elements[currentElement].count;
342
+ for (let currentElementCount = 0; currentElementCount < count; currentElementCount++) {
343
+ result = binaryReadElement(body, loc, header.elements[currentElement].properties, littleEndian);
344
+ loc += result[1];
345
+ const element = result[0];
346
+ handleElement(attributes, header.elements[currentElement].name, element);
347
+ }
348
+ }
349
+ return attributes;
350
+ }