freeform-modeling-mcp 1.0.26

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 (81) hide show
  1. package/README.md +61 -0
  2. package/index.cjs +21 -0
  3. package/package.json +48 -0
  4. package/src/cli.ts +47 -0
  5. package/src/commands/start.ts +88 -0
  6. package/src/commands/status.ts +81 -0
  7. package/src/dev.ts +24 -0
  8. package/src/lib/fileproxy/index.ts +505 -0
  9. package/src/lib/fileproxy/proxy-server.js +347 -0
  10. package/src/lib/gltf2obj/compress.js +33 -0
  11. package/src/lib/gltf2obj/engine/core/core.js +34 -0
  12. package/src/lib/gltf2obj/engine/core/eventnotifier.js +39 -0
  13. package/src/lib/gltf2obj/engine/core/taskrunner.js +88 -0
  14. package/src/lib/gltf2obj/engine/export/exporter.js +38 -0
  15. package/src/lib/gltf2obj/engine/export/exporterbase.js +86 -0
  16. package/src/lib/gltf2obj/engine/export/exportermodel.js +117 -0
  17. package/src/lib/gltf2obj/engine/export/exporterobj.js +147 -0
  18. package/src/lib/gltf2obj/engine/geometry/box3d.js +60 -0
  19. package/src/lib/gltf2obj/engine/geometry/coord2d.js +35 -0
  20. package/src/lib/gltf2obj/engine/geometry/coord3d.js +126 -0
  21. package/src/lib/gltf2obj/engine/geometry/coord4d.js +15 -0
  22. package/src/lib/gltf2obj/engine/geometry/geometry.js +56 -0
  23. package/src/lib/gltf2obj/engine/geometry/matrix.js +440 -0
  24. package/src/lib/gltf2obj/engine/geometry/octree.js +160 -0
  25. package/src/lib/gltf2obj/engine/geometry/quaternion.js +83 -0
  26. package/src/lib/gltf2obj/engine/geometry/transformation.js +63 -0
  27. package/src/lib/gltf2obj/engine/geometry/tween.js +31 -0
  28. package/src/lib/gltf2obj/engine/import/importer.js +270 -0
  29. package/src/lib/gltf2obj/engine/import/importerbase.js +115 -0
  30. package/src/lib/gltf2obj/engine/import/importerfiles.js +139 -0
  31. package/src/lib/gltf2obj/engine/import/importergltf.js +1045 -0
  32. package/src/lib/gltf2obj/engine/import/importerutils.js +102 -0
  33. package/src/lib/gltf2obj/engine/io/binaryreader.js +93 -0
  34. package/src/lib/gltf2obj/engine/io/binarywriter.js +92 -0
  35. package/src/lib/gltf2obj/engine/io/bufferutils.js +85 -0
  36. package/src/lib/gltf2obj/engine/io/externallibs.js +42 -0
  37. package/src/lib/gltf2obj/engine/io/fileutils.js +120 -0
  38. package/src/lib/gltf2obj/engine/io/textwriter.js +41 -0
  39. package/src/lib/gltf2obj/engine/main.js +19 -0
  40. package/src/lib/gltf2obj/engine/model/color.js +130 -0
  41. package/src/lib/gltf2obj/engine/model/generator.js +433 -0
  42. package/src/lib/gltf2obj/engine/model/material.js +243 -0
  43. package/src/lib/gltf2obj/engine/model/mesh.js +173 -0
  44. package/src/lib/gltf2obj/engine/model/meshbuffer.js +233 -0
  45. package/src/lib/gltf2obj/engine/model/meshinstance.js +128 -0
  46. package/src/lib/gltf2obj/engine/model/meshutils.js +64 -0
  47. package/src/lib/gltf2obj/engine/model/model.js +195 -0
  48. package/src/lib/gltf2obj/engine/model/modelfinalization.js +377 -0
  49. package/src/lib/gltf2obj/engine/model/modelutils.js +117 -0
  50. package/src/lib/gltf2obj/engine/model/node.js +178 -0
  51. package/src/lib/gltf2obj/engine/model/object.js +90 -0
  52. package/src/lib/gltf2obj/engine/model/property.js +86 -0
  53. package/src/lib/gltf2obj/engine/model/quantities.js +46 -0
  54. package/src/lib/gltf2obj/engine/model/topology.js +139 -0
  55. package/src/lib/gltf2obj/engine/model/triangle.js +99 -0
  56. package/src/lib/gltf2obj/engine/threejs/threemodelloader.js +85 -0
  57. package/src/lib/gltf2obj/handler.js +63 -0
  58. package/src/lib/gltf2obj/index.js +47 -0
  59. package/src/lib/logger.ts +304 -0
  60. package/src/lib/print.ts +37 -0
  61. package/src/lib/utils.ts +34 -0
  62. package/src/lib/wsbridge/bridge.ts +639 -0
  63. package/src/lib/wsbridge/lock.ts +258 -0
  64. package/src/llmClient.ts +245 -0
  65. package/src/prompt.ts +187 -0
  66. package/src/server.ts +125 -0
  67. package/src/tools/assets-tool.ts +314 -0
  68. package/src/tools/basic-tools.ts +531 -0
  69. package/src/tools/index.ts +2 -0
  70. package/src/tools/material-tools.ts +88 -0
  71. package/src/tools/modeling/auxiliary-curve-tool.ts +44 -0
  72. package/src/tools/modeling/find-face.ts +38 -0
  73. package/src/tools/modeling/sweep-tool.ts +60 -0
  74. package/src/tools/modeling/utils.ts +181 -0
  75. package/src/tools/modeling-tools.ts +135 -0
  76. package/src/tools/screenshot-tools.ts +107 -0
  77. package/src/tools/tools-info.ts +107 -0
  78. package/src/tools/tripo3d-tools.ts +496 -0
  79. package/src/types/index.ts +25 -0
  80. package/src/types/tripo3d.ts +38 -0
  81. package/tsconfig.json +22 -0
