@loaders.gl/gltf 4.2.0-alpha.4 → 4.2.0-alpha.5

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 (148) hide show
  1. package/dist/dist.dev.js +1049 -517
  2. package/dist/dist.min.js +9 -0
  3. package/dist/glb-loader.d.ts +2 -2
  4. package/dist/glb-loader.d.ts.map +1 -1
  5. package/dist/glb-loader.js +22 -21
  6. package/dist/glb-writer.d.ts +2 -2
  7. package/dist/glb-writer.d.ts.map +1 -1
  8. package/dist/glb-writer.js +27 -24
  9. package/dist/gltf-loader.d.ts +3 -3
  10. package/dist/gltf-loader.d.ts.map +1 -1
  11. package/dist/gltf-loader.js +31 -36
  12. package/dist/gltf-writer.js +24 -26
  13. package/dist/index.cjs +95 -284
  14. package/dist/index.cjs.map +7 -0
  15. package/dist/index.d.ts +17 -17
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +3 -1
  18. package/dist/lib/api/gltf-extensions.d.ts +2 -2
  19. package/dist/lib/api/gltf-extensions.d.ts.map +1 -1
  20. package/dist/lib/api/gltf-extensions.js +45 -22
  21. package/dist/lib/api/gltf-scenegraph.d.ts +2 -2
  22. package/dist/lib/api/gltf-scenegraph.d.ts.map +1 -1
  23. package/dist/lib/api/gltf-scenegraph.js +561 -438
  24. package/dist/lib/api/normalize-gltf-v1.js +250 -181
  25. package/dist/lib/api/post-process-gltf.d.ts +3 -3
  26. package/dist/lib/api/post-process-gltf.d.ts.map +1 -1
  27. package/dist/lib/api/post-process-gltf.js +375 -339
  28. package/dist/lib/encoders/encode-glb.js +62 -48
  29. package/dist/lib/encoders/encode-gltf.js +24 -10
  30. package/dist/lib/extensions/EXT_mesh_features.d.ts +2 -2
  31. package/dist/lib/extensions/EXT_mesh_features.d.ts.map +1 -1
  32. package/dist/lib/extensions/EXT_mesh_features.js +55 -33
  33. package/dist/lib/extensions/EXT_meshopt_compression.d.ts +2 -2
  34. package/dist/lib/extensions/EXT_meshopt_compression.d.ts.map +1 -1
  35. package/dist/lib/extensions/EXT_meshopt_compression.js +27 -31
  36. package/dist/lib/extensions/EXT_structural_metadata.d.ts +2 -2
  37. package/dist/lib/extensions/EXT_structural_metadata.d.ts.map +1 -1
  38. package/dist/lib/extensions/EXT_structural_metadata.js +434 -230
  39. package/dist/lib/extensions/EXT_texture_webp.d.ts +2 -2
  40. package/dist/lib/extensions/EXT_texture_webp.d.ts.map +1 -1
  41. package/dist/lib/extensions/EXT_texture_webp.js +24 -17
  42. package/dist/lib/extensions/KHR_binary_gltf.d.ts +1 -1
  43. package/dist/lib/extensions/KHR_binary_gltf.d.ts.map +1 -1
  44. package/dist/lib/extensions/KHR_binary_gltf.js +29 -15
  45. package/dist/lib/extensions/KHR_draco_mesh_compression.d.ts +2 -2
  46. package/dist/lib/extensions/KHR_draco_mesh_compression.d.ts.map +1 -1
  47. package/dist/lib/extensions/KHR_draco_mesh_compression.js +110 -87
  48. package/dist/lib/extensions/KHR_texture_basisu.d.ts +2 -2
  49. package/dist/lib/extensions/KHR_texture_basisu.d.ts.map +1 -1
  50. package/dist/lib/extensions/KHR_texture_basisu.js +19 -12
  51. package/dist/lib/extensions/KHR_texture_transform.d.ts +2 -2
  52. package/dist/lib/extensions/KHR_texture_transform.d.ts.map +1 -1
  53. package/dist/lib/extensions/KHR_texture_transform.js +194 -154
  54. package/dist/lib/extensions/deprecated/EXT_feature_metadata.d.ts +2 -2
  55. package/dist/lib/extensions/deprecated/EXT_feature_metadata.d.ts.map +1 -1
  56. package/dist/lib/extensions/deprecated/EXT_feature_metadata.js +263 -143
  57. package/dist/lib/extensions/deprecated/KHR_lights_punctual.d.ts +1 -1
  58. package/dist/lib/extensions/deprecated/KHR_lights_punctual.d.ts.map +1 -1
  59. package/dist/lib/extensions/deprecated/KHR_lights_punctual.js +44 -32
  60. package/dist/lib/extensions/deprecated/KHR_materials_unlit.d.ts +1 -1
  61. package/dist/lib/extensions/deprecated/KHR_materials_unlit.d.ts.map +1 -1
  62. package/dist/lib/extensions/deprecated/KHR_materials_unlit.js +30 -24
  63. package/dist/lib/extensions/deprecated/KHR_techniques_webgl.d.ts +1 -1
  64. package/dist/lib/extensions/deprecated/KHR_techniques_webgl.d.ts.map +1 -1
  65. package/dist/lib/extensions/deprecated/KHR_techniques_webgl.js +65 -52
  66. package/dist/lib/extensions/utils/3d-tiles-utils.d.ts +2 -2
  67. package/dist/lib/extensions/utils/3d-tiles-utils.d.ts.map +1 -1
  68. package/dist/lib/extensions/utils/3d-tiles-utils.js +298 -181
  69. package/dist/lib/gltf-utils/get-typed-array.d.ts +1 -1
  70. package/dist/lib/gltf-utils/get-typed-array.d.ts.map +1 -1
  71. package/dist/lib/gltf-utils/get-typed-array.js +54 -42
  72. package/dist/lib/gltf-utils/gltf-attribute-utils.d.ts +1 -1
  73. package/dist/lib/gltf-utils/gltf-attribute-utils.d.ts.map +1 -1
  74. package/dist/lib/gltf-utils/gltf-attribute-utils.js +58 -52
  75. package/dist/lib/gltf-utils/gltf-constants.js +27 -27
  76. package/dist/lib/gltf-utils/gltf-utils.d.ts +1 -1
  77. package/dist/lib/gltf-utils/gltf-utils.d.ts.map +1 -1
  78. package/dist/lib/gltf-utils/gltf-utils.js +67 -60
  79. package/dist/lib/gltf-utils/resolve-url.js +12 -10
  80. package/dist/lib/parsers/parse-glb.d.ts +1 -1
  81. package/dist/lib/parsers/parse-glb.d.ts.map +1 -1
  82. package/dist/lib/parsers/parse-glb.js +132 -89
  83. package/dist/lib/parsers/parse-gltf.d.ts +3 -3
  84. package/dist/lib/parsers/parse-gltf.d.ts.map +1 -1
  85. package/dist/lib/parsers/parse-gltf.js +155 -126
  86. package/dist/lib/types/glb-types.js +0 -1
  87. package/dist/lib/types/gltf-ext-feature-metadata-schema.d.ts +1 -1
  88. package/dist/lib/types/gltf-ext-feature-metadata-schema.d.ts.map +1 -1
  89. package/dist/lib/types/gltf-ext-feature-metadata-schema.js +0 -1
  90. package/dist/lib/types/gltf-ext-mesh-features-schema.d.ts +1 -1
  91. package/dist/lib/types/gltf-ext-mesh-features-schema.d.ts.map +1 -1
  92. package/dist/lib/types/gltf-ext-mesh-features-schema.js +0 -1
  93. package/dist/lib/types/gltf-ext-structural-metadata-schema.d.ts +1 -1
  94. package/dist/lib/types/gltf-ext-structural-metadata-schema.d.ts.map +1 -1
  95. package/dist/lib/types/gltf-ext-structural-metadata-schema.js +0 -1
  96. package/dist/lib/types/gltf-json-schema.js +2 -1
  97. package/dist/lib/types/gltf-postprocessed-schema.js +2 -1
  98. package/dist/lib/types/gltf-types.d.ts +3 -3
  99. package/dist/lib/types/gltf-types.d.ts.map +1 -1
  100. package/dist/lib/types/gltf-types.js +1 -1
  101. package/dist/lib/utils/assert.js +6 -4
  102. package/dist/lib/utils/version.js +3 -1
  103. package/dist/meshopt/meshopt-decoder.js +86 -67
  104. package/dist/webp/webp.js +28 -19
  105. package/package.json +12 -8
  106. package/dist/glb-loader.js.map +0 -1
  107. package/dist/glb-writer.js.map +0 -1
  108. package/dist/gltf-loader.js.map +0 -1
  109. package/dist/gltf-writer.js.map +0 -1
  110. package/dist/index.js.map +0 -1
  111. package/dist/lib/api/gltf-extensions.js.map +0 -1
  112. package/dist/lib/api/gltf-scenegraph.js.map +0 -1
  113. package/dist/lib/api/normalize-gltf-v1.js.map +0 -1
  114. package/dist/lib/api/post-process-gltf.js.map +0 -1
  115. package/dist/lib/encoders/encode-glb.js.map +0 -1
  116. package/dist/lib/encoders/encode-gltf.js.map +0 -1
  117. package/dist/lib/extensions/EXT_mesh_features.js.map +0 -1
  118. package/dist/lib/extensions/EXT_meshopt_compression.js.map +0 -1
  119. package/dist/lib/extensions/EXT_structural_metadata.js.map +0 -1
  120. package/dist/lib/extensions/EXT_texture_webp.js.map +0 -1
  121. package/dist/lib/extensions/KHR_binary_gltf.js.map +0 -1
  122. package/dist/lib/extensions/KHR_draco_mesh_compression.js.map +0 -1
  123. package/dist/lib/extensions/KHR_texture_basisu.js.map +0 -1
  124. package/dist/lib/extensions/KHR_texture_transform.js.map +0 -1
  125. package/dist/lib/extensions/deprecated/EXT_feature_metadata.js.map +0 -1
  126. package/dist/lib/extensions/deprecated/KHR_lights_punctual.js.map +0 -1
  127. package/dist/lib/extensions/deprecated/KHR_materials_unlit.js.map +0 -1
  128. package/dist/lib/extensions/deprecated/KHR_techniques_webgl.js.map +0 -1
  129. package/dist/lib/extensions/utils/3d-tiles-utils.js.map +0 -1
  130. package/dist/lib/gltf-utils/get-typed-array.js.map +0 -1
  131. package/dist/lib/gltf-utils/gltf-attribute-utils.js.map +0 -1
  132. package/dist/lib/gltf-utils/gltf-constants.js.map +0 -1
  133. package/dist/lib/gltf-utils/gltf-utils.js.map +0 -1
  134. package/dist/lib/gltf-utils/resolve-url.js.map +0 -1
  135. package/dist/lib/parsers/parse-glb.js.map +0 -1
  136. package/dist/lib/parsers/parse-gltf.js.map +0 -1
  137. package/dist/lib/types/glb-types.js.map +0 -1
  138. package/dist/lib/types/gltf-ext-feature-metadata-schema.js.map +0 -1
  139. package/dist/lib/types/gltf-ext-mesh-features-schema.js.map +0 -1
  140. package/dist/lib/types/gltf-ext-structural-metadata-schema.js.map +0 -1
  141. package/dist/lib/types/gltf-json-schema.js.map +0 -1
  142. package/dist/lib/types/gltf-postprocessed-schema.js.map +0 -1
  143. package/dist/lib/types/gltf-types.js.map +0 -1
  144. package/dist/lib/utils/assert.js.map +0 -1
  145. package/dist/lib/utils/version.js.map +0 -1
  146. package/dist/meshopt/meshopt-decoder.js.map +0 -1
  147. package/dist/meshopt/meshopt-encoder.ts.disabled +0 -409
  148. package/dist/webp/webp.js.map +0 -1
