@loaders.gl/ply 4.0.0-alpha.5 → 4.0.0-alpha.6

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 (74) hide show
  1. package/dist/bundle.js +2 -2
  2. package/dist/dist.min.js +201 -609
  3. package/dist/es5/bundle.js +6 -0
  4. package/dist/es5/bundle.js.map +1 -0
  5. package/dist/es5/index.js +51 -0
  6. package/dist/es5/index.js.map +1 -0
  7. package/dist/es5/lib/get-ply-schema.js +28 -0
  8. package/dist/es5/lib/get-ply-schema.js.map +1 -0
  9. package/dist/es5/lib/normalize-ply.js +93 -0
  10. package/dist/es5/lib/normalize-ply.js.map +1 -0
  11. package/dist/es5/lib/parse-ply-in-batches.js +289 -0
  12. package/dist/es5/lib/parse-ply-in-batches.js.map +1 -0
  13. package/dist/es5/lib/parse-ply.js +348 -0
  14. package/dist/es5/lib/parse-ply.js.map +1 -0
  15. package/dist/es5/lib/ply-types.js +2 -0
  16. package/dist/es5/lib/ply-types.js.map +1 -0
  17. package/dist/es5/ply-loader.js +26 -0
  18. package/dist/es5/ply-loader.js.map +1 -0
  19. package/dist/es5/workers/ply-worker.js +6 -0
  20. package/dist/es5/workers/ply-worker.js.map +1 -0
  21. package/dist/esm/bundle.js +4 -0
  22. package/dist/esm/bundle.js.map +1 -0
  23. package/dist/esm/index.js +12 -0
  24. package/dist/esm/index.js.map +1 -0
  25. package/dist/esm/lib/get-ply-schema.js +22 -0
  26. package/dist/esm/lib/get-ply-schema.js.map +1 -0
  27. package/dist/esm/lib/normalize-ply.js +86 -0
  28. package/dist/esm/lib/normalize-ply.js.map +1 -0
  29. package/dist/esm/lib/parse-ply-in-batches.js +177 -0
  30. package/dist/esm/lib/parse-ply-in-batches.js.map +1 -0
  31. package/dist/esm/lib/parse-ply.js +319 -0
  32. package/dist/esm/lib/parse-ply.js.map +1 -0
  33. package/dist/esm/lib/ply-types.js +2 -0
  34. package/dist/esm/lib/ply-types.js.map +1 -0
  35. package/dist/esm/ply-loader.js +18 -0
  36. package/dist/esm/ply-loader.js.map +1 -0
  37. package/dist/esm/workers/ply-worker.js +4 -0
  38. package/dist/esm/workers/ply-worker.js.map +1 -0
  39. package/dist/index.d.ts +7 -24
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +18 -11
  42. package/dist/lib/get-ply-schema.js +34 -24
  43. package/dist/lib/normalize-ply.js +76 -65
  44. package/dist/lib/parse-ply-in-batches.d.ts +1 -1
  45. package/dist/lib/parse-ply-in-batches.d.ts.map +1 -1
  46. package/dist/lib/parse-ply-in-batches.js +237 -202
  47. package/dist/lib/parse-ply.d.ts +4 -1
  48. package/dist/lib/parse-ply.d.ts.map +1 -1
  49. package/dist/lib/parse-ply.js +378 -299
  50. package/dist/lib/ply-types.d.ts +22 -14
  51. package/dist/lib/ply-types.d.ts.map +1 -1
  52. package/dist/lib/ply-types.js +2 -2
  53. package/dist/ply-loader.d.ts +3 -17
  54. package/dist/ply-loader.d.ts.map +1 -1
  55. package/dist/ply-loader.js +27 -18
  56. package/dist/ply-worker.js +240 -578
  57. package/dist/workers/ply-worker.js +5 -4
  58. package/package.json +6 -6
  59. package/src/index.ts +15 -10
  60. package/src/lib/get-ply-schema.ts +11 -10
  61. package/src/lib/normalize-ply.ts +34 -12
  62. package/src/lib/parse-ply-in-batches.ts +20 -22
  63. package/src/lib/parse-ply.ts +114 -55
  64. package/src/lib/ply-types.ts +21 -12
  65. package/src/ply-loader.ts +4 -3
  66. package/dist/bundle.js.map +0 -1
  67. package/dist/index.js.map +0 -1
  68. package/dist/lib/get-ply-schema.js.map +0 -1
  69. package/dist/lib/normalize-ply.js.map +0 -1
  70. package/dist/lib/parse-ply-in-batches.js.map +0 -1
  71. package/dist/lib/parse-ply.js.map +0 -1
  72. package/dist/lib/ply-types.js.map +0 -1
  73. package/dist/ply-loader.js.map +0 -1
  74. package/dist/workers/ply-worker.js.map +0 -1
@@ -1,4 +1,5 @@
1
- import { createLoaderWorker } from '@loaders.gl/loader-utils';
2
- import { PLYLoader } from '../index';
3
- createLoaderWorker(PLYLoader);
4
- //# sourceMappingURL=ply-worker.js.map
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const loader_utils_1 = require("@loaders.gl/loader-utils");
4
+ const index_1 = require("../index");
5
+ (0, loader_utils_1.createLoaderWorker)(index_1.PLYLoader);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loaders.gl/ply",
3
- "version": "4.0.0-alpha.5",
3
+ "version": "4.0.0-alpha.6",
4
4
  "description": "Framework-independent loader for the PLY format",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -19,8 +19,8 @@
19
19
  "PLY"
20
20
  ],