@@ -0,0 +1,1045 @@
1
+ import { Coord2D } from '../geometry/coord2d.js';
2
+ import { ArrayToCoord3D, Coord3D } from '../geometry/coord3d.js';
3
+ import { Coord4D } from '../geometry/coord4d.js';
4
+ import { Direction } from '../geometry/geometry.js';
5
+ import { Matrix } from '../geometry/matrix.js';
6
+ import { ArrayToQuaternion } from '../geometry/quaternion.js';
7
+ import { Transformation } from '../geometry/transformation.js';
8
+ import { BinaryReader } from '../io/binaryreader.js';
9
+ import { ArrayBufferToUtf8String, Base64DataURIToArrayBuffer, GetFileExtensionFromMimeType } from '../io/bufferutils.js';
10
+ import { RGBColor, ColorComponentFromFloat, RGBColorFromFloatComponents, LinearToSRGB } from '../model/color.js';
11
+ import { PhongMaterial, PhysicalMaterial, TextureMap } from '../model/material.js';
12
+ import { Mesh } from '../model/mesh.js';
13
+ import { Node, NodeType } from '../model/node.js';
14
+ import { Property, PropertyGroup, PropertyType } from '../model/property.js';
15
+ import { Triangle } from '../model/triangle.js';
16
+ import { ImporterBase } from './importerbase.js';
17
+
18
+ import pkg from 'draco3d';
19
+ const { DracoDecoderModule } = pkg;
20
+
21
+
22
+ const GltfComponentType =
23
+ {
24
+ BYTE: 5120,
25
+ UNSIGNED_BYTE: 5121,
26
+ SHORT: 5122,
27
+ UNSIGNED_SHORT: 5123,
28
+ UNSIGNED_INT: 5125,
29
+ FLOAT: 5126
30
+ };
31
+
32
+ const GltfDataType =
33
+ {
34
+ SCALAR: 0,
35
+ VEC2: 1,
36
+ VEC3: 2,
37
+ VEC4: 3,
38
+ MAT2: 4,
39
+ MAT3: 5,
40
+ MAT4: 6
41
+ };
42
+
43
+ const GltfRenderMode =
44
+ {
45
+ POINTS: 0,
46
+ LINES: 1,
47
+ LINE_LOOP: 2,
48
+ LINE_STRIP: 3,
49
+ TRIANGLES: 4,
50
+ TRIANGLE_STRIP: 5,
51
+ TRIANGLE_FAN: 6
52
+ };
53
+
54
+ const GltfConstants =
55
+ {
56
+ GLTF_STRING: 0x46546C67,
57
+ JSON_CHUNK_TYPE: 0x4E4F534A,
58
+ BINARY_CHUNK_TYPE: 0x004E4942
59
+ };
60
+
61
+ function GetGltfColor (color) {
62
+ return RGBColorFromFloatComponents(
63
+ LinearToSRGB(color[0]),
64
+ LinearToSRGB(color[1]),
65
+ LinearToSRGB(color[2])
66
+ );
67
+ }
68
+
69
+ function GetGltfVertexColor (color, componentType) {
70
+ function GetColorComponent (component, componentType) {
71
+ let normalized = component;
72
+ if (componentType === GltfComponentType.UNSIGNED_BYTE) {
73
+ normalized /= 255.0;
74
+ } else if (componentType === GltfComponentType.UNSIGNED_SHORT) {
75
+ normalized /= 65535.0;
76
+ }
77
+ return ColorComponentFromFloat(LinearToSRGB(normalized));
78
+ }
79
+
80
+ return new RGBColor(
81
+ GetColorComponent(color[0], componentType),
82
+ GetColorComponent(color[1], componentType),
83
+ GetColorComponent(color[2], componentType)
84
+ );
85
+ }
86
+
87
+ class GltfBufferReader {
88
+ constructor(buffer) {
89
+ this.reader = new BinaryReader(buffer, true);
90
+ this.componentType = null;
91
+ this.dataType = null;
92
+ this.byteStride = null;
93
+ this.dataCount = null;
94
+ this.sparseReader = null;
95
+ }
96
+
97
+ SetComponentType (componentType) {
98
+ this.componentType = componentType;
99
+ }
100
+
101
+ SetDataType (dataType) {
102
+ if (dataType === 'SCALAR') {
103
+ this.dataType = GltfDataType.SCALAR;
104
+ } else if (dataType === 'VEC2') {
105
+ this.dataType = GltfDataType.VEC2;
106
+ } else if (dataType === 'VEC3') {
107
+ this.dataType = GltfDataType.VEC3;
108
+ } else if (dataType === 'VEC4') {
109
+ this.dataType = GltfDataType.VEC4;
110
+ } else if (dataType === 'MAT2') {
111
+ this.dataType = GltfDataType.MAT2;
112
+ } else if (dataType === 'MAT3') {
113
+ this.dataType = GltfDataType.MAT3;
114
+ } else if (dataType === 'MAT4') {
115
+ this.dataType = GltfDataType.MAT4;
116
+ }
117
+ }
118
+
119
+ SetByteStride (byteStride) {
120
+ this.byteStride = byteStride;
121
+ }
122
+
123
+ SetDataCount (dataCount) {
124
+ this.dataCount = dataCount;
125
+ }
126
+
127
+ SetSparseReader (indexReader, valueReader) {
128
+ this.sparseReader = {
129
+ indexReader: indexReader,
130
+ valueReader: valueReader
131
+ };
132
+ }
133
+
134
+ ReadArrayBuffer (byteLength) {
135
+ return this.reader.ReadArrayBuffer(byteLength);
136
+ }
137
+
138
+ GetDataCount () {
139
+ return this.dataCount;
140
+ }
141
+
142
+ ReadData () {
143
+ if (this.dataType === null) {
144
+ return null;
145
+ }
146
+ if (this.dataType === GltfDataType.SCALAR) {
147
+ let data = this.ReadComponent();
148
+ this.SkipBytesByStride(1);
149
+ return data;
150
+ } else if (this.dataType === GltfDataType.VEC2) {
151
+ let x = this.ReadComponent();
152
+ let y = this.ReadComponent();
153
+ this.SkipBytesByStride(2);
154
+ return new Coord2D(x, y);
155
+ } else if (this.dataType === GltfDataType.VEC3) {
156
+ let x = this.ReadComponent();
157
+ let y = this.ReadComponent();
158
+ let z = this.ReadComponent();
159
+ this.SkipBytesByStride(3);
160
+ return new Coord3D(x, y, z);
161
+ } else if (this.dataType === GltfDataType.VEC4) {
162
+ let x = this.ReadComponent();
163
+ let y = this.ReadComponent();
164
+ let z = this.ReadComponent();
165
+ let w = this.ReadComponent();
166
+ this.SkipBytesByStride(4);
167
+ return new Coord4D(x, y, z, w);
168
+ }
169
+ return null;
170
+ }
171
+
172
+ EnumerateData (onData) {
173
+ if (this.sparseReader === null) {
174
+ for (let i = 0; i < this.dataCount; i++) {
175
+ onData(this.ReadData());
176
+ }
177
+ } else {
178
+ let sparseData = [];
179
+ for (let i = 0; i < this.sparseReader.indexReader.GetDataCount(); i++) {
180
+ let index = this.sparseReader.indexReader.ReadData();
181
+ let value = this.sparseReader.valueReader.ReadData();
182
+ sparseData.push({
183
+ index: index,
184
+ value: value
185
+ });
186
+ }
187
+ let sparseIndex = 0;
188
+ for (let i = 0; i < this.dataCount; i++) {
189
+ let data = this.ReadData();
190
+ if (sparseIndex < sparseData.length && sparseData[sparseIndex].index === i) {
191
+ onData(sparseData[sparseIndex].value);
192
+ sparseIndex += 1;
193
+ } else {
194
+ onData(data);
195
+ }
196
+ }
197
+ }
198
+ }
199
+
200
+ SkipBytes (bytes) {
201
+ this.reader.Skip(bytes);
202
+ }
203
+
204
+ ReadComponent () {
205
+ if (this.componentType === null) {
206
+ return null;
207
+ }
208
+ if (this.componentType === GltfComponentType.BYTE) {
209
+ return this.reader.ReadCharacter8();
210
+ } else if (this.componentType === GltfComponentType.UNSIGNED_BYTE) {
211
+ return this.reader.ReadUnsignedCharacter8();
212
+ } else if (this.componentType === GltfComponentType.SHORT) {
213
+ return this.reader.ReadInteger16();
214
+ } else if (this.componentType === GltfComponentType.UNSIGNED_SHORT) {
215
+ return this.reader.ReadUnsignedInteger16();
216
+ } else if (this.componentType === GltfComponentType.UNSIGNED_INT) {
217
+ return this.reader.ReadInteger32();
218
+ } else if (this.componentType === GltfComponentType.FLOAT) {
219
+ return this.reader.ReadFloat32();
220
+ }
221
+ return null;
222
+ }
223
+
224
+ SkipBytesByStride (componentCount) {
225
+ if (this.byteStride === null) {
226
+ return;
227
+ }
228
+ let readBytes = componentCount * this.GetComponentSize();
229
+ this.reader.Skip(this.byteStride - readBytes);
230
+ }
231
+
232
+ GetComponentSize () {
233
+ if (this.componentType === GltfComponentType.BYTE) {
234
+ return 1;
235
+ } else if (this.componentType === GltfComponentType.UNSIGNED_BYTE) {
236
+ return 1;
237
+ } else if (this.componentType === GltfComponentType.SHORT) {
238
+ return 2;
239
+ } else if (this.componentType === GltfComponentType.UNSIGNED_SHORT) {
240
+ return 2;
241
+ } else if (this.componentType === GltfComponentType.UNSIGNED_INT) {
242
+ return 4;
243
+ } else if (this.componentType === GltfComponentType.FLOAT) {
244
+ return 4;
245
+ }
246
+ return 0;
247
+ }
248
+ }
249
+
250
+ class GltfExtensions {
251
+ constructor() {
252
+ this.supportedExtensions = [
253
+ 'KHR_draco_mesh_compression',
254
+ 'KHR_materials_pbrSpecularGlossiness',
255
+ 'KHR_texture_transform',
256
+ ];
257
+ this.draco = null;
258
+ }
259
+
260
+ LoadLibraries (extensionsRequired, callbacks) {
261
+ if (extensionsRequired === undefined) {
262
+ callbacks.onSuccess();
263
+ return;
264
+ }
265
+ if (this.draco === null && extensionsRequired.indexOf('KHR_draco_mesh_compression') !== -1) {
266
+ this.draco = DracoDecoderModule();
267
+ callbacks.onSuccess();
268
+ } else {
269
+ callbacks.onSuccess();
270
+ }
271
+ }
272
+
273
+ GetUnsupportedExtensions (extensionsRequired) {
274
+ let unsupportedExtensions = [];
275
+ if (extensionsRequired === undefined) {
276
+ return unsupportedExtensions;
277
+ }
278
+ for (let i = 0; i < extensionsRequired.length; i++) {
279
+ let requiredExtension = extensionsRequired[i];
280
+ if (this.supportedExtensions.indexOf(requiredExtension) === -1) {
281
+ unsupportedExtensions.push(requiredExtension);
282
+ }
283
+ }
284
+ return unsupportedExtensions;
285
+ }
286
+
287
+ ProcessMaterial (gltfMaterial, material, imporTextureFn) {
288
+ if (gltfMaterial.extensions === undefined) {
289
+ return null;
290
+ }
291
+
292
+ let khrSpecularGlossiness = gltfMaterial.extensions.KHR_materials_pbrSpecularGlossiness;
293
+ if (khrSpecularGlossiness === undefined) {
294
+ return null;
295
+ }
296
+
297
+ let phongMaterial = new PhongMaterial();
298
+ let diffuseColor = khrSpecularGlossiness.diffuseFactor;
299
+ if (diffuseColor !== undefined) {
300
+ phongMaterial.color = GetGltfColor(diffuseColor);
301
+ phongMaterial.opacity = diffuseColor[3];
302
+ }
303
+ let diffuseTexture = khrSpecularGlossiness.diffuseTexture;
304
+ if (diffuseTexture !== undefined) {
305
+ phongMaterial.diffuseMap = imporTextureFn(diffuseTexture);
306
+ }
307
+ let specularColor = khrSpecularGlossiness.specularFactor;
308
+ if (specularColor !== undefined) {
309
+ phongMaterial.specular = GetGltfColor(specularColor);
310
+ }
311
+ let specularTexture = khrSpecularGlossiness.specularGlossinessTexture;
312
+ if (specularTexture !== undefined) {
313
+ phongMaterial.specularMap = imporTextureFn(specularTexture);
314
+ }
315
+ let glossiness = khrSpecularGlossiness.glossinessFactor;
316
+ if (glossiness !== undefined) {
317
+ phongMaterial.shininess = glossiness;
318
+ }
319
+
320
+ return phongMaterial;
321
+ }
322
+
323
+ ProcessTexture (gltfTexture, texture) {
324
+ if (gltfTexture.extensions === undefined) {
325
+ return;
326
+ }
327
+ let khrTextureTransform = gltfTexture.extensions.KHR_texture_transform;
328
+ if (khrTextureTransform !== undefined) {
329
+ if (khrTextureTransform.offset !== undefined) {
330
+ texture.offset.x = khrTextureTransform.offset[0];
331
+ texture.offset.y = -khrTextureTransform.offset[1];
332
+ }
333
+ if (khrTextureTransform.scale !== undefined) {
334
+ texture.scale.x = khrTextureTransform.scale[0];
335
+ texture.scale.y = khrTextureTransform.scale[1];
336
+ }
337
+ if (khrTextureTransform.rotation !== undefined) {
338
+ texture.rotation = -khrTextureTransform.rotation;
339
+ }
340
+ }
341
+ }
342
+
343
+ ProcessPrimitive (importer, gltf, primitive, mesh) {
344
+ function EnumerateComponents (draco, decoder, dracoMesh, attributeId, processor) {
345
+ let attribute = decoder.GetAttributeByUniqueId(dracoMesh, attributeId);
346
+ let numComponents = attribute.num_components();
347
+ let numPoints = dracoMesh.num_points();
348
+ let numValues = numPoints * numComponents;
349
+ let dataSize = numValues * 4;
350
+ let attributePtr = draco._malloc(dataSize);
351
+ decoder.GetAttributeDataArrayForAllPoints(dracoMesh, attribute, draco.DT_FLOAT32, dataSize, attributePtr);
352
+ let attributeArray = new Float32Array(draco.HEAPF32.buffer, attributePtr, numValues).slice();
353
+ if (numComponents === 2) {
354
+ for (let i = 0; i < attributeArray.length; i += 2) {
355
+ processor(new Coord2D(
356
+ attributeArray[i + 0],
357
+ attributeArray[i + 1]
358
+ ));
359
+ }
360
+ } else if (numComponents === 3) {
361
+ for (let i = 0; i < attributeArray.length; i += 3) {
362
+ processor(new Coord3D(
363
+ attributeArray[i + 0],
364
+ attributeArray[i + 1],
365
+ attributeArray[i + 2]
366
+ ));
367
+ }
368
+ } else if (numComponents === 4) {
369
+ for (let i = 0; i < attributeArray.length; i += 4) {
370
+ processor(new Coord4D(
371
+ attributeArray[i + 0],
372
+ attributeArray[i + 1],
373
+ attributeArray[i + 2],
374
+ attributeArray[i + 3]
375
+ ));
376
+ }
377
+ }
378
+ draco._free(attributePtr);
379
+ }
380
+
381
+ if (this.draco === null) {
382
+ return false;
383
+ }
384
+
385
+ if (primitive.extensions === undefined || primitive.extensions.KHR_draco_mesh_compression === undefined) {
386
+ return false;
387
+ }
388
+
389
+ let decoder = new this.draco.Decoder();
390
+ let decoderBuffer = new this.draco.DecoderBuffer();
391
+
392
+ let extensionParams = primitive.extensions.KHR_draco_mesh_compression;
393
+ let compressedBufferView = gltf.bufferViews[extensionParams.bufferView];
394
+ let compressedReader = importer.GetReaderFromBufferView(compressedBufferView);
395
+ let compressedArrayBuffer = compressedReader.ReadArrayBuffer(compressedBufferView.byteLength);
396
+ decoderBuffer.Init(new Int8Array(compressedArrayBuffer), compressedArrayBuffer.byteLength);
397
+ let geometryType = decoder.GetEncodedGeometryType(decoderBuffer);
398
+ if (geometryType !== this.draco.TRIANGULAR_MESH) {
399
+ return true;
400
+ }
401
+
402
+ let dracoMesh = new this.draco.Mesh();
403
+ let decodingStatus = decoder.DecodeBufferToMesh(decoderBuffer, dracoMesh);
404
+ if (!decodingStatus.ok()) {
405
+ return true;
406
+ }
407
+
408
+ let hasVertices = (extensionParams.attributes.POSITION !== undefined);
409
+ let hasVertexColors = false;
410
+ let hasNormals = (extensionParams.attributes.NORMAL !== undefined);
411
+ let hasUVs = (extensionParams.attributes.TEXCOORD_0 !== undefined);
412
+
413
+ if (!hasVertices) {
414
+ return true;
415
+ }
416
+
417
+ let vertexOffset = mesh.VertexCount();
418
+ let vertexColorOffset = mesh.VertexColorCount();
419
+ let normalOffset = mesh.NormalCount();
420
+ let uvOffset = mesh.TextureUVCount();
421
+
422
+ EnumerateComponents(this.draco, decoder, dracoMesh, extensionParams.attributes.POSITION, (vertex) => {
423
+ mesh.AddVertex(vertex);
424
+ });
425
+
426
+ if (hasNormals) {
427
+ EnumerateComponents(this.draco, decoder, dracoMesh, extensionParams.attributes.NORMAL, (normal) => {
428
+ mesh.AddNormal(normal);
429
+ });
430
+ }
431
+
432
+ if (hasUVs) {
433
+ EnumerateComponents(this.draco, decoder, dracoMesh, extensionParams.attributes.TEXCOORD_0, (uv) => {
434
+ uv.y = -uv.y;
435
+ mesh.AddTextureUV(uv);
436
+ });
437
+ }
438
+
439
+ let faceCount = dracoMesh.num_faces();
440
+ let indexCount = faceCount * 3;
441
+ let indexDataSize = indexCount * 4;
442
+ let indexDataPtr = this.draco._malloc(indexDataSize);
443
+ decoder.GetTrianglesUInt32Array(dracoMesh, indexDataSize, indexDataPtr);
444
+ let indexArray = new Uint32Array(this.draco.HEAPU32.buffer, indexDataPtr, indexCount).slice();
445
+ for (let i = 0; i < indexArray.length; i += 3) {
446
+ let v0 = indexArray[i];
447
+ let v1 = indexArray[i + 1];
448
+ let v2 = indexArray[i + 2];
449
+ importer.AddTriangle(primitive, mesh, v0, v1, v2, hasVertexColors, hasNormals, hasUVs, vertexOffset, vertexColorOffset, normalOffset, uvOffset);
450
+ }
451
+ this.draco._free(indexDataPtr);
452
+
453
+ return true;
454
+ }
455
+ }
456
+
457
+ export class ImporterGltf extends ImporterBase {
458
+ constructor() {
459
+ super();
460
+ this.gltfExtensions = new GltfExtensions();
461
+ }
462
+
463
+ CanImportExtension (extension) {
464
+ return extension === 'gltf' || extension === 'glb';
465
+ }
466
+
467
+ GetUpDirection () {
468
+ return Direction.Y;
469
+ }
470
+
471
+ ClearContent () {
472
+ this.bufferContents = null;
473
+ this.imageIndexToTextureParams = null;
474
+ }
475
+
476
+ ResetContent () {
477
+ this.bufferContents = [];
478
+ this.imageIndexToTextureParams = new Map();
479
+ }
480
+
481
+ ImportContent (fileContent, onFinish) {
482
+ if (this.extension === 'gltf') {
483
+ this.ProcessGltf(fileContent, onFinish);
484
+ } else if (this.extension === 'glb') {
485
+ this.ProcessBinaryGltf(fileContent, onFinish);
486
+ }
487
+ }
488
+
489
+ ProcessGltf (fileContent, onFinish) {
490
+ let textContent = ArrayBufferToUtf8String(fileContent);
491
+ let gltf = JSON.parse(textContent);
492
+ if (gltf.asset.version !== '2.0') {
493
+ this.SetError('Invalid glTF version.');
494
+ onFinish();
495
+ return;
496
+ }
497
+
498
+ for (let i = 0; i < gltf.buffers.length; i++) {
499
+ let buffer = null;
500
+ let gltfBuffer = gltf.buffers[i];
501
+ let base64Buffer = Base64DataURIToArrayBuffer(gltfBuffer.uri);
502
+ if (base64Buffer !== null) {
503
+ buffer = base64Buffer.buffer;
504
+ } else {
505
+ let fileBuffer = this.callbacks.getFileBuffer(gltfBuffer.uri);
506
+ if (fileBuffer !== null) {
507
+ buffer = fileBuffer;
508
+ }
509
+ }
510
+ if (buffer === null) {
511
+ this.SetError('One of the requested buffers is missing.');
512
+ onFinish();
513
+ return;
514
+ }
515
+ this.bufferContents.push(buffer);
516
+ }
517
+
518
+ this.ProcessMainFile(gltf, onFinish);
519
+ }
520
+
521
+ ProcessBinaryGltf (fileContent, onFinish) {
522
+ function ReadChunk (reader) {
523
+ let length = reader.ReadUnsignedInteger32();
524
+ let type = reader.ReadUnsignedInteger32();
525
+ let buffer = reader.ReadArrayBuffer(length);
526
+ return {
527
+ type: type,
528
+ buffer: buffer
529
+ };
530
+ }
531
+ let reader = new BinaryReader(fileContent, true);
532
+ let magic = reader.ReadUnsignedInteger32();
533
+ if (magic !== GltfConstants.GLTF_STRING) {
534
+ this.SetError('Invalid glTF file.');
535
+ onFinish();
536
+ return;
537
+ }
538
+ let version = reader.ReadUnsignedInteger32();
539
+ if (version !== 2) {
540
+ this.SetError('Invalid glTF version.');
541
+ onFinish();
542
+ return;
543
+ }
544
+ let length = reader.ReadUnsignedInteger32();
545
+ if (length !== reader.GetByteLength()) {
546
+ this.SetError('Invalid glTF file.');
547
+ onFinish();
548
+ return;
549
+ }
550
+
551
+ let gltfTextContent = null;
552
+ while (!reader.End()) {
553
+ let chunk = ReadChunk(reader);
554
+ if (chunk.type === GltfConstants.JSON_CHUNK_TYPE) {
555
+ gltfTextContent = ArrayBufferToUtf8String(chunk.buffer);
556
+ } else if (chunk.type === GltfConstants.BINARY_CHUNK_TYPE) {
557
+ this.bufferContents.push(chunk.buffer);
558
+ }
559
+ }
560
+
561
+ if (gltfTextContent !== null) {
562
+ let gltf = JSON.parse(gltfTextContent);
563
+ this.ProcessMainFile(gltf, onFinish);
564
+ }
565
+ }
566
+
567
+ ProcessMainFile (gltf, onFinish) {
568
+ let unsupportedExtensions = this.gltfExtensions.GetUnsupportedExtensions(gltf.extensionsRequired);
569
+ if (unsupportedExtensions.length > 0) {
570
+ this.SetError('Unsupported extension: ' + unsupportedExtensions.join(', ') + '.');
571
+ onFinish();
572
+ return;
573
+ }
574
+
575
+ this.gltfExtensions.LoadLibraries(gltf.extensionsRequired, {
576
+ onSuccess: () => {
577
+ this.ImportModel(gltf);
578
+ onFinish();
579
+ },
580
+ onError: (message) => {
581
+ this.SetError(message);
582
+ onFinish();
583
+ }
584
+ });
585
+ }
586
+
587
+ ImportModel (gltf) {
588
+ let materials = gltf.materials;
589
+ if (materials !== undefined) {
590
+ for (let material of materials) {
591
+ this.ImportMaterial(gltf, material);
592
+ }
593
+ }
594
+
595
+ let meshes = gltf.meshes;
596
+ if (meshes !== undefined) {
597
+ for (let mesh of meshes) {
598
+ this.ImportMesh(gltf, mesh);
599
+ }
600
+ }
601
+
602
+ this.ImportNodes(gltf);
603
+ this.ImportModelProperties(gltf);
604
+ }
605
+
606
+ ImportModelProperties (gltf) {
607
+ function ImportProperties (model, propertyGroupName, propertyObject) {
608
+ let propertyGroup = new PropertyGroup(propertyGroupName);
609
+ for (let propertyName in propertyObject) {
610
+ if (Object.prototype.hasOwnProperty.call(propertyObject, propertyName)) {
611
+ if (typeof propertyObject[propertyName] === 'string') {
612
+ const property = new Property(PropertyType.Text, propertyName, propertyObject[propertyName]);
613
+ propertyGroup.AddProperty(property);
614
+ }
615
+ }
616
+ }
617
+ if (propertyGroup.PropertyCount() > 0) {
618
+ model.AddPropertyGroup(propertyGroup);
619
+ }
620
+ return propertyGroup;
621
+ }
622
+
623
+ ImportProperties(this.model, 'Asset properties', gltf.asset);
624
+ if (gltf.asset['extras']) {
625
+ ImportProperties(this.model, 'Extras', gltf.asset['extras']);
626
+ }
627
+ }
628
+
629
+ GetDefaultScene (gltf) {
630
+ let defaultSceneIndex = gltf.scene || 0;
631
+ if (defaultSceneIndex >= gltf.scenes.length) {
632
+ return null;
633
+ }
634
+ return gltf.scenes[defaultSceneIndex];
635
+ }
636
+
637
+ ImportMaterial (gltf, gltfMaterial) {
638
+ let material = new PhysicalMaterial();
639
+ if (gltfMaterial.name !== undefined) {
640
+ material.name = gltfMaterial.name;
641
+ }
642
+
643
+ material.color = GetGltfColor([1.0, 1.0, 1.0]);
644
+ if (gltfMaterial.pbrMetallicRoughness !== undefined) {
645
+ let baseColor = gltfMaterial.pbrMetallicRoughness.baseColorFactor;
646
+ if (baseColor !== undefined) {
647
+ material.color = GetGltfColor(baseColor);
648
+ material.opacity = baseColor[3];
649
+ }
650
+ let metallicFactor = gltfMaterial.pbrMetallicRoughness.metallicFactor;
651
+ if (metallicFactor !== undefined) {
652
+ material.metalness = metallicFactor;
653
+ }
654
+ let roughnessFactor = gltfMaterial.pbrMetallicRoughness.roughnessFactor;
655
+ if (roughnessFactor !== undefined) {
656
+ material.roughness = roughnessFactor;
657
+ }
658
+ let emissiveColor = gltfMaterial.emissiveFactor;
659
+ if (emissiveColor !== undefined) {
660
+ material.emissive = GetGltfColor(emissiveColor);
661
+ }
662
+
663
+ material.diffuseMap = this.ImportTexture(gltf, gltfMaterial.pbrMetallicRoughness.baseColorTexture);
664
+ material.metalnessMap = this.ImportTexture(gltf, gltfMaterial.pbrMetallicRoughness.metallicRoughnessTexture);
665
+ material.normalMap = this.ImportTexture(gltf, gltfMaterial.normalTexture);
666
+ material.emissiveMap = this.ImportTexture(gltf, gltfMaterial.emissiveTexture);
667
+ if (material.diffuseMap !== null) {
668
+ material.multiplyDiffuseMap = true;
669
+ }
670
+
671
+ let alphaMode = gltfMaterial.alphaMode;
672
+ if (alphaMode !== undefined) {
673
+ if (alphaMode === 'BLEND') {
674
+ material.transparent = true;
675
+ } else if (alphaMode === 'MASK') {
676
+ material.transparent = true;
677
+ material.alphaTest = gltfMaterial.alphaCutoff || 0.5;
678
+ }
679
+ }
680
+ }
681
+
682
+ let newMaterial = this.gltfExtensions.ProcessMaterial(gltfMaterial, material, (textureRef) => {
683
+ return this.ImportTexture(gltf, textureRef);
684
+ });
685
+ if (newMaterial !== null) {
686
+ material = newMaterial;
687
+ }
688
+ this.model.AddMaterial(material);
689
+ }
690
+
691
+ ImportTexture (gltf, gltfTextureRef) {
692
+ if (gltfTextureRef === undefined || gltfTextureRef === null) {
693
+ return null;
694
+ }
695
+
696
+ let texture = new TextureMap();
697
+ let gltfTexture = gltf.textures[gltfTextureRef.index];
698
+ let gltfImageIndex = gltfTexture.source;
699
+ let gltfImage = gltf.images[gltfImageIndex];
700
+
701
+ let textureParams = null;
702
+ if (this.imageIndexToTextureParams.has(gltfImageIndex)) {
703
+ textureParams = this.imageIndexToTextureParams.get(gltfImageIndex);
704
+ } else {
705
+ textureParams = {
706
+ name: null,
707
+ mimeType: null,
708
+ buffer: null
709
+ };
710
+ let textureIndexString = gltfImageIndex.toString();
711
+ if (gltfImage.uri !== undefined) {
712
+ let base64Buffer = Base64DataURIToArrayBuffer(gltfImage.uri);
713
+ if (base64Buffer !== null) {
714
+ textureParams.name = 'Embedded_' + textureIndexString + '.' + GetFileExtensionFromMimeType(base64Buffer.mimeType);
715
+ textureParams.mimeType = base64Buffer.mimeType;
716
+ textureParams.buffer = base64Buffer.buffer;
717
+ } else {
718
+ let textureBuffer = this.callbacks.getFileBuffer(gltfImage.uri);
719
+ textureParams.name = gltfImage.uri;
720
+ textureParams.buffer = textureBuffer;
721
+ }
722
+ } else if (gltfImage.bufferView !== undefined) {
723
+ let bufferView = gltf.bufferViews[gltfImage.bufferView];
724
+ let reader = this.GetReaderFromBufferView(bufferView);
725
+ if (reader !== null) {
726
+ let buffer = reader.ReadArrayBuffer(bufferView.byteLength);
727
+ textureParams.name = 'Binary_' + textureIndexString + '.' + GetFileExtensionFromMimeType(gltfImage.mimeType);
728
+ textureParams.mimeType = gltfImage.mimeType;
729
+ textureParams.buffer = buffer;
730
+ }
731
+ }
732
+ this.imageIndexToTextureParams.set(gltfImageIndex, textureParams);
733
+ }
734
+
735
+ texture.name = textureParams.name;
736
+ texture.mimeType = textureParams.mimeType;
737
+ texture.buffer = textureParams.buffer;
738
+
739
+ this.gltfExtensions.ProcessTexture(gltfTextureRef, texture);
740
+ return texture;
741
+ }
742
+
743
+ ImportMesh (gltf, gltfMesh) {
744
+ let mesh = new Mesh();
745
+ this.model.AddMesh(mesh);
746
+ if (gltfMesh.name !== undefined) {
747
+ mesh.SetName(gltfMesh.name);
748
+ }
749
+
750
+ for (let i = 0; i < gltfMesh.primitives.length; i++) {
751
+ let primitive = gltfMesh.primitives[i];
752
+ this.ImportPrimitive(gltf, primitive, mesh);
753
+ }
754
+ }
755
+
756
+ ImportPrimitive (gltf, primitive, mesh) {
757
+ function HasAttribute (gltf, primitive, attributeName) {
758
+ let accessorIndex = primitive.attributes[attributeName];
759
+ if (accessorIndex === undefined) {
760
+ return false;
761
+ }
762
+ let accessor = gltf.accessors[accessorIndex];
763
+ if (accessor === undefined || accessor.count === 0) {
764
+ return false;
765
+ }
766
+ return true;
767
+ }
768
+
769
+ if (this.gltfExtensions.ProcessPrimitive(this, gltf, primitive, mesh)) {
770
+ return;
771
+ }
772
+
773
+ if (primitive.attributes === undefined) {
774
+ return;
775
+ }
776
+
777
+ let hasVertices = HasAttribute(gltf, primitive, 'POSITION');
778
+ let hasVertexColors = HasAttribute(gltf, primitive, 'COLOR_0');
779
+ let hasNormals = HasAttribute(gltf, primitive, 'NORMAL');
780
+ let hasUVs = HasAttribute(gltf, primitive, 'TEXCOORD_0');
781
+ let hasIndices = (primitive.indices !== undefined);
782
+
783
+ let mode = GltfRenderMode.TRIANGLES;
784
+ if (primitive.mode !== undefined) {
785
+ mode = primitive.mode;
786
+ }
787
+ if (mode !== GltfRenderMode.TRIANGLES && mode !== GltfRenderMode.TRIANGLE_STRIP && mode !== GltfRenderMode.TRIANGLE_FAN) {
788
+ return;
789
+ }
790
+
791
+ let vertexOffset = mesh.VertexCount();
792
+ let vertexColorOffset = mesh.VertexColorCount();
793
+ let normalOffset = mesh.NormalCount();
794
+ let uvOffset = mesh.TextureUVCount();
795
+
796
+ if (hasVertices) {
797
+ let accessor = gltf.accessors[primitive.attributes.POSITION];
798
+ let reader = this.GetReaderFromAccessor(gltf, accessor);
799
+ if (reader === null) {
800
+ return;
801
+ }
802
+ reader.EnumerateData((data) => {
803
+ mesh.AddVertex(data);
804
+ });
805
+ } else {
806
+ return;
807
+ }
808
+
809
+ if (hasVertexColors) {
810
+ let accessor = gltf.accessors[primitive.attributes.COLOR_0];
811
+ let reader = this.GetReaderFromAccessor(gltf, accessor);
812
+ if (reader === null) {
813
+ return;
814
+ }
815
+ reader.EnumerateData((data) => {
816
+ let color = GetGltfVertexColor([data.x, data.y, data.z], reader.componentType);
817
+ mesh.AddVertexColor(color);
818
+ });
819
+ }
820
+
821
+ if (hasNormals) {
822
+ let accessor = gltf.accessors[primitive.attributes.NORMAL];
823
+ let reader = this.GetReaderFromAccessor(gltf, accessor);
824
+ if (reader === null) {
825
+ return;
826
+ }
827
+ reader.EnumerateData((data) => {
828
+ mesh.AddNormal(data);
829
+ });
830
+ }
831
+
832
+ if (hasUVs) {
833
+ let accessor = gltf.accessors[primitive.attributes.TEXCOORD_0];
834
+ let reader = this.GetReaderFromAccessor(gltf, accessor);
835
+ if (reader === null) {
836
+ return;
837
+ }
838
+ reader.EnumerateData((data) => {
839
+ data.y = -data.y;
840
+ mesh.AddTextureUV(data);
841
+ });
842
+ }
843
+
844
+ let vertexIndices = [];
845
+ if (hasIndices) {
846
+ let accessor = gltf.accessors[primitive.indices];
847
+ let reader = this.GetReaderFromAccessor(gltf, accessor);
848
+ if (reader === null) {
849
+ return;
850
+ }
851
+ reader.EnumerateData((data) => {
852
+ vertexIndices.push(data);
853
+ });
854
+ } else {
855
+ let primitiveVertexCount = mesh.VertexCount() - vertexOffset;
856
+ for (let i = 0; i < primitiveVertexCount; i++) {
857
+ vertexIndices.push(i);
858
+ }
859
+ }
860
+
861
+ if (mode === GltfRenderMode.TRIANGLES) {
862
+ for (let i = 0; i < vertexIndices.length; i += 3) {
863
+ let v0 = vertexIndices[i];
864
+ let v1 = vertexIndices[i + 1];
865
+ let v2 = vertexIndices[i + 2];
866
+ this.AddTriangle(primitive, mesh, v0, v1, v2, hasVertexColors, hasNormals, hasUVs, vertexOffset, vertexColorOffset, normalOffset, uvOffset);
867
+ }
868
+ } else if (mode === GltfRenderMode.TRIANGLE_STRIP) {
869
+ for (let i = 0; i < vertexIndices.length - 2; i++) {
870
+ let v0 = vertexIndices[i];
871
+ let v1 = vertexIndices[i + 1];
872
+ let v2 = vertexIndices[i + 2];
873
+ if (i % 2 === 1) {
874
+ let tmp = v1;
875
+ v1 = v2;
876
+ v2 = tmp;
877
+ }
878
+ this.AddTriangle(primitive, mesh, v0, v1, v2, hasVertexColors, hasNormals, hasUVs, vertexOffset, vertexColorOffset, normalOffset, uvOffset);
879
+ }
880
+ } else if (mode === GltfRenderMode.TRIANGLE_FAN) {
881
+ for (let i = 1; i < vertexIndices.length - 1; i++) {
882
+ let v0 = vertexIndices[0];
883
+ let v1 = vertexIndices[i];
884
+ let v2 = vertexIndices[i + 1];
885
+ this.AddTriangle(primitive, mesh, v0, v1, v2, hasVertexColors, hasNormals, hasUVs, vertexOffset, vertexColorOffset, normalOffset, uvOffset);
886
+ }
887
+ }
888
+ }
889
+
890
+ AddTriangle (primitive, mesh, v0, v1, v2, hasVertexColors, hasNormals, hasUVs, vertexOffset, vertexColorOffset, normalOffset, uvOffset) {
891
+ let triangle = new Triangle(
892
+ vertexOffset + v0,
893
+ vertexOffset + v1,
894
+ vertexOffset + v2
895
+ );
896
+ if (hasVertexColors) {
897
+ triangle.SetVertexColors(
898
+ vertexColorOffset + v0,
899
+ vertexColorOffset + v1,
900
+ vertexColorOffset + v2
901
+ );
902
+ }
903
+ if (hasNormals) {
904
+ triangle.SetNormals(
905
+ normalOffset + v0,
906
+ normalOffset + v1,
907
+ normalOffset + v2
908
+ );
909
+ }
910
+ if (hasUVs) {
911
+ triangle.SetTextureUVs(
912
+ uvOffset + v0,
913
+ uvOffset + v1,
914
+ uvOffset + v2
915
+ );
916
+ }
917
+ if (primitive.material !== undefined) {
918
+ triangle.mat = primitive.material;
919
+ }
920
+ mesh.AddTriangle(triangle);
921
+ }
922
+
923
+ ImportNodes (gltf) {
924
+ let scene = this.GetDefaultScene(gltf);
925
+ if (scene === null) {
926
+ return;
927
+ }
928
+ let rootNode = this.model.GetRootNode();
929
+ for (let nodeIndex of scene.nodes) {
930
+ let gltfNode = gltf.nodes[nodeIndex];
931
+ this.ImportNode(gltf, gltfNode, rootNode);
932
+ }
933
+ }
934
+
935
+ ImportNode (gltf, gltfNode, parentNode) {
936
+ function GetNodeTransformation (gltfNode) {
937
+ let matrix = new Matrix().CreateIdentity();
938
+ if (gltfNode.matrix !== undefined) {
939
+ matrix.Set(gltfNode.matrix);
940
+ } else {
941
+ let translation = [0.0, 0.0, 0.0];
942
+ let rotation = [0.0, 0.0, 0.0, 1.0];
943
+ let scale = [1.0, 1.0, 1.0];
944
+ if (gltfNode.translation !== undefined) {
945
+ translation = gltfNode.translation;
946
+ }
947
+ if (gltfNode.rotation !== undefined) {
948
+ rotation = gltfNode.rotation;
949
+ }
950
+ if (gltfNode.scale !== undefined) {
951
+ scale = gltfNode.scale;
952
+ }
953
+ matrix.ComposeTRS(
954
+ ArrayToCoord3D(translation),
955
+ ArrayToQuaternion(rotation),
956
+ ArrayToCoord3D(scale)
957
+ );
958
+ }
959
+ return new Transformation(matrix);
960
+ }
961
+
962
+ if (gltfNode.children === undefined && gltfNode.mesh === undefined) {
963
+ return;
964
+ }
965
+
966
+ let node = new Node();
967
+ if (gltfNode.name !== undefined) {
968
+ node.SetName(gltfNode.name);
969
+ }
970
+ node.SetTransformation(GetNodeTransformation(gltfNode));
971
+ parentNode.AddChildNode(node);
972
+
973
+ if (gltfNode.children !== undefined) {
974
+ for (let childIndex of gltfNode.children) {
975
+ let childGltfNode = gltf.nodes[childIndex];
976
+ this.ImportNode(gltf, childGltfNode, node);
977
+ }
978
+ }
979
+
980
+ if (gltfNode.mesh !== undefined) {
981
+ if (gltfNode.children === undefined || gltfNode.children.length === 0) {
982
+ node.SetType(NodeType.MeshNode);
983
+ }
984
+ node.AddMeshIndex(gltfNode.mesh);
985
+ }
986
+ }
987
+
988
+ GetReaderFromBufferView (bufferView) {
989
+ let bufferIndex = bufferView.buffer || 0;
990
+ let buffer = this.bufferContents[bufferIndex];
991
+ if (buffer === undefined || buffer === null) {
992
+ return null;
993
+ }
994
+
995
+ let reader = new GltfBufferReader(buffer);
996
+ reader.SkipBytes(bufferView.byteOffset || 0);
997
+ let byteStride = bufferView.byteStride;
998
+ if (byteStride !== undefined && byteStride !== 0) {
999
+ reader.SetByteStride(byteStride);
1000
+ }
1001
+
1002
+ return reader;
1003
+ }
1004
+
1005
+ GetReaderFromAccessor (gltf, accessor) {
1006
+ let bufferViewIndex = accessor.bufferView || 0;
1007
+ let bufferView = gltf.bufferViews[bufferViewIndex];
1008
+ let reader = this.GetReaderFromBufferView(bufferView);
1009
+ if (reader === null) {
1010
+ return null;
1011
+ }
1012
+
1013
+ reader.SetComponentType(accessor.componentType);
1014
+ reader.SetDataType(accessor.type);
1015
+ reader.SetDataCount(accessor.count);
1016
+ reader.SkipBytes(accessor.byteOffset || 0);
1017
+
1018
+ if (accessor.sparse !== undefined) {
1019
+ let indexReader = this.GetReaderFromSparseAccessor(gltf, accessor.sparse.indices, accessor.sparse.indices.componentType, 'SCALAR', accessor.sparse.count);
1020
+ let valueReader = this.GetReaderFromSparseAccessor(gltf, accessor.sparse.values, accessor.componentType, accessor.type, accessor.sparse.count);
1021
+ if (indexReader !== null && valueReader !== null) {
1022
+ reader.SetSparseReader(indexReader, valueReader);
1023
+ }
1024
+ }
1025
+ return reader;
1026
+ }
1027
+
1028
+ GetReaderFromSparseAccessor (gltf, sparseAccessor, componentType, type, count) {
1029
+ if (sparseAccessor.bufferView === undefined) {
1030
+ return null;
1031
+ }
1032
+
1033
+ let bufferView = gltf.bufferViews[sparseAccessor.bufferView];
1034
+ let reader = this.GetReaderFromBufferView(bufferView);
1035
+ if (reader === null) {
1036
+ return null;
1037
+ }
1038
+
1039
+ reader.SetComponentType(componentType);
1040
+ reader.SetDataType(type);
1041
+ reader.SetDataCount(count);
1042
+ reader.SkipBytes(sparseAccessor.byteOffset || 0);
1043
+ return reader;
1044
+ }
1045
+ }