@@ -1,214 +1,331 @@
1
+ /**
2
+ * loaders.gl, MIT license
3
+ *
4
+ * Shared code for 3DTiles extensions:
5
+ * * EXT_feature_metadata
6
+ * * EXT_mesh_features
7
+ * * EXT_structural_metadata
8
+ */
1
9
  import { getComponentTypeFromArray } from "../../gltf-utils/gltf-utils.js";
2
10
  import { getImageData } from '@loaders.gl/images';
3
11
  function emod(n) {
4
- return (n % 1 + 1) % 1;
12
+ return ((n % 1) + 1) % 1;
5
13
  }
6
14
  const ATTRIBUTE_TYPE_TO_COMPONENTS = {
7
- SCALAR: 1,
8
- VEC2: 2,
9
- VEC3: 3,
10
- VEC4: 4,
11
- MAT2: 4,
12
- MAT3: 9,
13
- MAT4: 16,
14
- BOOLEAN: 1,
15
- STRING: 1,
16
- ENUM: 1
15
+ SCALAR: 1,
16
+ VEC2: 2,
17
+ VEC3: 3,
18
+ VEC4: 4,
19
+ MAT2: 4,
20
+ MAT3: 9,
21
+ MAT4: 16,
22
+ BOOLEAN: 1,
23
+ STRING: 1,
24
+ ENUM: 1
17
25
  };