21
21
  "types": "dist/index.d.ts",
22
- "main": "dist/index.js",
23
- "module": "dist/index.js",
22
+ "main": "dist/es5/index.js",
23
+ "module": "dist/esm/index.js",
24
24
  "sideEffects": false,
25
25
  "files": [
26
26
  "src",
@@ -34,8 +34,8 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@babel/runtime": "^7.3.1",
37
- "@loaders.gl/loader-utils": "4.0.0-alpha.5",
38
- "@loaders.gl/schema": "4.0.0-alpha.5"
37
+ "@loaders.gl/loader-utils": "4.0.0-alpha.6",
38
+ "@loaders.gl/schema": "4.0.0-alpha.6"
39
39
  },
40
- "gitHead": "7a71a54bdf1ddf985cc3af3db90b82e7fa97d025"
40
+ "gitHead": "acc1985050dfaa0f1f0c066f8da5bce7454a046c"
41
41
  }
package/src/index.ts CHANGED
@@ -1,22 +1,27 @@
1
- import type {LoaderWithParser} from '@loaders.gl/loader-utils';
1
+ // loaders.gl, MIT license
2
+
3
+ import type {LoaderOptions, LoaderWithParser} from '@loaders.gl/loader-utils';
4
+ import type {PLYMesh} from './lib/ply-types';
2
5
  import {PLYLoader as PLYWorkerLoader} from './ply-loader';
3
- import parsePLY from './lib/parse-ply';
4
- import parsePLYInBatches from './lib/parse-ply-in-batches';
6
+ import {ParsePLYOptions, parsePLY} from './lib/parse-ply';
7
+ import {parsePLYInBatches} from './lib/parse-ply-in-batches';
5
8
 
6
9
  // PLYLoader
7
10
 
8
11
  export {PLYWorkerLoader};
9
12
 
13
+ export type PLYLoaderOptions = LoaderOptions & {
14
+ ply?: ParsePLYOptions;
15
+ };
16
+
10
17
  /**
11
18
  * Loader for PLY - Polygon File Format
12
19
  */
