@loaders.gl/gltf 3.2.6 → 3.3.0-alpha.2

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 (49) hide show
  1. package/dist/dist.min.js +1494 -38
  2. package/dist/es5/index.js.map +1 -1
  3. package/dist/es5/lib/api/gltf-extensions.js +5 -1
  4. package/dist/es5/lib/api/gltf-extensions.js.map +1 -1
  5. package/dist/es5/lib/extensions/KHR_texture_transform.js +293 -0
  6. package/dist/es5/lib/extensions/KHR_texture_transform.js.map +1 -0
  7. package/dist/es5/lib/extensions/deprecated/EXT_feature_metadata.js +131 -0
  8. package/dist/es5/lib/extensions/deprecated/EXT_feature_metadata.js.map +1 -0
  9. package/dist/es5/lib/gltf-utils/gltf-constants.js +3 -0
  10. package/dist/es5/lib/gltf-utils/gltf-constants.js.map +1 -1
  11. package/dist/es5/lib/utils/version.js +1 -1
  12. package/dist/es5/lib/utils/version.js.map +1 -1
  13. package/dist/esm/index.js.map +1 -1
  14. package/dist/esm/lib/api/gltf-extensions.js +3 -1
  15. package/dist/esm/lib/api/gltf-extensions.js.map +1 -1
  16. package/dist/esm/lib/extensions/KHR_texture_transform.js +218 -0
  17. package/dist/esm/lib/extensions/KHR_texture_transform.js.map +1 -0
  18. package/dist/esm/lib/extensions/deprecated/EXT_feature_metadata.js +95 -0
  19. package/dist/esm/lib/extensions/deprecated/EXT_feature_metadata.js.map +1 -0
  20. package/dist/esm/lib/gltf-utils/gltf-constants.js +2 -2
  21. package/dist/esm/lib/gltf-utils/gltf-constants.js.map +1 -1
  22. package/dist/esm/lib/utils/version.js +1 -1
  23. package/dist/esm/lib/utils/version.js.map +1 -1
  24. package/dist/index.d.ts +1 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/lib/api/gltf-extensions.d.ts +5 -0
  27. package/dist/lib/api/gltf-extensions.d.ts.map +1 -1
  28. package/dist/lib/api/gltf-extensions.js +5 -1
  29. package/dist/lib/extensions/KHR_texture_transform.d.ts +13 -0
  30. package/dist/lib/extensions/KHR_texture_transform.d.ts.map +1 -0
  31. package/dist/lib/extensions/KHR_texture_transform.js +230 -0
  32. package/dist/lib/extensions/deprecated/EXT_feature_metadata.d.ts +6 -0
  33. package/dist/lib/extensions/deprecated/EXT_feature_metadata.d.ts.map +1 -0
  34. package/dist/lib/extensions/deprecated/EXT_feature_metadata.js +118 -0
  35. package/dist/lib/gltf-utils/gltf-constants.d.ts +17 -0
  36. package/dist/lib/gltf-utils/gltf-constants.d.ts.map +1 -1
  37. package/dist/lib/gltf-utils/gltf-constants.js +5 -5
  38. package/dist/lib/types/gltf-json-schema.d.ts +386 -2
  39. package/dist/lib/types/gltf-json-schema.d.ts.map +1 -1
  40. package/dist/lib/types/gltf-types.d.ts +2 -2
  41. package/dist/lib/types/gltf-types.d.ts.map +1 -1
  42. package/package.json +7 -6
  43. package/src/index.ts +2 -1
  44. package/src/lib/api/gltf-extensions.ts +13 -2
  45. package/src/lib/extensions/KHR_texture_transform.ts +305 -0
  46. package/src/lib/extensions/deprecated/EXT_feature_metadata.ts +163 -0
  47. package/src/lib/gltf-utils/gltf-constants.ts +2 -2
  48. package/src/lib/types/gltf-json-schema.ts +431 -2
  49. package/src/lib/types/gltf-types.ts +4 -2