18
26
  const ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY = {
19
- INT8: Int8Array,
20
- UINT8: Uint8Array,
21
- INT16: Int16Array,
22
- UINT16: Uint16Array,
23
- INT32: Int32Array,
24
- UINT32: Uint32Array,
25
- INT64: BigInt64Array,
26
- UINT64: BigUint64Array,
27
- FLOAT32: Float32Array,
28
- FLOAT64: Float64Array
27
+ INT8: Int8Array,
28
+ UINT8: Uint8Array,
29
+ INT16: Int16Array,
30
+ UINT16: Uint16Array,
31
+ INT32: Int32Array,
32
+ UINT32: Uint32Array,
33
+ INT64: BigInt64Array,
34
+ UINT64: BigUint64Array,
35
+ FLOAT32: Float32Array,
36
+ FLOAT64: Float64Array
29
37
  };
30
38
  const ATTRIBUTE_COMPONENT_TYPE_TO_BYTE_SIZE = {
31
- INT8: 1,
32
- UINT8: 1,
33
- INT16: 2,
34
- UINT16: 2,
35
- INT32: 4,
36
- UINT32: 4,
37
- INT64: 8,
38
- UINT64: 8,
39
- FLOAT32: 4,
40
- FLOAT64: 8
39
+ INT8: 1,
40
+ UINT8: 1,
41
+ INT16: 2,
42
+ UINT16: 2,
43
+ INT32: 4,
44
+ UINT32: 4,
45
+ INT64: 8,
46
+ UINT64: 8,
47
+ FLOAT32: 4,
48
+ FLOAT64: 8
41
49
  };
42
50
  export function getArrayElementByteSize(attributeType, componentType) {
43
- return ATTRIBUTE_COMPONENT_TYPE_TO_BYTE_SIZE[componentType] * ATTRIBUTE_TYPE_TO_COMPONENTS[attributeType];
51
+ return (ATTRIBUTE_COMPONENT_TYPE_TO_BYTE_SIZE[componentType] *
52
+ ATTRIBUTE_TYPE_TO_COMPONENTS[attributeType]);
44
53
  }
54
+ /**
55
+ * Gets offset array from `arrayOffsets` or `stringOffsets`.
56
+ * @param scenegraph - Instance of the class for structured access to GLTF data.
57
+ * @param bufferViewIndex - Buffer view index
58
+ * @param offsetType - The type of values in `arrayOffsets` or `stringOffsets`.
59
+ * @param numberOfElements - The number of elements in each property array.
60
+ * @returns Array of values offsets. The number of offsets in the array is equal to `numberOfElements` plus one.
61
+ */
45
62
  export function getOffsetsForProperty(scenegraph, bufferViewIndex, offsetType, numberOfElements) {
46
- if (offsetType !== 'UINT8' && offsetType !== 'UINT16' && offsetType !== 'UINT32' && offsetType !== 'UINT64') {
47
- return null;
48
- }
49
- const arrayOffsetsBytes = scenegraph.getTypedArrayForBufferView(bufferViewIndex);
50
- const arrayOffsets = convertRawBufferToMetadataArray(arrayOffsetsBytes, 'SCALAR', offsetType, numberOfElements + 1);
51
- if (arrayOffsets instanceof BigInt64Array || arrayOffsets instanceof BigUint64Array) {
52
- return null;
53
- }
54
- return arrayOffsets;
63
+ if (offsetType !== 'UINT8' &&
64
+ offsetType !== 'UINT16' &&
65
+ offsetType !== 'UINT32' &&
66
+ offsetType !== 'UINT64') {
67
+ return null;
68
+ }
69
+ const arrayOffsetsBytes = scenegraph.getTypedArrayForBufferView(bufferViewIndex);
70
+ const arrayOffsets = convertRawBufferToMetadataArray(arrayOffsetsBytes, 'SCALAR', // offsets consist of ONE component
71
+ offsetType, numberOfElements + 1 // The number of offsets is equal to the property table `count` plus one.
72
+ );
73
+ // We don't support BigInt offsets at the moment. It requires additional logic and potential issues in Safari
74
+ if (arrayOffsets instanceof BigInt64Array || arrayOffsets instanceof BigUint64Array) {
75
+ return null;
76
+ }
77
+ return arrayOffsets;
55
78
  }