13
- export const PLYLoader = {
20
+ export const PLYLoader: LoaderWithParser<PLYMesh, any, PLYLoaderOptions> = {
14
21
  ...PLYWorkerLoader,
15
22
  // Note: parsePLY supports both text and binary
16
- parse: async (arrayBuffer, options) => parsePLY(arrayBuffer, options), // TODO - this may not detect text correctly?
17
- parseTextSync: parsePLY,
18
- parseSync: parsePLY,
19
- parseInBatches: parsePLYInBatches
23
+ parse: async (arrayBuffer, options) => parsePLY(arrayBuffer, options?.ply), // TODO - this may not detect text correctly?
24
+ parseTextSync: (arrayBuffer, options) => parsePLY(arrayBuffer, options?.ply),
25
+ parseSync: (arrayBuffer, options) => parsePLY(arrayBuffer, options?.ply),
26
+ parseInBatches: (arrayBuffer, options) => parsePLYInBatches(arrayBuffer, options?.ply)
20
27
  };
21
-
22
- export const _typecheckPLYLoader: LoaderWithParser = PLYLoader;
@@ -8,8 +8,8 @@ import type {PLYHeader} from './ply-types';
8
8
  * @returns Schema
9
9
  */
10
10
  export function getPLYSchema(plyHeader: PLYHeader, attributes: MeshAttributes): Schema {
11
- const metadataMap = makeMetadataFromPlyHeader(plyHeader);
12
- const schema = deduceMeshSchema(attributes, metadataMap);
11
+ const metadata = makeMetadataFromPlyHeader(plyHeader);
12
+ const schema = deduceMeshSchema(attributes, metadata);
13
13
  return schema;
14
14
  }
15
15
 
@@ -18,18 +18,19 @@ export function getPLYSchema(plyHeader: PLYHeader, attributes: MeshAttributes):
18
18
  * @param plyHeader
19
19
  * @returns
20
20
  */
21
- function makeMetadataFromPlyHeader(plyHeader: PLYHeader): Map<string, string> {
22
- const metadataMap = new Map();
23
- metadataMap.set('ply_comments', JSON.stringify(plyHeader.comments));
24
- metadataMap.set('ply_elements', JSON.stringify(plyHeader.elements));
21
+ function makeMetadataFromPlyHeader(plyHeader: PLYHeader): Record<string, string> {
22
+ /* eslint-disable camelcase */
23
+ const metadata: Record<string, string> = {};
24
+ metadata.ply_comments = JSON.stringify(plyHeader.comments);
25
+ metadata.ply_elements = JSON.stringify(plyHeader.elements);
25
26
  if (plyHeader.format !== undefined) {
26
- metadataMap.set('ply_format', plyHeader.format);
27
+ metadata.ply_format = plyHeader.format;
27
28
  }
28
29
  if (plyHeader.version !== undefined) {
29
- metadataMap.set('ply_version', plyHeader.version);
30
+ metadata.ply_version = plyHeader.version;
30
31
  }
31
32
  if (plyHeader.headerLength !== undefined) {
32
- metadataMap.set('ply_headerLength', plyHeader.headerLength.toString(10));
33
+ metadata.ply_headerLength = plyHeader.headerLength.toString(10);
33
34
  }
34
- return metadataMap;
35
+ return metadata;
35
36
  }
@@ -50,25 +50,47 @@ export default function normalizePLY(
50
50
  * @param attributes
51
51
  * @returns accessors []
52
52
  */
53
+ // eslint-disable-next-line complexity
53
54
  function getMeshAttributes(attributes: PLYAttributes): MeshAttributes {
54
55
  const accessors: MeshAttributes = {};
55
56
 
56
- accessors.POSITION = {value: new Float32Array(attributes.vertices), size: 3};
57
+ for (const attributeName of Object.keys(attributes)) {
58
+ switch (attributeName) {
59
+ case 'vertices':
60
+ if (attributes.vertices.length > 0) {
61
+ accessors.POSITION = {value: new Float32Array(attributes.vertices), size: 3};
62
+ }
63
+ break;
57
64
 
58
- // optional attributes data
65
+ // optional attributes data
66
+ case 'normals':
67
+ if (attributes.normals.length > 0) {
68
+ accessors.NORMAL = {value: new Float32Array(attributes.normals), size: 3};
69
+ }
70
+ break;
59
71
 
60
- if (attributes.normals.length > 0) {
61
- accessors.NORMAL = {value: new Float32Array(attributes.normals), size: 3};
62
- }
72
+ case 'uvs':
73
+ if (attributes.uvs.length > 0) {
74
+ accessors.TEXCOORD_0 = {value: new Float32Array(attributes.uvs), size: 2};
75
+ }
76
+ break;
63
77
 
64
- if (attributes.uvs.length > 0) {
65
- accessors.TEXCOORD_0 = {value: new Float32Array(attributes.uvs), size: 2};
66
- }
78
+ case 'colors':
79
+ if (attributes.colors.length > 0) {
80
+ // TODO - normalized shoud be based on `uchar` flag in source data?
81
+ accessors.COLOR_0 = {value: new Uint8Array(attributes.colors), size: 3, normalized: true};
82
+ }
83
+ break;
67
84
 
68
- if (attributes.colors.length > 0) {
69
- // TODO - normalized shoud be based on `uchar` flag in source data?
70
- accessors.COLOR_0 = {value: new Uint8Array(attributes.colors), size: 3, normalized: true};
71
- }
85
+ case 'indices':
86
+ break;
72
87
 
88
+ default:
89
+ if (attributes[attributeName].length > 0) {
90
+ accessors[attributeName] = {value: new Float32Array(attributes[attributeName]), size: 1};
91
+ }
92
+ break;
93
+ }
94
+ }
73
95
  return accessors;
74
96
  }
@@ -23,16 +23,16 @@
23
23
 
24
24
  import {makeLineIterator, makeTextDecoderIterator, forEach} from '@loaders.gl/loader-utils';
25
25
  import normalizePLY from './normalize-ply';
26
- import {PLYMesh, PLYHeader, ASCIIElement, PLYAttributes} from './ply-types';
26
+ import {PLYMesh, PLYHeader, PLYElement, PLYProperty, PLYAttributes} from './ply-types';
27
27
 
28
- let currentElement: ASCIIElement;
28
+ let currentElement: PLYElement;
29
29
 
30
30
  /**
31
31
  * PARSER
32
32
  * @param iterator
33
33
  * @param options
34
34
  */
35
- export default async function* parsePLYInBatches(
35
+ export async function* parsePLYInBatches(
36
36
  iterator: AsyncIterable<ArrayBuffer> | Iterable<ArrayBuffer>,
37
37
  options: any
38
38
  ): AsyncIterable<PLYMesh> {
@@ -134,24 +134,22 @@ async function parsePLYHeader(
134
134
  return header;
135
135
  }
136
136
 
137
- function makePLYElementProperty(propertValues: string[], propertyNameMapping: []) {
138
- const property: {[index: string]: string} = {
139
- type: propertValues[0]
140
- };
141
-
142
- if (property.type === 'list') {
143
- property.name = propertValues[3];
144
- property.countType = propertValues[1];
145
- property.itemType = propertValues[2];
146
- } else {
147
- property.name = propertValues[1];
148
- }
149
-
150
- if (propertyNameMapping && property.name in propertyNameMapping) {
151
- property.name = propertyNameMapping[property.name];
137
+ function makePLYElementProperty(propertyValues: string[], propertyNameMapping: []): PLYProperty {
138
+ const type = propertyValues[0];
139
+ switch (type) {
140
+ case 'list':
141
+ return {
142
+ type,
143
+ name: propertyValues[3],
144
+ countType: propertyValues[1],
145
+ itemType: propertyValues[2]
146
+ };
147
+ default:
148
+ return {
149
+ type,
150
+ name: propertyValues[1]
151
+ };
152
152
  }
153
-
154
- return property;
155
153
  }
156
154
 
157
155
  // ASCII PARSING
@@ -182,7 +180,7 @@ async function parseASCII(lineIterator: AsyncIterable<string>, header: PLYHeader
182
180
  currentElementCount = 0;
183
181
  }
184
182
 
185
- const element = parseASCIIElement(header.elements[currentElement].properties, line);
183
+ const element = parsePLYElement(header.elements[currentElement].properties, line);
186
184
  handleElement(attributes, header.elements[currentElement].name, element);
187
185
  currentElementCount++;
188
186
  }
@@ -229,7 +227,7 @@ function parseASCIINumber(n: string, type: string): number {
229
227
  * @param line
230
228
  * @returns element
231
229
  */
232
- function parseASCIIElement(properties: any[], line: string) {
230
+ function parsePLYElement(properties: any[], line: string) {
233
231
  const values: any = line.split(/\s+/);
234
232
 
235
233
  const element = {};
@@ -25,17 +25,21 @@ import type {
25
25
  PLYHeader,
26
26
  PLYAttributes,
27
27
  MeshHeader,
28
- ASCIIElement,
28
+ PLYElement,
29
29
  PLYProperty
30
30
  } from './ply-types';
31
31
  import normalizePLY from './normalize-ply';
32
32
 
33
+ export type ParsePLYOptions = {
34
+ propertyNameMapping?: Record<string, string>;
35
+ };
36
+
33
37
  /**
34
38
  * @param data
35
39
  * @param options
36
40
  * @returns
37
41
  */
38
- export default function parsePLY(data: ArrayBuffer | string, options = {}): PLYMesh {
42
+ export function parsePLY(data: ArrayBuffer | string, options: ParsePLYOptions = {}): PLYMesh {
39
43
  let header: PLYHeader & MeshHeader;
40
44
  let attributes: PLYAttributes;
41
45
 
@@ -56,7 +60,7 @@ export default function parsePLY(data: ArrayBuffer | string, options = {}): PLYM
56
60
  * @param options
57
61
  * @returns header
58
62
  */
59
- function parseHeader(data: any, options: {[index: string]: any}): PLYHeader {
63
+ function parseHeader(data: any, options?: ParsePLYOptions): PLYHeader {
60
64
  const PLY_HEADER_PATTERN = /ply([\s\S]*)end_header\s/;
61
65
 
62
66
  let headerText = '';
@@ -80,10 +84,11 @@ function parseHeader(data: any, options: {[index: string]: any}): PLYHeader {
80
84
  * @param options
81
85
  * @returns header
82
86
  */
87
+ // eslint-disable-next-line complexity
83
88
  function parseHeaderLines(
84
89
  lines: string[],
85
90
  headerLength: number,
86
- options: {[index: string]: any}
91
+ options?: ParsePLYOptions
87
92
  ): PLYHeader {
88
93
  const header: PLYHeader = {
89
94
  comments: [],
@@ -93,7 +98,7 @@ function parseHeaderLines(
93
98
 
94
99
  let lineType: string | undefined;
95
100
  let lineValues: string[];
96
- let currentElement: ASCIIElement | null = null;
101
+ let currentElement: PLYElement | null = null;
97
102
 
98
103
  for (let i = 0; i < lines.length; i++) {
99
104
  let line: string = lines[i];
@@ -119,6 +124,7 @@ function parseHeaderLines(
119
124
  break;
120
125
 
121
126
  case 'element':
127
+ // Start new element, store previous element
122
128
  if (currentElement) {
123
129
  header.elements.push(currentElement);
124
130
  }
@@ -131,12 +137,13 @@ function parseHeaderLines(
131
137
  break;
132
138
 
133
139
  case 'property':
134
- if (!currentElement) {
135
- break;
140
+ if (currentElement) {
141
+ const property = makePLYElementProperty(lineValues);
142
+ if (options?.propertyNameMapping && property.name in options?.propertyNameMapping) {
143
+ property.name = options?.propertyNameMapping[property.name];
144
+ }
145
+ currentElement.properties.push(property);
136
146
  }
137
- currentElement.properties.push(
138
- makePLYElementProperty(lineValues, options.propertyNameMapping)
139
- );
140
147
  break;
141
148
 
142
149
  default:
@@ -145,36 +152,74 @@ function parseHeaderLines(
145
152
  }
146
153
  }
147
154
 
148
- if (currentElement !== undefined) {
155
+ // Store in-progress element
156
+ if (currentElement) {
149
157
  header.elements.push(currentElement);
150
158
  }
151
159
 
152
160
  return header;
153
161
  }
154
162
 
155
- /**
156
- * @param propertValues
157
- * @param propertyNameMapping
158
- * @returns property of ply element
159
- */
160
- function makePLYElementProperty(propertValues: string[], propertyNameMapping: []): PLYProperty {
161
- const property: PLYProperty = {
162
- type: propertValues[0]
163
+ /** Generate attributes arrays from the header */
164
+ // eslint-disable-next-line complexity
165
+ function getPLYAttributes(header: PLYHeader): PLYAttributes {
166
+ // TODO Generate only the attribute arrays actually in the header
167
+ const attributes = {
168
+ indices: [],
169
+ vertices: [],
170
+ normals: [],
171
+ uvs: [],
172
+ colors: []
163
173
  };
164
174
 
165
- if (property.type === 'list') {
166
- property.name = propertValues[3];
167
- property.countType = propertValues[1];
168
- property.itemType = propertValues[2];
169
- } else {
170
- property.name = propertValues[1];
175
+ for (const element of header.elements) {
176
+ if (element.name === 'vertex') {
177
+ for (const property of element.properties) {
178
+ switch (property.name) {
179
+ case 'x':
180
+ case 'y':
181
+ case 'z':
182
+ case 'nx':
183
+ case 'ny':
184
+ case 'nz':
185
+ case 's':
186
+ case 't':
187
+ case 'red':
188
+ case 'green':
189
+ case 'blue':
190
+ break;
191
+ default:
192
+ // Add any non-geometry attributes
193
+ attributes[property.name] = [];
194
+ break;
195
+ }
196
+ }
197
+ }
171
198
  }
172
199
 
173
- if (propertyNameMapping && property.name in propertyNameMapping) {
174
- property.name = propertyNameMapping[property.name];
175
- }
200
+ return attributes;
201
+ }
176
202
 
177
- return property;
203
+ /**
204
+ * @param propertyValues
205
+ * @returns property of ply element
206
+ */
207
+ function makePLYElementProperty(propertyValues: string[]): PLYProperty {
208
+ const type = propertyValues[0];
209
+ switch (type) {
210
+ case 'list':
211
+ return {
212
+ type,
213
+ name: propertyValues[3],
214
+ countType: propertyValues[1],
215
+ itemType: propertyValues[2]
216
+ };
217
+ default:
218
+ return {
219
+ type,
220
+ name: propertyValues[1]
221
+ };
222
+ }
178
223
  }
179
224
 
180
225
  /**
@@ -216,7 +261,7 @@ function parseASCIINumber(n: string, type: string): number {
216
261
  * @param line
217
262
  * @returns ASCII element
218
263
  */
219
- function parseASCIIElement(properties: any[], line: string) {
264
+ function parsePLYElement(properties: any[], line: string) {
220
265
  const values: any = line.split(/\s+/);
221
266
 
222
267
  const element = {};
@@ -247,13 +292,7 @@ function parseASCIIElement(properties: any[], line: string) {
247
292
  function parseASCII(data: any, header: PLYHeader): PLYAttributes {
248
293
  // PLY ascii format specification, as per http://en.wikipedia.org/wiki/PLY_(file_format)
249
294
 
250
- const attributes: PLYAttributes = {
251
- indices: [],
252
- vertices: [],
253
- normals: [],
254
- uvs: [],
255
- colors: []
256
- };
295
+ const attributes = getPLYAttributes(header);
257
296
 
258
297
  let result: RegExpExecArray | null;
259
298
 
@@ -277,7 +316,7 @@ function parseASCII(data: any, header: PLYHeader): PLYAttributes {
277
316
  currentElementCount = 0;
278
317
  }
279
318
 
280
- const element = parseASCIIElement(header.elements[currentElement].properties, line);
319
+ const element = parsePLYElement(header.elements[currentElement].properties, line);
281
320
  handleElement(attributes, header.elements[currentElement].name, element);
282
321
  currentElementCount++;
283
322
  }
@@ -298,18 +337,44 @@ function handleElement(
298
337
  element: any = {}
299
338
  ) {
300
339
  if (elementName === 'vertex') {
301
- buffer.vertices.push(element.x, element.y, element.z);
340
+ for (const propertyName of Object.keys(element)) {
341
+ switch (propertyName) {
342
+ case 'x':
343
+ buffer.vertices.push(element.x, element.y, element.z);
344
+ break;
345
+ case 'y':
346
+ case 'z':
347
+ break;
302
348
 
303
- if ('nx' in element && 'ny' in element && 'nz' in element) {
304
- buffer.normals.push(element.nx, element.ny, element.nz);
305
- }
349
+ case 'nx':
350
+ if ('nx' in element && 'ny' in element && 'nz' in element) {
351
+ buffer.normals.push(element.nx, element.ny, element.nz);
352
+ }
353
+ break;
354
+ case 'ny':
355
+ case 'nz':
356
+ break;
306
357
 
307
- if ('s' in element && 't' in element) {
308
- buffer.uvs.push(element.s, element.t);
309
- }
358
+ case 's':
359
+ if ('s' in element && 't' in element) {
360
+ buffer.uvs.push(element.s, element.t);
361
+ }
362
+ break;
363
+ case 't':
364
+ break;
365
+
366
+ case 'red':
367
+ if ('red' in element && 'green' in element && 'blue' in element) {
368
+ buffer.colors.push(element.red, element.green, element.blue);
369
+ }
370
+ break;
371
+ case 'green':
372
+ case 'blue':
373
+ break;
310
374
 
311
- if ('red' in element && 'green' in element && 'blue' in element) {
312
- buffer.colors.push(element.red, element.green, element.blue);
375
+ default:
376
+ buffer[propertyName].push(element[propertyName]);
377
+ }
313
378
  }
314
379
  } else if (elementName === 'face') {
315
380
  const vertexIndices = element.vertex_indices || element.vertex_index; // issue #9338
@@ -419,14 +484,8 @@ type BinaryAttributes = {
419
484
  * @param header
420
485
  * @returns [attributes] of data
421
486
  */
422
- function parseBinary(data: ArrayBuffer, header: {[index: string]: any}): BinaryAttributes {
423
- const attributes: BinaryAttributes = {
424
- indices: [],
425
- vertices: [],
426
- normals: [],
427
- uvs: [],
428
- colors: []
429
- };
487
+ function parseBinary(data: ArrayBuffer, header: PLYHeader): BinaryAttributes {
488
+ const attributes = getPLYAttributes(header);
430
489
 
431
490
  const littleEndian = header.format === 'binary_little_endian';
432
491
  const body = new DataView(data, header.headerLength);
@@ -1,36 +1,45 @@
1
+ // loaders.gl, MIT license
1
2
  import type {Mesh} from '@loaders.gl/schema';
2
3
 
4
+ /** A parsed PLY mesh */
5
+ export type PLYMesh = Mesh & {
6
+ loader: 'ply';
7
+ loaderData: PLYHeader;
8
+ };
9
+
10
+ /** A PLY header */
3
11
  export type PLYHeader = {
4
12
  format?: string;
5
13
  comments: string[];
6
- elements: any[];
14
+ elements: PLYElement[];
7
15
  version?: string;
8
16
  headerLength?: number;
9
17
  };
10
18
 
11
- /** A parsed PLY mesh */
12
- export type PLYMesh = Mesh & {
13
- loader: 'ply';
14
- loaderData: PLYHeader;
15
- };
16
-
17
19
  // INTERNAL TYPES
18
20
 
21
+ /** A general mesh header */
19
22
  export type MeshHeader = {
20
23
  vertexCount?: number;
21
24
  boundingBox?: [[number, number, number], [number, number, number]];
22
25
  };
23
26
 
27
+ /** The parsed columnar values */
24
28
  export type PLYAttributes = {
25
29
  [index: string]: number[];
26
30
  };
27
31
 
28
- export type PLYProperty = {
29
- [index: string]: string;
32
+ /** A top level PLY element (vertex, face, ...) */
33
+ export type PLYElement = {
34
+ name: string;
35
+ count: number;
36
+ properties: PLYProperty[];
30
37
  };
31
38
 
32
- export type ASCIIElement = {
39
+ /** One property in a top-level PLY element */
40
+ export type PLYProperty = {
33
41
  name: string;
34
- count: number;
35
- properties: any[];
42
+ type: string;
43
+ countType?: string;
44
+ itemType?: string;
36
45
  };
package/src/ply-loader.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  // PLY Loader
2
- import type {Loader} from '@loaders.gl/loader-utils';
2
+ import type {Loader, LoaderOptions} from '@loaders.gl/loader-utils';
3
+ import {PLYMesh} from './lib/ply-types';
3
4
 
4
5
  // __VERSION__ is injected by babel-plugin-version-inline
5
6
  // @ts-ignore TS2304: Cannot find name '__VERSION__'.
@@ -10,11 +11,11 @@ const VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'latest';
10
11
  * links: ['http://paulbourke.net/dataformats/ply/',
11
12
  * 'https://en.wikipedia.org/wiki/PLY_(file_format)']
12
13
  */
13
- export const PLYLoader = {
14
+ export const PLYLoader: Loader<PLYMesh, never, LoaderOptions> = {
14
15
  name: 'PLY',
15
16
  id: 'ply',
16
17
  module: 'ply',
17
- shapes: ['mesh', 'gltf', 'columnar-table'],
18
+ // shapes: ['mesh', 'gltf', 'columnar-table'],
18
19
  version: VERSION,
19
20
  worker: true,
20
21
  extensions: ['ply'],
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/bundle.ts"],"names":["moduleExports","require","globalThis","loaders","module","exports","Object","assign"],"mappings":"AACA,MAAMA,aAAa,GAAGC,OAAO,CAAC,SAAD,CAA7B;;AACAC,UAAU,CAACC,OAAX,GAAqBD,UAAU,CAACC,OAAX,IAAsB,EAA3C;AACAC,MAAM,CAACC,OAAP,GAAiBC,MAAM,CAACC,MAAP,CAAcL,UAAU,CAACC,OAAzB,EAAkCH,aAAlC,CAAjB","sourcesContent":["// @ts-nocheck\nconst moduleExports = require('./index');\nglobalThis.loaders = globalThis.loaders || {};\nmodule.exports = Object.assign(globalThis.loaders, moduleExports);\n"],"file":"bundle.js"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["PLYLoader","PLYWorkerLoader","parsePLY","parsePLYInBatches","parse","arrayBuffer","options","parseTextSync","parseSync","parseInBatches","_typecheckPLYLoader"],"mappings":"AACA,SAAQA,SAAS,IAAIC,eAArB,QAA2C,cAA3C;AACA,OAAOC,QAAP,MAAqB,iBAArB;AACA,OAAOC,iBAAP,MAA8B,4BAA9B;AAIA,SAAQF,eAAR;AAKA,OAAO,MAAMD,SAAS,GAAG,EACvB,GAAGC,eADoB;AAGvBG,EAAAA,KAAK,EAAE,OAAOC,WAAP,EAAoBC,OAApB,KAAgCJ,QAAQ,CAACG,WAAD,EAAcC,OAAd,CAHxB;AAIvBC,EAAAA,aAAa,EAAEL,QAJQ;AAKvBM,EAAAA,SAAS,EAAEN,QALY;AAMvBO,EAAAA,cAAc,EAAEN;AANO,CAAlB;AASP,OAAO,MAAMO,mBAAqC,GAAGV,SAA9C","sourcesContent":["import type {LoaderWithParser} from '@loaders.gl/loader-utils';\nimport {PLYLoader as PLYWorkerLoader} from './ply-loader';\nimport parsePLY from './lib/parse-ply';\nimport parsePLYInBatches from './lib/parse-ply-in-batches';\n\n// PLYLoader\n\nexport {PLYWorkerLoader};\n\n/**\n * Loader for PLY - Polygon File Format\n */\nexport const PLYLoader = {\n ...PLYWorkerLoader,\n // Note: parsePLY supports both text and binary\n parse: async (arrayBuffer, options) => parsePLY(arrayBuffer, options), // TODO - this may not detect text correctly?\n parseTextSync: parsePLY,\n parseSync: parsePLY,\n parseInBatches: parsePLYInBatches\n};\n\nexport const _typecheckPLYLoader: LoaderWithParser = PLYLoader;\n"],"file":"index.js"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/lib/get-ply-schema.ts"],"names":["deduceMeshSchema","getPLYSchema","plyHeader","attributes","metadataMap","makeMetadataFromPlyHeader","schema","Map","set","JSON","stringify","comments","elements","format","undefined","version","headerLength","toString"],"mappings":"AAAA,SAAgCA,gBAAhC,QAAuD,oBAAvD;AASA,OAAO,SAASC,YAAT,CAAsBC,SAAtB,EAA4CC,UAA5C,EAAgF;AACrF,QAAMC,WAAW,GAAGC,yBAAyB,CAACH,SAAD,CAA7C;AACA,QAAMI,MAAM,GAAGN,gBAAgB,CAACG,UAAD,EAAaC,WAAb,CAA/B;AACA,SAAOE,MAAP;AACD;;AAOD,SAASD,yBAAT,CAAmCH,SAAnC,EAA8E;AAC5E,QAAME,WAAW,GAAG,IAAIG,GAAJ,EAApB;AACAH,EAAAA,WAAW,CAACI,GAAZ,CAAgB,cAAhB,EAAgCC,IAAI,CAACC,SAAL,CAAeR,SAAS,CAACS,QAAzB,CAAhC;AACAP,EAAAA,WAAW,CAACI,GAAZ,CAAgB,cAAhB,EAAgCC,IAAI,CAACC,SAAL,CAAeR,SAAS,CAACU,QAAzB,CAAhC;;AACA,MAAIV,SAAS,CAACW,MAAV,KAAqBC,SAAzB,EAAoC;AAClCV,IAAAA,WAAW,CAACI,GAAZ,CAAgB,YAAhB,EAA8BN,SAAS,CAACW,MAAxC;AACD;;AACD,MAAIX,SAAS,CAACa,OAAV,KAAsBD,SAA1B,EAAqC;AACnCV,IAAAA,WAAW,CAACI,GAAZ,CAAgB,aAAhB,EAA+BN,SAAS,CAACa,OAAzC;AACD;;AACD,MAAIb,SAAS,CAACc,YAAV,KAA2BF,SAA/B,EAA0C;AACxCV,IAAAA,WAAW,CAACI,GAAZ,CAAgB,kBAAhB,EAAoCN,SAAS,CAACc,YAAV,CAAuBC,QAAvB,CAAgC,EAAhC,CAApC;AACD;;AACD,SAAOb,WAAP;AACD","sourcesContent":["import {Schema, MeshAttributes, deduceMeshSchema} from '@loaders.gl/schema';\nimport type {PLYHeader} from './ply-types';\n\n/**\n * Gets schema from PLY header\n * @param plyHeader\n * @param metadata\n * @returns Schema\n */\nexport function getPLYSchema(plyHeader: PLYHeader, attributes: MeshAttributes): Schema {\n const metadataMap = makeMetadataFromPlyHeader(plyHeader);\n const schema = deduceMeshSchema(attributes, metadataMap);\n return schema;\n}\n\n/**\n * Make arrow like schema metadata by PlyHeader properties\n * @param plyHeader\n * @returns\n */\nfunction makeMetadataFromPlyHeader(plyHeader: PLYHeader): Map<string, string> {\n const metadataMap = new Map();\n metadataMap.set('ply_comments', JSON.stringify(plyHeader.comments));\n metadataMap.set('ply_elements', JSON.stringify(plyHeader.elements));\n if (plyHeader.format !== undefined) {\n metadataMap.set('ply_format', plyHeader.format);\n }\n if (plyHeader.version !== undefined) {\n metadataMap.set('ply_version', plyHeader.version);\n }\n if (plyHeader.headerLength !== undefined) {\n metadataMap.set('ply_headerLength', plyHeader.headerLength.toString(10));\n }\n return metadataMap;\n}\n"],"file":"get-ply-schema.js"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/lib/normalize-ply.ts"],"names":["getMeshBoundingBox","getPLYSchema","normalizePLY","plyHeader","plyAttributes","options","attributes","getMeshAttributes","boundingBox","vertexCount","indices","length","vertices","isTriangles","mode","topology","schema","plyMesh","loader","loaderData","header","value","Uint32Array","size","accessors","POSITION","Float32Array","normals","NORMAL","uvs","TEXCOORD_0","colors","COLOR_0","Uint8Array","normalized"],"mappings":"AACA,SAAQA,kBAAR,QAAiC,oBAAjC;AAEA,SAAQC,YAAR,QAA2B,kBAA3B;AAOA,eAAe,SAASC,YAAT,CACbC,SADa,EAEbC,aAFa,EAGbC,OAHa,EAIJ;AACT,QAAMC,UAAU,GAAGC,iBAAiB,CAACH,aAAD,CAApC;AACA,QAAMI,WAAW,GAAGR,kBAAkB,CAACM,UAAD,CAAtC;AACA,QAAMG,WAAW,GAAGL,aAAa,CAACM,OAAd,CAAsBC,MAAtB,IAAgCP,aAAa,CAACQ,QAAd,CAAuBD,MAAvB,GAAgC,CAApF;AAIA,QAAME,WAAW,GAAGT,aAAa,CAACM,OAAd,IAAyBN,aAAa,CAACM,OAAd,CAAsBC,MAAtB,GAA+B,CAA5E;AACA,QAAMG,IAAI,GAAGD,WAAW,GAAG,CAAH,GAAO,CAA/B;AACA,QAAME,QAAQ,GAAGF,WAAW,GAAG,eAAH,GAAqB,YAAjD;AAEA,QAAMG,MAAM,GAAGf,YAAY,CAACE,SAAD,EAAYG,UAAZ,CAA3B;AAEA,QAAMW,OAAgB,GAAG;AACvBC,IAAAA,MAAM,EAAE,KADe;AAEvBC,IAAAA,UAAU,EAAEhB,SAFW;AAGvBiB,IAAAA,MAAM,EAAE;AACNX,MAAAA,WADM;AAEND,MAAAA;AAFM,KAHe;AAOvBQ,IAAAA,MAPuB;AAQvBV,IAAAA,UARuB;AASvBI,IAAAA,OAAO,EAAE;AAACW,MAAAA,KAAK,EAAE,IAAIC,WAAJ,CAAgB,CAAhB,CAAR;AAA4BC,MAAAA,IAAI,EAAE;AAAlC,KATc;AAUvBT,IAAAA,IAVuB;AAWvBC,IAAAA;AAXuB,GAAzB;;AAcA,MAAIX,aAAa,CAACM,OAAd,CAAsBC,MAAtB,GAA+B,CAAnC,EAAsC;AACpCM,IAAAA,OAAO,CAACP,OAAR,GAAkB;AAACW,MAAAA,KAAK,EAAE,IAAIC,WAAJ,CAAgBlB,aAAa,CAACM,OAA9B,CAAR;AAAgDa,MAAAA,IAAI,EAAE;AAAtD,KAAlB;AACD;;AAED,SAAON,OAAP;AACD;;AAMD,SAASV,iBAAT,CAA2BD,UAA3B,EAAsE;AACpE,QAAMkB,SAAyB,GAAG,EAAlC;AAEAA,EAAAA,SAAS,CAACC,QAAV,GAAqB;AAACJ,IAAAA,KAAK,EAAE,IAAIK,YAAJ,CAAiBpB,UAAU,CAACM,QAA5B,CAAR;AAA+CW,IAAAA,IAAI,EAAE;AAArD,GAArB;;AAIA,MAAIjB,UAAU,CAACqB,OAAX,CAAmBhB,MAAnB,GAA4B,CAAhC,EAAmC;AACjCa,IAAAA,SAAS,CAACI,MAAV,GAAmB;AAACP,MAAAA,KAAK,EAAE,IAAIK,YAAJ,CAAiBpB,UAAU,CAACqB,OAA5B,CAAR;AAA8CJ,MAAAA,IAAI,EAAE;AAApD,KAAnB;AACD;;AAED,MAAIjB,UAAU,CAACuB,GAAX,CAAelB,MAAf,GAAwB,CAA5B,EAA+B;AAC7Ba,IAAAA,SAAS,CAACM,UAAV,GAAuB;AAACT,MAAAA,KAAK,EAAE,IAAIK,YAAJ,CAAiBpB,UAAU,CAACuB,GAA5B,CAAR;AAA0CN,MAAAA,IAAI,EAAE;AAAhD,KAAvB;AACD;;AAED,MAAIjB,UAAU,CAACyB,MAAX,CAAkBpB,MAAlB,GAA2B,CAA/B,EAAkC;AAEhCa,IAAAA,SAAS,CAACQ,OAAV,GAAoB;AAACX,MAAAA,KAAK,EAAE,IAAIY,UAAJ,CAAe3B,UAAU,CAACyB,MAA1B,CAAR;AAA2CR,MAAAA,IAAI,EAAE,CAAjD;AAAoDW,MAAAA,UAAU,EAAE;AAAhE,KAApB;AACD;;AAED,SAAOV,SAAP;AACD","sourcesContent":["import type {MeshAttributes} from '@loaders.gl/schema';\nimport {getMeshBoundingBox} from '@loaders.gl/schema';\nimport type {PLYMesh, PLYHeader, PLYAttributes, MeshHeader} from './ply-types';\nimport {getPLYSchema} from './get-ply-schema';\n\n/**\n * @param header\n * @param attributes\n * @returns data and header\n */\nexport default function normalizePLY(\n plyHeader: MeshHeader & PLYHeader,\n plyAttributes: PLYAttributes,\n options?: {}\n): PLYMesh {\n const attributes = getMeshAttributes(plyAttributes);\n const boundingBox = getMeshBoundingBox(attributes);\n const vertexCount = plyAttributes.indices.length || plyAttributes.vertices.length / 3;\n\n // TODO - how to detect POINT CLOUDS vs MESHES?\n // TODO - For Meshes, PLY quadrangles must be split?\n const isTriangles = plyAttributes.indices && plyAttributes.indices.length > 0;\n const mode = isTriangles ? 4 : 0; // TRIANGLES vs POINTS\n const topology = isTriangles ? 'triangle-list' : 'point-list';\n\n const schema = getPLYSchema(plyHeader, attributes);\n\n const plyMesh: PLYMesh = {\n loader: 'ply',\n loaderData: plyHeader,\n header: {\n vertexCount,\n boundingBox\n },\n schema,\n attributes,\n indices: {value: new Uint32Array(0), size: 0},\n mode,\n topology\n };\n\n if (plyAttributes.indices.length > 0) {\n plyMesh.indices = {value: new Uint32Array(plyAttributes.indices), size: 1};\n }\n\n return plyMesh;\n}\n\n/**\n * @param attributes\n * @returns accessors []\n */\nfunction getMeshAttributes(attributes: PLYAttributes): MeshAttributes {\n const accessors: MeshAttributes = {};\n\n accessors.POSITION = {value: new Float32Array(attributes.vertices), size: 3};\n\n // optional attributes data\n\n if (attributes.normals.length > 0) {\n accessors.NORMAL = {value: new Float32Array(attributes.normals), size: 3};\n }\n\n if (attributes.uvs.length > 0) {\n accessors.TEXCOORD_0 = {value: new Float32Array(attributes.uvs), size: 2};\n }\n\n if (attributes.colors.length > 0) {\n // TODO - normalized shoud be based on `uchar` flag in source data?\n accessors.COLOR_0 = {value: new Uint8Array(attributes.colors), size: 3, normalized: true};\n }\n\n return accessors;\n}\n"],"file":"normalize-ply.js"}