@@ -0,0 +1,305 @@
1
+ /**
2
+ * https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_texture_transform/README.md
3
+ */
4
+
5
+ import {Vector3, Matrix3} from '@math.gl/core';
6
+ import type {GLTFMeshPrimitive, GLTFWithBuffers} from '../types/gltf-types';
7
+ import type {GLTFLoaderOptions} from '../../gltf-loader';
8
+ import {getAccessorArrayTypeAndLength} from '../gltf-utils/gltf-utils';
9
+ import {BYTES, COMPONENTS} from '../gltf-utils/gltf-constants';
10
+ import {
11
+ Accessor,
12
+ BufferView,
13
+ MaterialNormalTextureInfo,
14
+ MaterialOcclusionTextureInfo,
15
+ TextureInfo as GLTFTextureInfo
16
+ } from '../types/gltf-json-schema';
17
+ import GLTFScenegraph from '../api/gltf-scenegraph';
18
+
19
+ /** Extension name */
20
+ const EXT_MESHOPT_TRANSFORM = 'KHR_texture_transform';
21
+
22
+ export const name = EXT_MESHOPT_TRANSFORM;
23
+
24
+ const scratchVector = new Vector3();
25
+ const scratchRotationMatrix = new Matrix3();
26
+ const scratchScaleMatrix = new Matrix3();
27
+
28
+ /** Extension textureInfo https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform#gltf-schema-updates */
29
+ type TextureInfo = {
30
+ /** The offset of the UV coordinate origin as a factor of the texture dimensions. */
31
+ offset?: [number, number];
32
+ /** Rotate the UVs by this many radians counter-clockwise around the origin. This is equivalent to a similar rotation of the image clockwise. */
33
+ rotation?: number;
34
+ /** The scale factor applied to the components of the UV coordinates. */
35
+ scale?: [number, number];
36
+ /** Overrides the textureInfo texCoord value if supplied, and if this extension is supported. */
37
+ texCoord?: number;
38
+ };
39
+ /** Intersection of all GLTF textures */
40
+ type CompoundGLTFTextureInfo = GLTFTextureInfo &
41
+ MaterialNormalTextureInfo &
42
+ MaterialOcclusionTextureInfo;
43
+ /** Parameters for TEXCOORD transformation */
44
+ type TransformParameters = {
45
+ /** Original texCoord value https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_textureinfo_texcoord */
46
+ originalTexCoord: number;
47
+ /** New texCoord value from extension https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform#gltf-schema-updates */
48
+ texCoord: number;
49
+ /** Transformation matrix */
50
+ matrix: Matrix3;
51
+ };
52
+
53
+ /**
54
+ * The extension entry to process the transformation
55
+ * @param gltfData gltf buffers and json
56
+ * @param options GLTFLoader options
57
+ */
58
+ export async function decode(gltfData: GLTFWithBuffers, options: GLTFLoaderOptions) {
59
+ const gltfScenegraph = new GLTFScenegraph(gltfData);
60
+ const extension = gltfScenegraph.getExtension(EXT_MESHOPT_TRANSFORM);
61
+ if (!extension) {
62
+ return;
63
+ }
64
+ const materials = gltfData.json.materials || [];
65
+ for (let i = 0; i < materials.length; i++) {
66
+ transformTexCoords(i, gltfData);
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Transform TEXCOORD by material
72
+ * @param materialIndex processing material index
73
+ * @param gltfData gltf buffers and json
74
+ */
75
+ function transformTexCoords(materialIndex: number, gltfData: GLTFWithBuffers): void {
76
+ // Save processed texCoords in order no to process the same twice
77
+ const processedTexCoords: [number, number][] = [];
78
+ const material = gltfData.json.materials?.[materialIndex];
79
+ const baseColorTexture = material?.pbrMetallicRoughness?.baseColorTexture;
80
+ if (baseColorTexture) {
81
+ transformPrimitives(gltfData, materialIndex, baseColorTexture, processedTexCoords);
82
+ }
83
+ const emisiveTexture = material?.emissiveTexture;
84
+ if (emisiveTexture) {
85
+ transformPrimitives(gltfData, materialIndex, emisiveTexture, processedTexCoords);
86
+ }
87
+ const normalTexture = material?.normalTexture;
88
+ if (normalTexture) {
89
+ transformPrimitives(gltfData, materialIndex, normalTexture, processedTexCoords);
90
+ }
91
+ const occlusionTexture = material?.occlusionTexture;
92
+ if (occlusionTexture) {
93
+ transformPrimitives(gltfData, materialIndex, occlusionTexture, processedTexCoords);
94
+ }
95
+ const metallicRoughnessTexture = material?.pbrMetallicRoughness?.metallicRoughnessTexture;
96
+ if (metallicRoughnessTexture) {
97
+ transformPrimitives(gltfData, materialIndex, metallicRoughnessTexture, processedTexCoords);
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Transform primitives of the particular material
103
+ * @param gltfData gltf data
104
+ * @param materialIndex primitives with this material will be transformed
105
+ * @param texture texture object
106
+ * @param processedTexCoords storage to save already processed texCoords
107
+ */
108
+ function transformPrimitives(
109
+ gltfData: GLTFWithBuffers,
110
+ materialIndex: number,
111
+ texture: CompoundGLTFTextureInfo,
112
+ processedTexCoords: [number, number][]
113
+ ) {
114
+ const transformParameters = getTransformParameters(texture, processedTexCoords);
115
+ if (!transformParameters) {
116
+ return;
117
+ }
118
+ const meshes = gltfData.json.meshes || [];
119
+ for (const mesh of meshes) {
120
+ for (const primitive of mesh.primitives) {
121
+ const material = primitive.material;
122
+ if (Number.isFinite(material) && materialIndex === material) {
123
+ transformPrimitive(gltfData, primitive, transformParameters);
124
+ }
125
+ }
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Get parameters for TEXCOORD transformation
131
+ * @param texture texture object
132
+ * @param processedTexCoords storage to save already processed texCoords
133
+ * @returns texCoord couple and transformation matrix
134
+ */
135
+ function getTransformParameters(
136
+ texture: CompoundGLTFTextureInfo,
137
+ processedTexCoords: [number, number][]
138
+ ): TransformParameters | null {
139
+ const textureInfo = texture.extensions?.[EXT_MESHOPT_TRANSFORM];
140
+ const {texCoord: originalTexCoord = 0} = texture;
141
+ // If texCoord is not set in the extension, original attribute data will be replaced
142
+ const {texCoord = originalTexCoord} = textureInfo;
143
+ // Make sure that couple [originalTexCoord, extensionTexCoord] is not processed twice
144
+ const isProcessed =
145
+ processedTexCoords.findIndex(
146
+ ([original, newTexCoord]) => original === originalTexCoord && newTexCoord === texCoord
147
+ ) !== -1;
148
+ if (!isProcessed) {
149
+ const matrix = makeTransformationMatrix(textureInfo);
150
+ if (originalTexCoord !== texCoord) {
151
+ texture.texCoord = texCoord;
152
+ }
153
+ processedTexCoords.push([originalTexCoord, texCoord]);
154
+ return {originalTexCoord, texCoord, matrix};
155
+ }
156
+ return null;
157
+ }
158
+
159
+ /**
160
+ * Transform `TEXCOORD_0` attribute in the primitive
161
+ * @param gltfData gltf data
162
+ * @param primitive primitive object
163
+ * @param transformParameters texCoord couple and transformation matrix
164
+ */
165
+ function transformPrimitive(
166
+ gltfData: GLTFWithBuffers,
167
+ primitive: GLTFMeshPrimitive,
168
+ transformParameters: TransformParameters
169
+ ) {
170
+ const {originalTexCoord, texCoord, matrix} = transformParameters;
171
+ const texCoordAccessor = primitive.attributes[`TEXCOORD_${originalTexCoord}`];
172
+ if (Number.isFinite(texCoordAccessor)) {
173
+ // Get accessor of the `TEXCOORD_0` attribute
174
+ const accessor = gltfData.json.accessors?.[texCoordAccessor];
175
+ if (accessor && accessor.bufferView) {
176
+ // Get `bufferView` of the `accessor`
177
+ const bufferView = gltfData.json.bufferViews?.[accessor.bufferView];
178
+ if (bufferView) {
179
+ // Get `arrayBuffer` the `bufferView` look at
180
+ const {arrayBuffer, byteOffset: bufferByteOffset} = gltfData.buffers[bufferView.buffer];
181
+ // Resulting byteOffset is sum of the buffer, accessor and bufferView byte offsets
182
+ const byteOffset =
183
+ (bufferByteOffset || 0) + (accessor.byteOffset || 0) + (bufferView.byteOffset || 0);
184
+ // Deduce TypedArray type and its length from `accessor` and `bufferView` data
185
+ const {ArrayType, length} = getAccessorArrayTypeAndLength(accessor, bufferView);
186
+ // Number of bytes each component occupies
187
+ const bytes = BYTES[accessor.componentType];
188
+ // Number of components. For the `TEXCOORD_0` with `VEC2` type, it must return 2
189
+ const components = COMPONENTS[accessor.type];
190
+ // Multiplier to calculate the address of the `TEXCOORD_0` element in the arrayBuffer
191
+ const elementAddressScale = bufferView.byteStride || bytes * components;
192
+ // Data transform to Float32Array
193
+ const result = new Float32Array(length);
194
+ for (let i = 0; i < accessor.count; i++) {
195
+ // Take [u, v] couple from the arrayBuffer
196
+ const uv = new ArrayType(arrayBuffer, byteOffset + i * elementAddressScale, 2);
197
+ // Set and transform Vector3 per https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform#overview
198
+ scratchVector.set(uv[0], uv[1], 1);
199
+ scratchVector.transformByMatrix3(matrix);
200
+ // Save result in Float32Array
201
+ result.set([scratchVector[0], scratchVector[1]], i * components);
202
+ }
203
+ // If texCoord the same, replace gltf structural data
204
+ if (originalTexCoord === texCoord) {
205
+ updateGltf(accessor, bufferView, gltfData.buffers, result);
206
+ } else {
207
+ // If texCoord change, create new attribute
208
+ createAttribute(texCoord, accessor, primitive, gltfData, result);
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Update GLTF structural objects with new data as we create new `Float32Array` for `TEXCOORD_0`.
217
+ * @param accessor accessor to change
218
+ * @param bufferView bufferView to change
219
+ * @param buffers binary buffers
220
+ * @param newTexcoordArray typed array with data after transformation
221
+ */
222
+ function updateGltf(
223
+ accessor: Accessor,
224
+ bufferView: BufferView,
225
+ buffers: {arrayBuffer: ArrayBuffer; byteOffset: number; byteLength: number}[],
226
+ newTexCoordArray: Float32Array
227
+ ): void {
228
+ accessor.componentType = 5126;
229
+ buffers.push({
230
+ arrayBuffer: newTexCoordArray.buffer,
231
+ byteOffset: 0,
232
+ byteLength: newTexCoordArray.buffer.byteLength
233
+ });
234
+ bufferView.buffer = buffers.length - 1;
235
+ bufferView.byteLength = newTexCoordArray.buffer.byteLength;
236
+ bufferView.byteOffset = 0;
237
+ delete bufferView.byteStride;
238
+ }
239
+
240
+ /**
241
+ *
242
+ * @param newTexCoord new `texCoord` value
243
+ * @param originalAccessor original accessor object, that store data before transformation
244
+ * @param primitive primitive object
245
+ * @param gltfData gltf data
246
+ * @param newTexCoordArray typed array with data after transformation
247
+ * @returns
248
+ */
249
+ function createAttribute(
250
+ newTexCoord: number,
251
+ originalAccessor: Accessor,
252
+ primitive: GLTFMeshPrimitive,
253
+ gltfData: GLTFWithBuffers,
254
+ newTexCoordArray: Float32Array
255
+ ) {
256
+ gltfData.buffers.push({
257
+ arrayBuffer: newTexCoordArray.buffer,
258
+ byteOffset: 0,
259
+ byteLength: newTexCoordArray.buffer.byteLength
260
+ });
261
+ const bufferViews = gltfData.json.bufferViews;
262
+ if (!bufferViews) {
263
+ return;
264
+ }
265
+ bufferViews.push({
266
+ buffer: gltfData.buffers.length - 1,
267
+ byteLength: newTexCoordArray.buffer.byteLength,
268
+ byteOffset: 0
269
+ });
270
+ const accessors = gltfData.json.accessors;
271
+ if (!accessors) {
272
+ return;
273
+ }
274
+ accessors.push({
275
+ bufferView: bufferViews?.length - 1,
276
+ byteOffset: 0,
277
+ componentType: 5126,
278
+ count: originalAccessor.count,
279
+ type: 'VEC2'
280
+ });
281
+ primitive.attributes[`TEXCOORD_${newTexCoord}`] = accessors.length - 1;
282
+ }
283
+
284
+ /**
285
+ * Construct transformation matrix from the extension data (transition, rotation, scale)
286
+ * @param extensionData extension data
287
+ * @returns transformation matrix
288
+ */
289
+ function makeTransformationMatrix(extensionData: TextureInfo): Matrix3 {
290
+ const {offset = [0, 0], rotation = 0, scale = [1, 1]} = extensionData;
291
+ const translationMatirx = new Matrix3().set(1, 0, 0, 0, 1, 0, offset[0], offset[1], 1);
292
+ const rotationMatirx = scratchRotationMatrix.set(
293
+ Math.cos(rotation),
294
+ Math.sin(rotation),
295
+ 0,
296
+ -Math.sin(rotation),
297
+ Math.cos(rotation),
298
+ 0,
299
+ 0,
300
+ 0,
301
+ 1
302
+ );
303
+ const scaleMatrix = scratchScaleMatrix.set(scale[0], 0, 0, 0, scale[1], 0, 0, 0, 1);
304
+ return translationMatirx.multiplyRight(rotationMatirx).multiplyRight(scaleMatrix);
305
+ }
@@ -0,0 +1,163 @@
1
+ /* eslint-disable camelcase */
2
+ import type {GLTF} from '../../types/gltf-types';
3
+
4
+ import GLTFScenegraph from '../../api/gltf-scenegraph';
5
+ import {
6
+ ClassProperty,
7
+ EXT_feature_metadata_class_object,
8
+ EXT_feature_metadata_feature_table,
9
+ FeatureTableProperty,
10
+ GLTF_EXT_feature_metadata
11
+ } from '../../types/gltf-json-schema';
12
+
13
+ /** Extension name */
14
+ const EXT_FEATURE_METADATA = 'EXT_feature_metadata';
15
+
16
+ export const name = EXT_FEATURE_METADATA;
17
+
18
+ export async function decode(gltfData: {json: GLTF}): Promise<void> {
19
+ const scenegraph = new GLTFScenegraph(gltfData);
20
+ decodeExtFeatureMetadata(scenegraph);
21
+ }
22
+
23
+ /**
24
+ * Decodes feature metadata from extension
25
+ * @param scenegraph
26
+ */
27
+ function decodeExtFeatureMetadata(scenegraph: GLTFScenegraph): void {
28
+ const extension: GLTF_EXT_feature_metadata | null = scenegraph.getExtension(EXT_FEATURE_METADATA);
29
+ const schemaClasses = extension?.schema?.classes;
30
+ const featureTables = extension?.featureTables;
31
+ const featureTextures = extension?.featureTextures;
32
+
33
+ if (featureTextures) {
34
+ /*
35
+ * TODO add support for featureTextures
36
+ * Spec - https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_feature_metadata#feature-textures
37
+ */
38
+ // eslint-disable-next-line no-console
39
+ console.warn('featureTextures is not yet supported in the "EXT_feature_metadata" extension.');
40
+ }
41
+
42
+ if (schemaClasses && featureTables) {
43
+ for (const schemaName in schemaClasses) {
44
+ const schemaClass = schemaClasses[schemaName];
45
+ const featureTable = findFeatureTableByName(featureTables, schemaName);
46
+
47
+ if (featureTable) {
48
+ handleFeatureTableProperties(scenegraph, featureTable, schemaClass);
49
+ }
50
+ }
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Navigate throw all properies in feature table and gets properties data.
56
+ * @param scenegraph
57
+ * @param featureTable
58
+ * @param schemaClass
59
+ */
60
+ function handleFeatureTableProperties(
61
+ scenegraph: GLTFScenegraph,
62
+ featureTable: EXT_feature_metadata_feature_table,
63
+ schemaClass: EXT_feature_metadata_class_object
64
+ ): void {
65
+ for (const propertyName in schemaClass.properties) {
66
+ const schemaProperty = schemaClass.properties[propertyName];
67
+ const featureTableProperty = featureTable?.properties?.[propertyName];
68
+ const numberOfFeatures = featureTable.count;
69
+
70
+ if (featureTableProperty) {
71
+ const data = getPropertyDataFromBinarySource(
72
+ scenegraph,
73
+ schemaProperty,
74
+ numberOfFeatures,
75
+ featureTableProperty
76
+ );
77
+ featureTableProperty.data = data;
78
+ }
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Decode properties from binary sourse based on property type.
84
+ * @param scenegraph
85
+ * @param schemaProperty
86
+ * @param numberOfFeatures
87
+ * @param featureTableProperty
88
+ */
89
+ function getPropertyDataFromBinarySource(
90
+ scenegraph: GLTFScenegraph,
91
+ schemaProperty: ClassProperty,
92
+ numberOfFeatures: number,
93
+ featureTableProperty: FeatureTableProperty
94
+ ): Uint8Array | string[] {
95
+ const bufferView = featureTableProperty.bufferView;
96
+ // TODO think maybe we shouldn't get data only in Uint8Array format.
97
+ let data: Uint8Array | string[] = scenegraph.getTypedArrayForBufferView(bufferView);
98
+
99
+ switch (schemaProperty.type) {
100
+ case 'STRING': {
101
+ // stringOffsetBufferView should be available for string type.
102
+ const stringOffsetBufferView = featureTableProperty.stringOffsetBufferView!;
103
+ const offsetsData = scenegraph.getTypedArrayForBufferView(stringOffsetBufferView);
104
+ data = getStringAttributes(data, offsetsData, numberOfFeatures);
105
+ break;
106
+ }
107
+ default:
108
+ }
109
+
110
+ return data;
111
+ }
112
+
113
+ /**
114
+ * Find the feature table by class name.
115
+ * @param featureTables
116
+ * @param schemaClassName
117
+ */
118
+ function findFeatureTableByName(
119
+ featureTables: {[key: string]: EXT_feature_metadata_feature_table},
120
+ schemaClassName: string
121
+ ): EXT_feature_metadata_feature_table | null {
122
+ for (const featureTableName in featureTables) {
123
+ const featureTable = featureTables[featureTableName];
124
+
125
+ if (featureTable.class === schemaClassName) {
126
+ return featureTable;
127
+ }
128
+ }
129
+
130
+ return null;
131
+ }
132
+
133
+ /**
134
+ * Getting string attributes from binary data.
135
+ * Spec - https://github.com/CesiumGS/3d-tiles/tree/main/specification/Metadata#strings
136
+ * @param data
137
+ * @param offsetsData
138
+ * @param stringsCount
139
+ */
140
+ function getStringAttributes(
141
+ data: Uint8Array,
142
+ offsetsData: Uint8Array,
143
+ stringsCount: number
144
+ ): string[] {
145
+ const stringsArray: string[] = [];
146
+ const textDecoder = new TextDecoder('utf8');
147
+
148
+ let stringOffset = 0;
149
+ const bytesPerStringSize = 4;
150
+
151
+ for (let index = 0; index < stringsCount; index++) {
152
+ // TODO check if it is multiplication on bytesPerStringSize is valid operation?
153
+ const stringByteSize =
154
+ offsetsData[(index + 1) * bytesPerStringSize] - offsetsData[index * bytesPerStringSize];
155
+ const stringData = data.subarray(stringOffset, stringByteSize + stringOffset);
156
+ const stringAttribute = textDecoder.decode(stringData);
157
+
158
+ stringsArray.push(stringAttribute);
159
+ stringOffset += stringByteSize;
160
+ }
161
+
162
+ return stringsArray;
163
+ }
@@ -1,4 +1,4 @@
1
- const COMPONENTS = {
1
+ export const COMPONENTS = {
2
2
  SCALAR: 1,
3
3
  VEC2: 2,
4
4
  VEC3: 3,
@@ -8,7 +8,7 @@ const COMPONENTS = {
8
8
  MAT4: 16
9
9
  };
10
10
 
11
- const BYTES = {
11
+ export const BYTES = {
12
12
  5120: 1, // BYTE
13
13
  5121: 1, // UNSIGNED_BYTE
14
14
  5122: 2, // SHORT