56
- export function convertRawBufferToMetadataArray(data, attributeType, componentType) {
57
- let elementCount = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
58
- const numberOfComponents = ATTRIBUTE_TYPE_TO_COMPONENTS[attributeType];
59
- const ArrayType = ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY[componentType];
60
- const size = ATTRIBUTE_COMPONENT_TYPE_TO_BYTE_SIZE[componentType];
61
- const length = elementCount * numberOfComponents;
62
- const byteLength = length * size;
63
- let buffer = data.buffer;
64
- let offset = data.byteOffset;
65
- if (offset % size !== 0) {
66
- const bufferArray = new Uint8Array(buffer);
67
- buffer = bufferArray.slice(offset, offset + byteLength).buffer;
68
- offset = 0;
69
- }
70
- return new ArrayType(buffer, offset, length);
79
+ /**
80
+ * Converts raw bytes that are in the buffer to an array of the type defined by the schema.
81
+ * @param data - Raw bytes in the buffer.
82
+ * @param attributeType - SCALAR, VECN, MATN.
83
+ * @param componentType - Type of the component in elements, e.g. 'UINT8' or 'FLOAT32'.
84
+ * @param elementCount - Number of elements in the array. Default value is 1.
85
+ * @returns Data array
86
+ */
87
+ export function convertRawBufferToMetadataArray(data, attributeType, componentType, elementCount = 1) {
88
+ const numberOfComponents = ATTRIBUTE_TYPE_TO_COMPONENTS[attributeType];
89
+ const ArrayType = ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY[componentType];
90
+ const size = ATTRIBUTE_COMPONENT_TYPE_TO_BYTE_SIZE[componentType];
91
+ const length = elementCount * numberOfComponents;
92
+ const byteLength = length * size;
93
+ let buffer = data.buffer;
94
+ let offset = data.byteOffset;
95
+ if (offset % size !== 0) {
96
+ const bufferArray = new Uint8Array(buffer);
97
+ buffer = bufferArray.slice(offset, offset + byteLength).buffer;
98
+ offset = 0;
99
+ }
100
+ return new ArrayType(buffer, offset, length);
71
101
  }
102
+ /**
103
+ * Processes data encoded in the texture associated with the primitive.
104
+ * @param scenegraph - Instance of the class for structured access to GLTF data.
105
+ * @param textureInfo - Reference to the texture where extension data are stored.
106
+ * @param primitive - Primitive object in the mesh.
107
+ * @returns Array of data taken. Null if data can't be taken from the texture.
108
+ */
72
109
  export function getPrimitiveTextureData(scenegraph, textureInfo, primitive) {
73
- var _json$textures, _json$textures$textur;
74
- const texCoordAccessorKey = `TEXCOORD_${textureInfo.texCoord || 0}`;
75
- const texCoordAccessorIndex = primitive.attributes[texCoordAccessorKey];
76
- const textureCoordinates = scenegraph.getTypedArrayForAccessor(texCoordAccessorIndex);
77
- const json = scenegraph.gltf.json;
78
- const textureIndex = textureInfo.index;
79
- const imageIndex = (_json$textures = json.textures) === null || _json$textures === void 0 ? void 0 : (_json$textures$textur = _json$textures[textureIndex]) === null || _json$textures$textur === void 0 ? void 0 : _json$textures$textur.source;
80
- if (typeof imageIndex !== 'undefined') {
81
- var _json$images, _json$images$imageInd, _scenegraph$gltf$imag;
82
- const mimeType = (_json$images = json.images) === null || _json$images === void 0 ? void 0 : (_json$images$imageInd = _json$images[imageIndex]) === null || _json$images$imageInd === void 0 ? void 0 : _json$images$imageInd.mimeType;
83
- const parsedImage = (_scenegraph$gltf$imag = scenegraph.gltf.images) === null || _scenegraph$gltf$imag === void 0 ? void 0 : _scenegraph$gltf$imag[imageIndex];
84
- if (parsedImage && typeof parsedImage.width !== 'undefined') {
85
- const textureData = [];
86
- for (let index = 0; index < textureCoordinates.length; index += 2) {
87
- const value = getImageValueByCoordinates(parsedImage, mimeType, textureCoordinates, index, textureInfo.channels);
88
- textureData.push(value);
110
+ /*
111
+ texture.index is an index for the "textures" array.
112
+ The texture object referenced by this index looks like this:
113
+ {
114
+ "sampler": 0,
115
+ "source": 0
89
116
  }
90
- return textureData;
117
+ "sampler" is an index for the "samplers" array
118
+ "source" is an index for the "images" array that contains data stored in rgba channels of the image.
119
+
120
+ texture.texCoord is a number-suffix (like 1) for an attribute like "TEXCOORD_1" in meshes.primitives
121
+ The value of "TEXCOORD_1" is an accessor that is used to get coordinates.
122
+ These coordinates are being used to get data from the image.
123
+
124
+ Default for texture.texCoord is 0
125
+ @see https://github.com/CesiumGS/glTF/blob/3d-tiles-next/specification/2.0/schema/textureInfo.schema.json
126
+ */
127
+ const texCoordAccessorKey = `TEXCOORD_${textureInfo.texCoord || 0}`;
128
+ const texCoordAccessorIndex = primitive.attributes[texCoordAccessorKey];
129
+ const textureCoordinates = scenegraph.getTypedArrayForAccessor(texCoordAccessorIndex);
130
+ const json = scenegraph.gltf.json;
131
+ const textureIndex = textureInfo.index;
132
+ const imageIndex = json.textures?.[textureIndex]?.source;
133
+ if (typeof imageIndex !== 'undefined') {
134
+ const mimeType = json.images?.[imageIndex]?.mimeType;
135
+ const parsedImage = scenegraph.gltf.images?.[imageIndex];
136
+ // Checking for width is to prevent handling Un-processed images (e.g. [analyze] stage, where loadImages option is set to false)
137
+ if (parsedImage && typeof parsedImage.width !== 'undefined') {
138
+ const textureData = [];
139
+ for (let index = 0; index < textureCoordinates.length; index += 2) {
140
+ const value = getImageValueByCoordinates(parsedImage, mimeType, textureCoordinates, index, textureInfo.channels);
141
+ textureData.push(value);
142
+ }
143
+ return textureData;
144
+ }
91
145
  }
92
- }
93
- return [];
146
+ return [];
94
147
  }
148
+ /**
149
+ * Puts property data to attributes.
150
+ * It creates corresponding buffer, bufferView and accessor
151
+ * so the data can be accessed like regular data stored in buffers.
152
+ * @param scenegraph - Scenegraph object.
153
+ * @param attributeName - Name of the attribute.
154
+ * @param propertyData - Property data to store.
155
+ * @param featureTable - Array where unique data from the property data are being stored.
156
+ * @param primitive - Primitive object.
157
+ */
95
158
  export function primitivePropertyDataToAttributes(scenegraph, attributeName, propertyData, featureTable, primitive) {
96
- if (!(propertyData !== null && propertyData !== void 0 && propertyData.length)) {
97
- return;
98
- }
99
- const featureIndices = [];
100
- for (const texelData of propertyData) {
101
- let index = featureTable.findIndex(item => item === texelData);
102
- if (index === -1) {
103
- index = featureTable.push(texelData) - 1;
159
+ // No reason to create an empty buffer if there is no property data to store.
160
+ if (!propertyData?.length) {
161
+ return;
104
162
  }
105
- featureIndices.push(index);
106
- }
107
- const typedArray = new Uint32Array(featureIndices);
108
- const bufferIndex = scenegraph.gltf.buffers.push({
109
- arrayBuffer: typedArray.buffer,
110
- byteOffset: typedArray.byteOffset,
111
- byteLength: typedArray.byteLength
112
- }) - 1;
113
- const bufferViewIndex = scenegraph.addBufferView(typedArray, bufferIndex, 0);
114
- const accessorIndex = scenegraph.addAccessor(bufferViewIndex, {
115
- size: 1,
116
- componentType: getComponentTypeFromArray(typedArray),
117
- count: typedArray.length
118
- });
119
- primitive.attributes[attributeName] = accessorIndex;
120
- }
121
- function getImageValueByCoordinates(parsedImage, mimeType, textureCoordinates, index) {
122
- let channels = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [0];
123
- const CHANNELS_MAP = {
124
- r: {
125
- offset: 0,
126
- shift: 0
127
- },
128
- g: {
129
- offset: 1,
130
- shift: 8
131
- },
132
- b: {
133
- offset: 2,
134
- shift: 16
135
- },
136
- a: {
137
- offset: 3,
138
- shift: 24
163
+ /*
164
+ featureTable will contain unique values, e.g.
165
+ propertyData = [24, 35, 28, 24]
166
+ featureTable = [24, 35, 28]
167
+ featureIndices will contain indices that refer featureTextureTable, e.g.
168
+ featureIndices = [0, 1, 2, 0]
169
+ */
170
+ const featureIndices = [];
171
+ for (const texelData of propertyData) {
172
+ let index = featureTable.findIndex((item) => item === texelData);
173
+ if (index === -1) {
174
+ index = featureTable.push(texelData) - 1;
175
+ }
176
+ featureIndices.push(index);
139
177
  }
140
- };
141
- const u = textureCoordinates[index];
142
- const v = textureCoordinates[index + 1];
143
- let components = 1;
144
- if (mimeType && (mimeType.indexOf('image/jpeg') !== -1 || mimeType.indexOf('image/png') !== -1)) components = 4;
145
- const offset = coordinatesToOffset(u, v, parsedImage, components);
146
- let value = 0;
147
- for (const c of channels) {
148
- const map = typeof c === 'number' ? Object.values(CHANNELS_MAP)[c] : CHANNELS_MAP[c];
149
- const imageOffset = offset + map.offset;
150
- const imageData = getImageData(parsedImage);
151
- if (imageData.data.length <= imageOffset) {
152
- throw new Error(`${imageData.data.length} <= ${imageOffset}`);
178
+ const typedArray = new Uint32Array(featureIndices);
179
+ const bufferIndex = scenegraph.gltf.buffers.push({
180
+ arrayBuffer: typedArray.buffer,
181
+ byteOffset: typedArray.byteOffset,
182
+ byteLength: typedArray.byteLength
183
+ }) - 1;
184
+ const bufferViewIndex = scenegraph.addBufferView(typedArray, bufferIndex, 0);
185
+ const accessorIndex = scenegraph.addAccessor(bufferViewIndex, {
186
+ size: 1,
187
+ componentType: getComponentTypeFromArray(typedArray),
188
+ count: typedArray.length
189
+ });
190
+ primitive.attributes[attributeName] = accessorIndex;
191
+ }
192
+ /**
193
+ * Gets the value from the texture by coordinates provided.
194
+ * @param parsedImage - Image where the data are stored.
195
+ * @param mimeType - MIME type.
196
+ * @param textureCoordinates - uv coordinates to access data in the image.
197
+ * @param index - Index of uv coordinates in the array textureCoordinates.
198
+ * @param channels - Image channels where data are stored.
199
+ * Channels of an RGBA texture are numbered 0..3 respectively.
200
+ * For Ext_mesh_features and EXT_strucural_metadata the channels default is [0]
201
+ * @see https://github.com/CesiumGS/glTF/blob/3d-tiles-next/extensions/2.0/Vendor/EXT_mesh_features/schema/featureIdTexture.schema.json
202
+ * @see https://github.com/CesiumGS/glTF/blob/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata/schema/propertyTexture.property.schema.json
203
+ * @returns Value taken from the image.
204
+ */
205
+ function getImageValueByCoordinates(parsedImage, mimeType, textureCoordinates, index, channels = [0]) {
206
+ const CHANNELS_MAP = {
207
+ r: { offset: 0, shift: 0 },
208
+ g: { offset: 1, shift: 8 },
209
+ b: { offset: 2, shift: 16 },
210
+ a: { offset: 3, shift: 24 }
211
+ };
212
+ const u = textureCoordinates[index];
213
+ const v = textureCoordinates[index + 1];
214
+ let components = 1;
215
+ if (mimeType && (mimeType.indexOf('image/jpeg') !== -1 || mimeType.indexOf('image/png') !== -1))
216
+ components = 4;
217
+ const offset = coordinatesToOffset(u, v, parsedImage, components);
218
+ let value = 0;
219
+ for (const c of channels) {
220
+ /*
221
+ According to the EXT_feature_metadata extension specification:
222
+ Channels are labeled by rgba and are swizzled with a string of 1-4 characters.
223
+ According to the EXT_mesh_features extension specification:
224
+ The channels array contains non-negative integer values corresponding to channels of the source texture that the feature ID consists of.
225
+ Channels of an RGBA texture are numbered 0–3 respectively.
226
+ Function getImageValueByCoordinates is used to process both extensions.
227
+ So, there should be possible to get the element of CHANNELS_MAP by either index (0, 1, 2, 3) or key (r, g, b, a).
228
+ */
229
+ const map = typeof c === 'number' ? Object.values(CHANNELS_MAP)[c] : CHANNELS_MAP[c];
230
+ const imageOffset = offset + map.offset;
231
+ const imageData = getImageData(parsedImage);
232
+ if (imageData.data.length <= imageOffset) {
233
+ throw new Error(`${imageData.data.length} <= ${imageOffset}`);
234
+ }
235
+ const imageValue = imageData.data[imageOffset];
236
+ value |= imageValue << map.shift;
153
237
  }
154
- const imageValue = imageData.data[imageOffset];
155
- value |= imageValue << map.shift;
156
- }
157
- return value;
238
+ return value;
158
239
  }
159
- function coordinatesToOffset(u, v, parsedImage) {
160
- let componentsCount = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
161
- const w = parsedImage.width;
162
- const iX = emod(u) * (w - 1);
163
- const indX = Math.round(iX);
164
- const h = parsedImage.height;
165
- const iY = emod(v) * (h - 1);
166
- const indY = Math.round(iY);
167
- const components = parsedImage.components ? parsedImage.components : componentsCount;
168
- const offset = (indY * w + indX) * components;
169
- return offset;
240
+ /**
241
+ * Retrieves the offset in the image where the data are stored.
242
+ * @param u - u-coordinate.
243
+ * @param v - v-coordinate.
244
+ * @param parsedImage - Image where the data are stored.
245
+ * @param componentsCount - Number of components the data consists of.
246
+ * @returns Offset in the image where the data are stored.
247
+ */
248
+ function coordinatesToOffset(u, v, parsedImage, componentsCount = 1) {
249
+ const w = parsedImage.width;
250
+ const iX = emod(u) * (w - 1);
251
+ const indX = Math.round(iX);
252
+ const h = parsedImage.height;
253
+ const iY = emod(v) * (h - 1);
254
+ const indY = Math.round(iY);
255
+ const components = parsedImage.components ? parsedImage.components : componentsCount;
256
+ // components is a number of channels in the image
257
+ const offset = (indY * w + indX) * components;
258
+ return offset;
170
259
  }
260
+ /**
261
+ * Parses variable-length array data.
262
+ * In this case every value of the property in the table will be an array
263
+ * of arbitrary length.
264
+ * @param valuesData - Values in a flat typed array.
265
+ * @param numberOfElements - Number of rows in the property table.
266
+ * @param arrayOffsets - Offsets of nested arrays in the flat values array.
267
+ * @param valuesDataBytesLength - Data byte length.
268
+ * @param valueSize - Value size in bytes.
269
+ * @returns Array of typed arrays.
270
+ */
171
271
  export function parseVariableLengthArrayNumeric(valuesData, numberOfElements, arrayOffsets, valuesDataBytesLength, valueSize) {
172
- const attributeValueArray = [];
173
- for (let index = 0; index < numberOfElements; index++) {
174
- const arrayOffset = arrayOffsets[index];
175
- const arrayByteSize = arrayOffsets[index + 1] - arrayOffsets[index];
176
- if (arrayByteSize + arrayOffset > valuesDataBytesLength) {
177
- break;
272
+ const attributeValueArray = [];
273
+ for (let index = 0; index < numberOfElements; index++) {
274
+ const arrayOffset = arrayOffsets[index];
275
+ const arrayByteSize = arrayOffsets[index + 1] - arrayOffsets[index];
276
+ if (arrayByteSize + arrayOffset > valuesDataBytesLength) {
277
+ break;
278
+ }
279
+ const typedArrayOffset = arrayOffset / valueSize;
280
+ const elementCount = arrayByteSize / valueSize;
281
+ attributeValueArray.push(valuesData.slice(typedArrayOffset, typedArrayOffset + elementCount));
178
282
  }
179
- const typedArrayOffset = arrayOffset / valueSize;
180
- const elementCount = arrayByteSize / valueSize;
181
- attributeValueArray.push(valuesData.slice(typedArrayOffset, typedArrayOffset + elementCount));
182
- }
183
- return attributeValueArray;
283
+ return attributeValueArray;
184
284
  }
285
+ /**
286
+ * Parses fixed-length array data.
287
+ * In this case every value of the property in the table will be an array
288
+ * of constant length equal to `arrayCount`.
289
+ * @param valuesData - Values in a flat typed array.
290
+ * @param numberOfElements - Number of rows in the property table.
291
+ * @param arrayCount - Nested arrays length.
292
+ * @returns Array of typed arrays.
293
+ */
185
294
  export function parseFixedLengthArrayNumeric(valuesData, numberOfElements, arrayCount) {
186
- const attributeValueArray = [];
187
- for (let index = 0; index < numberOfElements; index++) {
188
- const elementOffset = index * arrayCount;
189
- attributeValueArray.push(valuesData.slice(elementOffset, elementOffset + arrayCount));
190
- }
191
- return attributeValueArray;
295
+ const attributeValueArray = [];
296
+ for (let index = 0; index < numberOfElements; index++) {
297
+ const elementOffset = index * arrayCount;
298
+ attributeValueArray.push(valuesData.slice(elementOffset, elementOffset + arrayCount));
299
+ }
300
+ return attributeValueArray;
192
301
  }
302
+ /**
303
+ * Decodes properties of string type from binary source.
304
+ * @param numberOfElements - The number of elements in each property array that propertyTableProperty contains. It's a number of rows in the table.
305
+ * @param valuesDataBytes - Data taken from values property of the property table property.
306
+ * @param arrayOffsets - Offsets for variable-length arrays. It's null for fixed-length arrays or scalar types.
307
+ * @param stringOffsets - Index of the buffer view containing offsets for strings. It should be available for string type.
308
+ * @returns String property values
309
+ */
193
310
  export function getPropertyDataString(numberOfElements, valuesDataBytes, arrayOffsets, stringOffsets) {
194
- if (arrayOffsets) {
195
- throw new Error('Not implemented - arrayOffsets for strings is specified');
196
- }
197
- if (stringOffsets) {
198
- const stringsArray = [];
199
- const textDecoder = new TextDecoder('utf8');
200
- let stringOffset = 0;
201
- for (let index = 0; index < numberOfElements; index++) {
202
- const stringByteSize = stringOffsets[index + 1] - stringOffsets[index];
203
- if (stringByteSize + stringOffset <= valuesDataBytes.length) {
204
- const stringData = valuesDataBytes.subarray(stringOffset, stringByteSize + stringOffset);
205
- const stringAttribute = textDecoder.decode(stringData);
206
- stringsArray.push(stringAttribute);
207
- stringOffset += stringByteSize;
208
- }
311
+ if (arrayOffsets) {
312
+ // TODO: implement it as soon as we have the corresponding tileset
313
+ throw new Error('Not implemented - arrayOffsets for strings is specified');
314
+ }
315
+ if (stringOffsets) {
316
+ const stringsArray = [];
317
+ const textDecoder = new TextDecoder('utf8');
318
+ let stringOffset = 0;
319
+ for (let index = 0; index < numberOfElements; index++) {
320
+ const stringByteSize = stringOffsets[index + 1] - stringOffsets[index];
321
+ if (stringByteSize + stringOffset <= valuesDataBytes.length) {
322
+ const stringData = valuesDataBytes.subarray(stringOffset, stringByteSize + stringOffset);
323
+ const stringAttribute = textDecoder.decode(stringData);
324
+ stringsArray.push(stringAttribute);
325
+ stringOffset += stringByteSize;
326
+ }
327
+ }
328
+ return stringsArray;
209
329
  }
210
- return stringsArray;
211
- }
212
- return [];
330
+ return [];
213
331
  }
214
- //# sourceMappingURL=3d-tiles-utils.js.map
@@ -1,5 +1,5 @@
1
1
  import type { TypedArray } from '@loaders.gl/schema';
2
- import type { GLTF, GLTFExternalBuffer, GLTFAccessor } from '../types/gltf-types';
2
+ import type { GLTF, GLTFExternalBuffer, GLTFAccessor } from "../types/gltf-types.js";
3
3
  export declare function getTypedArrayForBufferView(json: any, buffers: any, bufferViewIndex: any): Uint8Array;
4
4
  export declare function getTypedArrayForImageData(json: any, buffers: any, imageIndex: any): Uint8Array;
5
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"get-typed-array.d.ts","sourceRoot":"","sources":["../../../src/lib/gltf-utils/get-typed-array.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAC,IAAI,EAAE,kBAAkB,EAAE,YAAY,EAAC,MAAM,qBAAqB,CAAC;AAKhF,wBAAgB,0BAA0B,CAAC,IAAI,KAAA,EAAE,OAAO,KAAA,EAAE,eAAe,KAAA,cAWxE;AAID,wBAAgB,yBAAyB,CAAC,IAAI,KAAA,EAAE,OAAO,KAAA,EAAE,UAAU,KAAA,cAIlE;AAED;;;;;;GAMG;AAEH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,kBAAkB,EAAE,EAC7B,QAAQ,EAAE,YAAY,GAAG,MAAM,GAC9B,UAAU,CAsCZ"}
1
+ {"version":3,"file":"get-typed-array.d.ts","sourceRoot":"","sources":["../../../src/lib/gltf-utils/get-typed-array.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAC,IAAI,EAAE,kBAAkB,EAAE,YAAY,EAAC,+BAA4B;AAKhF,wBAAgB,0BAA0B,CAAC,IAAI,KAAA,EAAE,OAAO,KAAA,EAAE,eAAe,KAAA,cAWxE;AAID,wBAAgB,yBAAyB,CAAC,IAAI,KAAA,EAAE,OAAO,KAAA,EAAE,UAAU,KAAA,cAIlE;AAED;;;;;;GAMG;AAEH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,kBAAkB,EAAE,EAC7B,QAAQ,EAAE,YAAY,GAAG,MAAM,GAC9B,UAAU,CAsCZ"}
@@ -1,51 +1,63 @@
1
+ // TODO - GLTFScenegraph should use these
1
2
  import { assert } from "../utils/assert.js";
2
3
  import { getAccessorArrayTypeAndLength } from "./gltf-utils.js";
4
+ // accepts buffer view index or buffer view object
5
+ // returns a `Uint8Array`
3
6
  export function getTypedArrayForBufferView(json, buffers, bufferViewIndex) {
4
- const bufferView = json.bufferViews[bufferViewIndex];
5
- assert(bufferView);
6
- const bufferIndex = bufferView.buffer;
7
- const binChunk = buffers[bufferIndex];
8
- assert(binChunk);
9
- const byteOffset = (bufferView.byteOffset || 0) + binChunk.byteOffset;
10
- return new Uint8Array(binChunk.arrayBuffer, byteOffset, bufferView.byteLength);
7
+ const bufferView = json.bufferViews[bufferViewIndex];
8
+ assert(bufferView);
9
+ // Get hold of the arrayBuffer
10
+ const bufferIndex = bufferView.buffer;
11
+ const binChunk = buffers[bufferIndex];
12
+ assert(binChunk);
13
+ const byteOffset = (bufferView.byteOffset || 0) + binChunk.byteOffset;
14
+ return new Uint8Array(binChunk.arrayBuffer, byteOffset, bufferView.byteLength);
11
15
  }
16
+ // accepts accessor index or accessor object
17
+ // returns a `Uint8Array`
12
18
  export function getTypedArrayForImageData(json, buffers, imageIndex) {
13
- const image = json.images[imageIndex];
14
- const bufferViewIndex = json.bufferViews[image.bufferView];
15
- return getTypedArrayForBufferView(json, buffers, bufferViewIndex);
19
+ const image = json.images[imageIndex];
20
+ const bufferViewIndex = json.bufferViews[image.bufferView];
21
+ return getTypedArrayForBufferView(json, buffers, bufferViewIndex);
16
22
  }
23
+ /**
24
+ * Gets data pointed by the accessor.
25
+ * @param json - json part of gltf content of a GLTF tile.
26
+ * @param buffers - Array containing buffers of data.
27
+ * @param accessor - accepts accessor index or accessor object.
28
+ * @returns {TypedArray} Typed array with type matching the type of data poited by the accessor.
29
+ */
30
+ // eslint-disable-next-line complexity
17
31
  export function getTypedArrayForAccessor(json, buffers, accessor) {
18
- var _json$accessors, _json$bufferViews;
19
- const gltfAccessor = typeof accessor === 'number' ? (_json$accessors = json.accessors) === null || _json$accessors === void 0 ? void 0 : _json$accessors[accessor] : accessor;
20
- if (!gltfAccessor) {
21
- throw new Error(`No gltf accessor ${JSON.stringify(accessor)}`);
22
- }
23
- const bufferView = (_json$bufferViews = json.bufferViews) === null || _json$bufferViews === void 0 ? void 0 : _json$bufferViews[gltfAccessor.bufferView || 0];
24
- if (!bufferView) {
25
- throw new Error(`No gltf buffer view for accessor ${bufferView}`);
26
- }
27
- const {
28
- arrayBuffer,
29
- byteOffset: bufferByteOffset
30
- } = buffers[bufferView.buffer];
31
- const byteOffset = (bufferByteOffset || 0) + (gltfAccessor.byteOffset || 0) + (bufferView.byteOffset || 0);
32
- const {
33
- ArrayType,
34
- length,
35
- componentByteSize,
36
- numberOfComponentsInElement
37
- } = getAccessorArrayTypeAndLength(gltfAccessor, bufferView);
38
- const elementByteSize = componentByteSize * numberOfComponentsInElement;
39
- const elementAddressScale = bufferView.byteStride || elementByteSize;
40
- if (typeof bufferView.byteStride === 'undefined' || bufferView.byteStride === elementByteSize) {
41
- const result = new ArrayType(arrayBuffer, byteOffset, length);
32
+ const gltfAccessor = typeof accessor === 'number' ? json.accessors?.[accessor] : accessor;
33
+ if (!gltfAccessor) {
34
+ throw new Error(`No gltf accessor ${JSON.stringify(accessor)}`);
35
+ }
36
+ const bufferView = json.bufferViews?.[gltfAccessor.bufferView || 0];
37
+ if (!bufferView) {
38
+ throw new Error(`No gltf buffer view for accessor ${bufferView}`);
39
+ }
40
+ // Get `arrayBuffer` the `bufferView` looks at
41
+ const { arrayBuffer, byteOffset: bufferByteOffset } = buffers[bufferView.buffer];
42
+ // Resulting byteOffset is sum of the buffer, accessor and bufferView byte offsets
43
+ const byteOffset = (bufferByteOffset || 0) + (gltfAccessor.byteOffset || 0) + (bufferView.byteOffset || 0);
44
+ // Deduce TypedArray type and its length from `accessor` and `bufferView` data
45
+ const { ArrayType, length, componentByteSize, numberOfComponentsInElement } = getAccessorArrayTypeAndLength(gltfAccessor, bufferView);
46
+ // 'length' is a whole number of components of all elements in the buffer pointed by the accessor
47
+ // Multiplier to calculate the address of the element in the arrayBuffer
48
+ const elementByteSize = componentByteSize * numberOfComponentsInElement;
49
+ const elementAddressScale = bufferView.byteStride || elementByteSize;
50
+ // Creare an array of component's type where all components (not just elements) will reside
51
+ if (typeof bufferView.byteStride === 'undefined' || bufferView.byteStride === elementByteSize) {
52
+ // No iterleaving
53
+ const result = new ArrayType(arrayBuffer, byteOffset, length);
54
+ return result;
55
+ }
56
+ // Iterleaving
57
+ const result = new ArrayType(length);
58
+ for (let i = 0; i < gltfAccessor.count; i++) {
59
+ const values = new ArrayType(arrayBuffer, byteOffset + i * elementAddressScale, numberOfComponentsInElement);
60
+ result.set(values, i * numberOfComponentsInElement);
61
+ }
42
62
  return result;
43
- }
44
- const result = new ArrayType(length);
45
- for (let i = 0; i < gltfAccessor.count; i++) {
46
- const values = new ArrayType(arrayBuffer, byteOffset + i * elementAddressScale, numberOfComponentsInElement);
47
- result.set(values, i * numberOfComponentsInElement);
48
- }
49
- return result;
50
63
  }
51
- //# sourceMappingURL=get-typed-array.js.map
@@ -1,4 +1,4 @@
1
- import type { GLTFAccessor } from '../types/gltf-json-schema';
1
+ import type { GLTFAccessor } from "../types/gltf-json-schema.js";
2
2
  export declare function getGLTFAccessors(attributes: any): {
3
3
  [key: string]: GLTFAccessor;
4
4
  };