sdl-mcp 0.12.2 → 0.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. package/README.md +10 -0
  2. package/config/sdlmcp.config.example.json +53 -8
  3. package/config/sdlmcp.config.schema.json +530 -106
  4. package/dist/.tsbuildinfo +1 -1
  5. package/dist/benchmark/external-manifest.d.ts +162 -0
  6. package/dist/benchmark/external-manifest.d.ts.map +1 -0
  7. package/dist/benchmark/external-manifest.js +336 -0
  8. package/dist/benchmark/external-manifest.js.map +1 -0
  9. package/dist/benchmark/external-runner.d.ts +100 -0
  10. package/dist/benchmark/external-runner.d.ts.map +1 -0
  11. package/dist/benchmark/external-runner.js +1171 -0
  12. package/dist/benchmark/external-runner.js.map +1 -0
  13. package/dist/benchmark/output-file.d.ts +3 -0
  14. package/dist/benchmark/output-file.d.ts.map +1 -0
  15. package/dist/benchmark/output-file.js +8 -0
  16. package/dist/benchmark/output-file.js.map +1 -0
  17. package/dist/cli/argParsing.d.ts.map +1 -1
  18. package/dist/cli/argParsing.js +6 -0
  19. package/dist/cli/argParsing.js.map +1 -1
  20. package/dist/cli/commands/benchmark.d.ts.map +1 -1
  21. package/dist/cli/commands/benchmark.js +3 -2
  22. package/dist/cli/commands/benchmark.js.map +1 -1
  23. package/dist/cli/commands/index.d.ts +1 -0
  24. package/dist/cli/commands/index.d.ts.map +1 -1
  25. package/dist/cli/commands/index.js +13 -7
  26. package/dist/cli/commands/index.js.map +1 -1
  27. package/dist/cli/commands/init.d.ts +5 -1
  28. package/dist/cli/commands/init.d.ts.map +1 -1
  29. package/dist/cli/commands/init.js +73 -3
  30. package/dist/cli/commands/init.js.map +1 -1
  31. package/dist/cli/commands/serve.d.ts.map +1 -1
  32. package/dist/cli/commands/serve.js +2 -0
  33. package/dist/cli/commands/serve.js.map +1 -1
  34. package/dist/cli/index.js +2 -0
  35. package/dist/cli/index.js.map +1 -1
  36. package/dist/cli/transport/http.d.ts +1 -35
  37. package/dist/cli/transport/http.d.ts.map +1 -1
  38. package/dist/cli/transport/http.js +151 -175
  39. package/dist/cli/transport/http.js.map +1 -1
  40. package/dist/cli/types.d.ts +1 -0
  41. package/dist/cli/types.d.ts.map +1 -1
  42. package/dist/config/constants.d.ts +30 -0
  43. package/dist/config/constants.d.ts.map +1 -1
  44. package/dist/config/constants.js +30 -0
  45. package/dist/config/constants.js.map +1 -1
  46. package/dist/config/types.d.ts +53 -1
  47. package/dist/config/types.d.ts.map +1 -1
  48. package/dist/config/types.js +62 -14
  49. package/dist/config/types.js.map +1 -1
  50. package/dist/db/ladybug-batching.d.ts +1 -0
  51. package/dist/db/ladybug-batching.d.ts.map +1 -1
  52. package/dist/db/ladybug-batching.js +1 -0
  53. package/dist/db/ladybug-batching.js.map +1 -1
  54. package/dist/db/ladybug-core.d.ts +3 -0
  55. package/dist/db/ladybug-core.d.ts.map +1 -1
  56. package/dist/db/ladybug-core.js +72 -2
  57. package/dist/db/ladybug-core.js.map +1 -1
  58. package/dist/db/ladybug-embeddings.d.ts +6 -1
  59. package/dist/db/ladybug-embeddings.d.ts.map +1 -1
  60. package/dist/db/ladybug-embeddings.js +6 -1
  61. package/dist/db/ladybug-embeddings.js.map +1 -1
  62. package/dist/db/ladybug-file-summaries.d.ts.map +1 -1
  63. package/dist/db/ladybug-file-summaries.js +23 -0
  64. package/dist/db/ladybug-file-summaries.js.map +1 -1
  65. package/dist/db/ladybug-queries.js +1 -1
  66. package/dist/db/ladybug-queries.js.map +1 -1
  67. package/dist/db/migrations/index.d.ts.map +1 -1
  68. package/dist/db/migrations/index.js +2 -0
  69. package/dist/db/migrations/index.js.map +1 -1
  70. package/dist/db/migrations/m007-copy-embeddings-to-symbol.d.ts +5 -9
  71. package/dist/db/migrations/m007-copy-embeddings-to-symbol.d.ts.map +1 -1
  72. package/dist/db/migrations/m007-copy-embeddings-to-symbol.js +24 -126
  73. package/dist/db/migrations/m007-copy-embeddings-to-symbol.js.map +1 -1
  74. package/dist/db/migrations/m021-remediate-symbol-embeddings.d.ts +5 -0
  75. package/dist/db/migrations/m021-remediate-symbol-embeddings.d.ts.map +1 -0
  76. package/dist/db/migrations/m021-remediate-symbol-embeddings.js +7 -0
  77. package/dist/db/migrations/m021-remediate-symbol-embeddings.js.map +1 -0
  78. package/dist/db/migrations/symbol-embedding-remediation.d.ts +57 -0
  79. package/dist/db/migrations/symbol-embedding-remediation.d.ts.map +1 -0
  80. package/dist/db/migrations/symbol-embedding-remediation.js +335 -0
  81. package/dist/db/migrations/symbol-embedding-remediation.js.map +1 -0
  82. package/dist/graph/layout/force-layout.d.ts +4 -0
  83. package/dist/graph/layout/force-layout.d.ts.map +1 -0
  84. package/dist/graph/layout/force-layout.js +127 -0
  85. package/dist/graph/layout/force-layout.js.map +1 -0
  86. package/dist/graph/layout/layout-service.d.ts +37 -0
  87. package/dist/graph/layout/layout-service.d.ts.map +1 -0
  88. package/dist/graph/layout/layout-service.js +172 -0
  89. package/dist/graph/layout/layout-service.js.map +1 -0
  90. package/dist/graph/layout/native-engine.d.ts +9 -0
  91. package/dist/graph/layout/native-engine.d.ts.map +1 -0
  92. package/dist/graph/layout/native-engine.js +59 -0
  93. package/dist/graph/layout/native-engine.js.map +1 -0
  94. package/dist/graph/layout/prng.d.ts +3 -0
  95. package/dist/graph/layout/prng.d.ts.map +1 -0
  96. package/dist/graph/layout/prng.js +19 -0
  97. package/dist/graph/layout/prng.js.map +1 -0
  98. package/dist/graph/layout/serializer.d.ts +3 -0
  99. package/dist/graph/layout/serializer.d.ts.map +1 -0
  100. package/dist/graph/layout/serializer.js +20 -0
  101. package/dist/graph/layout/serializer.js.map +1 -0
  102. package/dist/graph/layout/types.d.ts +30 -0
  103. package/dist/graph/layout/types.d.ts.map +1 -0
  104. package/dist/graph/layout/types.js +2 -0
  105. package/dist/graph/layout/types.js.map +1 -0
  106. package/dist/indexer/embeddings.d.ts +7 -0
  107. package/dist/indexer/embeddings.d.ts.map +1 -1
  108. package/dist/indexer/embeddings.js +44 -4
  109. package/dist/indexer/embeddings.js.map +1 -1
  110. package/dist/indexer/file-summary-embeddings.d.ts +12 -0
  111. package/dist/indexer/file-summary-embeddings.d.ts.map +1 -1
  112. package/dist/indexer/file-summary-embeddings.js +83 -21
  113. package/dist/indexer/file-summary-embeddings.js.map +1 -1
  114. package/dist/indexer/fileWalker.d.ts.map +1 -1
  115. package/dist/indexer/fileWalker.js +2 -1
  116. package/dist/indexer/fileWalker.js.map +1 -1
  117. package/dist/indexer/metrics-updater.d.ts.map +1 -1
  118. package/dist/indexer/metrics-updater.js +27 -4
  119. package/dist/indexer/metrics-updater.js.map +1 -1
  120. package/dist/indexer/watcher.d.ts.map +1 -1
  121. package/dist/indexer/watcher.js +2 -1
  122. package/dist/indexer/watcher.js.map +1 -1
  123. package/dist/mcp/context-response-projection.d.ts.map +1 -1
  124. package/dist/mcp/context-response-projection.js +49 -13
  125. package/dist/mcp/context-response-projection.js.map +1 -1
  126. package/dist/mcp/tools/search-edit/planner.d.ts.map +1 -1
  127. package/dist/mcp/tools/search-edit/planner.js +10 -3
  128. package/dist/mcp/tools/search-edit/planner.js.map +1 -1
  129. package/dist/observability/event-tap.d.ts +2 -1
  130. package/dist/observability/event-tap.d.ts.map +1 -1
  131. package/dist/observability/event-tap.js.map +1 -1
  132. package/dist/observability/service.d.ts +11 -4
  133. package/dist/observability/service.d.ts.map +1 -1
  134. package/dist/observability/service.js +83 -13
  135. package/dist/observability/service.js.map +1 -1
  136. package/dist/observability/types.d.ts +48 -2
  137. package/dist/observability/types.d.ts.map +1 -1
  138. package/dist/ui/.tsbuildinfo +1 -0
  139. package/dist/ui/vendor/fflate.js +2692 -0
  140. package/dist/ui/vendor/jsm/controls/ArcballControls.js +3543 -0
  141. package/dist/ui/vendor/jsm/controls/DragControls.js +452 -0
  142. package/dist/ui/vendor/jsm/controls/FirstPersonControls.js +488 -0
  143. package/dist/ui/vendor/jsm/controls/FlyControls.js +384 -0
  144. package/dist/ui/vendor/jsm/controls/MapControls.js +116 -0
  145. package/dist/ui/vendor/jsm/controls/OrbitControls.js +1963 -0
  146. package/dist/ui/vendor/jsm/controls/PointerLockControls.js +264 -0
  147. package/dist/ui/vendor/jsm/controls/TrackballControls.js +1001 -0
  148. package/dist/ui/vendor/jsm/controls/TransformControls.js +2003 -0
  149. package/dist/ui/vendor/jsm/loaders/3DMLoader.js +1836 -0
  150. package/dist/ui/vendor/jsm/loaders/3MFLoader.js +1621 -0
  151. package/dist/ui/vendor/jsm/loaders/AMFLoader.js +541 -0
  152. package/dist/ui/vendor/jsm/loaders/BVHLoader.js +484 -0
  153. package/dist/ui/vendor/jsm/loaders/ColladaLoader.js +153 -0
  154. package/dist/ui/vendor/jsm/loaders/DDSLoader.js +385 -0
  155. package/dist/ui/vendor/jsm/loaders/DRACOLoader.js +772 -0
  156. package/dist/ui/vendor/jsm/loaders/EXRLoader.js +3395 -0
  157. package/dist/ui/vendor/jsm/loaders/FBXLoader.js +4580 -0
  158. package/dist/ui/vendor/jsm/loaders/FontLoader.js +260 -0
  159. package/dist/ui/vendor/jsm/loaders/GCodeLoader.js +318 -0
  160. package/dist/ui/vendor/jsm/loaders/GLTFLoader.js +4860 -0
  161. package/dist/ui/vendor/jsm/loaders/HDRCubeTextureLoader.js +164 -0
  162. package/dist/ui/vendor/jsm/loaders/HDRLoader.js +463 -0
  163. package/dist/ui/vendor/jsm/loaders/IESLoader.js +379 -0
  164. package/dist/ui/vendor/jsm/loaders/KMZLoader.js +163 -0
  165. package/dist/ui/vendor/jsm/loaders/KTX2Loader.js +1276 -0
  166. package/dist/ui/vendor/jsm/loaders/KTXLoader.js +197 -0
  167. package/dist/ui/vendor/jsm/loaders/LDrawLoader.js +2510 -0
  168. package/dist/ui/vendor/jsm/loaders/LUT3dlLoader.js +205 -0
  169. package/dist/ui/vendor/jsm/loaders/LUTCubeLoader.js +190 -0
  170. package/dist/ui/vendor/jsm/loaders/LUTImageLoader.js +190 -0
  171. package/dist/ui/vendor/jsm/loaders/LWOLoader.js +1051 -0
  172. package/dist/ui/vendor/jsm/loaders/LottieLoader.js +130 -0
  173. package/dist/ui/vendor/jsm/loaders/MD2Loader.js +435 -0
  174. package/dist/ui/vendor/jsm/loaders/MDDLoader.js +147 -0
  175. package/dist/ui/vendor/jsm/loaders/MTLLoader.js +593 -0
  176. package/dist/ui/vendor/jsm/loaders/MaterialXLoader.js +1126 -0
  177. package/dist/ui/vendor/jsm/loaders/NRRDLoader.js +718 -0
  178. package/dist/ui/vendor/jsm/loaders/OBJLoader.js +955 -0
  179. package/dist/ui/vendor/jsm/loaders/PCDLoader.js +620 -0
  180. package/dist/ui/vendor/jsm/loaders/PDBLoader.js +272 -0
  181. package/dist/ui/vendor/jsm/loaders/PLYLoader.js +968 -0
  182. package/dist/ui/vendor/jsm/loaders/PVRLoader.js +270 -0
  183. package/dist/ui/vendor/jsm/loaders/RGBELoader.js +18 -0
  184. package/dist/ui/vendor/jsm/loaders/STLLoader.js +421 -0
  185. package/dist/ui/vendor/jsm/loaders/SVGLoader.js +3319 -0
  186. package/dist/ui/vendor/jsm/loaders/TDSLoader.js +1142 -0
  187. package/dist/ui/vendor/jsm/loaders/TGALoader.js +538 -0
  188. package/dist/ui/vendor/jsm/loaders/TIFFLoader.js +59 -0
  189. package/dist/ui/vendor/jsm/loaders/TTFLoader.js +261 -0
  190. package/dist/ui/vendor/jsm/loaders/USDLoader.js +303 -0
  191. package/dist/ui/vendor/jsm/loaders/USDZLoader.js +16 -0
  192. package/dist/ui/vendor/jsm/loaders/UltraHDRLoader.js +755 -0
  193. package/dist/ui/vendor/jsm/loaders/VOXLoader.js +919 -0
  194. package/dist/ui/vendor/jsm/loaders/VRMLLoader.js +3646 -0
  195. package/dist/ui/vendor/jsm/loaders/VTKLoader.js +1293 -0
  196. package/dist/ui/vendor/jsm/loaders/XYZLoader.js +143 -0
  197. package/dist/ui/vendor/jsm/loaders/collada/ColladaComposer.js +3044 -0
  198. package/dist/ui/vendor/jsm/loaders/collada/ColladaParser.js +1977 -0
  199. package/dist/ui/vendor/jsm/loaders/lwo/IFFParser.js +1217 -0
  200. package/dist/ui/vendor/jsm/loaders/lwo/LWO2Parser.js +414 -0
  201. package/dist/ui/vendor/jsm/loaders/lwo/LWO3Parser.js +373 -0
  202. package/dist/ui/vendor/jsm/loaders/usd/USDAParser.js +901 -0
  203. package/dist/ui/vendor/jsm/loaders/usd/USDCParser.js +1878 -0
  204. package/dist/ui/vendor/jsm/loaders/usd/USDComposer.js +4627 -0
  205. package/dist/ui/vendor/jsm/utils/BufferGeometryUtils.js +1501 -0
  206. package/dist/ui/vendor/jsm/utils/CameraUtils.js +82 -0
  207. package/dist/ui/vendor/jsm/utils/ColorUtils.js +76 -0
  208. package/dist/ui/vendor/jsm/utils/GeometryCompressionUtils.js +547 -0
  209. package/dist/ui/vendor/jsm/utils/GeometryUtils.js +226 -0
  210. package/dist/ui/vendor/jsm/utils/LDrawUtils.js +211 -0
  211. package/dist/ui/vendor/jsm/utils/SceneOptimizer.js +458 -0
  212. package/dist/ui/vendor/jsm/utils/SceneUtils.js +363 -0
  213. package/dist/ui/vendor/jsm/utils/ShadowMapViewer.js +244 -0
  214. package/dist/ui/vendor/jsm/utils/ShadowMapViewerGPU.js +233 -0
  215. package/dist/ui/vendor/jsm/utils/SkeletonUtils.js +496 -0
  216. package/dist/ui/vendor/jsm/utils/SortUtils.js +175 -0
  217. package/dist/ui/vendor/jsm/utils/UVsDebug.js +173 -0
  218. package/dist/ui/vendor/jsm/utils/WebGLTextureUtils.js +115 -0
  219. package/dist/ui/vendor/jsm/utils/WebGPUTextureUtils.js +81 -0
  220. package/dist/ui/vendor/jsm/utils/WorkerPool.js +167 -0
  221. package/dist/ui/vendor/three.core.min.js +6 -0
  222. package/dist/ui/vendor/three.module.min.js +6 -0
  223. package/dist/ui/viewer/ambient.js +39 -0
  224. package/dist/ui/viewer/api.js +93 -0
  225. package/dist/ui/viewer/chrome.js +36 -0
  226. package/dist/ui/viewer/edges.js +33 -0
  227. package/dist/ui/viewer/index.html +32 -0
  228. package/dist/ui/viewer/inspector.js +23 -0
  229. package/dist/ui/viewer/lenses/activity.js +24 -0
  230. package/dist/ui/viewer/lenses/community.js +5 -0
  231. package/dist/ui/viewer/lenses/edges.js +4 -0
  232. package/dist/ui/viewer/lenses/impact.js +6 -0
  233. package/dist/ui/viewer/lenses/search.js +69 -0
  234. package/dist/ui/viewer/lod.js +100 -0
  235. package/dist/ui/viewer/main.js +92 -0
  236. package/dist/ui/viewer/picking.js +45 -0
  237. package/dist/ui/viewer/scene.js +85 -0
  238. package/dist/ui/viewer/skins/default-skin.js +15 -0
  239. package/dist/ui/viewer/skins/loader.js +44 -0
  240. package/dist/ui/viewer/skins/manifest-schema.js +30 -0
  241. package/dist/ui/viewer/state.js +44 -0
  242. package/dist/ui/viewer/theme.js +23 -0
  243. package/dist/ui/viewer/universe.js +151 -0
  244. package/dist/ui/viewer/viewer.css +85 -0
  245. package/dist/util/safeRegex.d.ts.map +1 -1
  246. package/dist/util/safeRegex.js +221 -68
  247. package/dist/util/safeRegex.js.map +1 -1
  248. package/dist/viewer/legacy-graph.d.ts +40 -0
  249. package/dist/viewer/legacy-graph.d.ts.map +1 -0
  250. package/dist/viewer/legacy-graph.js +152 -0
  251. package/dist/viewer/legacy-graph.js.map +1 -0
  252. package/dist/viewer/routes.d.ts +10 -0
  253. package/dist/viewer/routes.d.ts.map +1 -0
  254. package/dist/viewer/routes.js +221 -0
  255. package/dist/viewer/routes.js.map +1 -0
  256. package/dist/viewer/service.d.ts +44 -0
  257. package/dist/viewer/service.d.ts.map +1 -0
  258. package/dist/viewer/service.js +160 -0
  259. package/dist/viewer/service.js.map +1 -0
  260. package/dist/viewer/types.d.ts +63 -0
  261. package/dist/viewer/types.d.ts.map +1 -0
  262. package/dist/viewer/types.js +2 -0
  263. package/dist/viewer/types.js.map +1 -0
  264. package/dist/viewer/viewer-config.d.ts +12 -0
  265. package/dist/viewer/viewer-config.d.ts.map +1 -0
  266. package/dist/viewer/viewer-config.js +36 -0
  267. package/dist/viewer/viewer-config.js.map +1 -0
  268. package/package.json +18 -9
  269. package/templates/SDL.md +19 -0
  270. package/templates/claude-code.json +8 -43
  271. package/dist/ui/graph.css +0 -108
  272. package/dist/ui/graph.d.ts +0 -2
  273. package/dist/ui/graph.d.ts.map +0 -1
  274. package/dist/ui/graph.html +0 -52
  275. package/dist/ui/graph.js +0 -259
  276. package/dist/ui/graph.js.map +0 -1
@@ -0,0 +1,1621 @@
1
+ import {
2
+ BufferAttribute,
3
+ BufferGeometry,
4
+ ClampToEdgeWrapping,
5
+ Color,
6
+ FileLoader,
7
+ Float32BufferAttribute,
8
+ Group,
9
+ LinearFilter,
10
+ LinearMipmapLinearFilter,
11
+ Loader,
12
+ Matrix4,
13
+ Mesh,
14
+ MeshPhongMaterial,
15
+ MeshStandardMaterial,
16
+ MirroredRepeatWrapping,
17
+ NearestFilter,
18
+ RepeatWrapping,
19
+ TextureLoader,
20
+ SRGBColorSpace
21
+ } from 'three';
22
+ import { unzipSync } from '../libs/fflate.module.js';
23
+
24
+ const COLOR_SPACE_3MF = SRGBColorSpace;
25
+
26
+ /**
27
+ * A loader for the [3D Manufacturing Format (3MF)](https://3mf.io/specification/) format.
28
+ *
29
+ * The following features from the core specification are supported:
30
+ *
31
+ * - 3D Models
32
+ * - Object Resources (Meshes and Components)
33
+ * - Material Resources (Base Materials)
34
+ *
35
+ * 3MF Materials and Properties Extension are only partially supported.
36
+ *
37
+ * - Texture 2D
38
+ * - Texture 2D Groups
39
+ * - Color Groups (Vertex Colors)
40
+ * - Metallic Display Properties (PBR)
41
+ *
42
+ * ```js
43
+ * const loader = new ThreeMFLoader();
44
+ *
45
+ * const object = await loader.loadAsync( './models/3mf/truck.3mf' );
46
+ * object.rotation.set( - Math.PI / 2, 0, 0 ); // z-up conversion
47
+ * scene.add( object );
48
+ * ```
49
+ *
50
+ * @augments Loader
51
+ * @three_import import { ThreeMFLoader } from 'three/addons/loaders/3MFLoader.js';
52
+ */
53
+ class ThreeMFLoader extends Loader {
54
+
55
+ /**
56
+ * Constructs a new 3MF loader.
57
+ *
58
+ * @param {LoadingManager} [manager] - The loading manager.
59
+ */
60
+ constructor( manager ) {
61
+
62
+ super( manager );
63
+
64
+ /**
65
+ * An array of available extensions.
66
+ *
67
+ * @type {Array<Object>}
68
+ */
69
+ this.availableExtensions = [];
70
+
71
+ }
72
+
73
+ /**
74
+ * Starts loading from the given URL and passes the loaded 3MF asset
75
+ * to the `onLoad()` callback.
76
+ *
77
+ * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
78
+ * @param {function(Group)} onLoad - Executed when the loading process has been finished.
79
+ * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
80
+ * @param {onErrorCallback} onError - Executed when errors occur.
81
+ */
82
+ load( url, onLoad, onProgress, onError ) {
83
+
84
+ const scope = this;
85
+ const loader = new FileLoader( scope.manager );
86
+ loader.setPath( scope.path );
87
+ loader.setResponseType( 'arraybuffer' );
88
+ loader.setRequestHeader( scope.requestHeader );
89
+ loader.setWithCredentials( scope.withCredentials );
90
+ loader.load( url, function ( buffer ) {
91
+
92
+ try {
93
+
94
+ onLoad( scope.parse( buffer ) );
95
+
96
+ } catch ( e ) {
97
+
98
+ if ( onError ) {
99
+
100
+ onError( e );
101
+
102
+ } else {
103
+
104
+ console.error( e );
105
+
106
+ }
107
+
108
+ scope.manager.itemError( url );
109
+
110
+ }
111
+
112
+ }, onProgress, onError );
113
+
114
+ }
115
+
116
+ /**
117
+ * Parses the given 3MF data and returns the resulting group.
118
+ *
119
+ * @param {ArrayBuffer} data - The raw 3MF asset data as an array buffer.
120
+ * @return {Group} A group representing the parsed asset.
121
+ */
122
+ parse( data ) {
123
+
124
+ const scope = this;
125
+ const textureLoader = new TextureLoader( this.manager );
126
+
127
+ function loadDocument( data ) {
128
+
129
+ let zip = null;
130
+ let file = null;
131
+
132
+ let relsName;
133
+ let modelRelsName;
134
+ const modelPartNames = [];
135
+ const texturesPartNames = [];
136
+
137
+ let modelRels;
138
+ const modelParts = {};
139
+ const printTicketParts = {};
140
+ const texturesParts = {};
141
+
142
+ const textDecoder = new TextDecoder();
143
+
144
+ try {
145
+
146
+ zip = unzipSync( new Uint8Array( data ) );
147
+
148
+ } catch ( e ) {
149
+
150
+ if ( e instanceof ReferenceError ) {
151
+
152
+ console.error( 'THREE.3MFLoader: fflate missing and file is compressed.' );
153
+ return null;
154
+
155
+ }
156
+
157
+ }
158
+
159
+ let rootModelFile = null;
160
+
161
+ for ( file in zip ) {
162
+
163
+ if ( file.match( /\_rels\/.rels$/ ) ) {
164
+
165
+ relsName = file;
166
+
167
+ } else if ( file.match( /3D\/_rels\/.*\.model\.rels$/ ) ) {
168
+
169
+ modelRelsName = file;
170
+
171
+ } else if ( file.match( /^3D\/[^\/]*\.model$/ ) ) {
172
+
173
+ rootModelFile = file;
174
+
175
+ } else if ( file.match( /^3D\/.*\/.*\.model$/ ) ) {
176
+
177
+ modelPartNames.push( file ); // sub models
178
+
179
+ } else if ( file.match( /^3D\/Textures?\/.*/ ) ) {
180
+
181
+ texturesPartNames.push( file );
182
+
183
+ }
184
+
185
+ }
186
+
187
+ modelPartNames.push( rootModelFile ); // push root model at the end so it is processed after the sub models
188
+
189
+ if ( relsName === undefined ) throw new Error( 'THREE.ThreeMFLoader: Cannot find relationship file `rels` in 3MF archive.' );
190
+
191
+ //
192
+
193
+ const relsView = zip[ relsName ];
194
+ const relsFileText = textDecoder.decode( relsView );
195
+ const rels = parseRelsXml( relsFileText );
196
+
197
+ //
198
+
199
+ if ( modelRelsName ) {
200
+
201
+ const relsView = zip[ modelRelsName ];
202
+ const relsFileText = textDecoder.decode( relsView );
203
+ modelRels = parseRelsXml( relsFileText );
204
+
205
+ }
206
+
207
+ //
208
+
209
+ for ( let i = 0; i < modelPartNames.length; i ++ ) {
210
+
211
+ const modelPart = modelPartNames[ i ];
212
+ const view = zip[ modelPart ];
213
+
214
+ const fileText = textDecoder.decode( view );
215
+ const xmlData = new DOMParser().parseFromString( fileText, 'application/xml' );
216
+
217
+ if ( xmlData.documentElement.nodeName.toLowerCase() !== 'model' ) {
218
+
219
+ console.error( 'THREE.3MFLoader: Error loading 3MF - no 3MF document found: ', modelPart );
220
+
221
+ }
222
+
223
+ const modelNode = xmlData.querySelector( 'model' );
224
+ const extensions = {};
225
+
226
+ for ( let i = 0; i < modelNode.attributes.length; i ++ ) {
227
+
228
+ const attr = modelNode.attributes[ i ];
229
+ if ( attr.name.match( /^xmlns:(.+)$/ ) ) {
230
+
231
+ extensions[ attr.value ] = RegExp.$1;
232
+
233
+ }
234
+
235
+ }
236
+
237
+ const modelData = parseModelNode( modelNode );
238
+ modelData[ 'xml' ] = modelNode;
239
+
240
+ if ( 0 < Object.keys( extensions ).length ) {
241
+
242
+ modelData[ 'extensions' ] = extensions;
243
+
244
+ }
245
+
246
+ modelParts[ modelPart ] = modelData;
247
+
248
+ }
249
+
250
+ //
251
+
252
+ for ( let i = 0; i < texturesPartNames.length; i ++ ) {
253
+
254
+ const texturesPartName = texturesPartNames[ i ];
255
+ texturesParts[ texturesPartName ] = zip[ texturesPartName ].buffer;
256
+
257
+ }
258
+
259
+ return {
260
+ rels: rels,
261
+ modelRels: modelRels,
262
+ model: modelParts,
263
+ printTicket: printTicketParts,
264
+ texture: texturesParts
265
+ };
266
+
267
+ }
268
+
269
+ function parseRelsXml( relsFileText ) {
270
+
271
+ const relationships = [];
272
+
273
+ const relsXmlData = new DOMParser().parseFromString( relsFileText, 'application/xml' );
274
+
275
+ const relsNodes = relsXmlData.querySelectorAll( 'Relationship' );
276
+
277
+ for ( let i = 0; i < relsNodes.length; i ++ ) {
278
+
279
+ const relsNode = relsNodes[ i ];
280
+
281
+ const relationship = {
282
+ target: relsNode.getAttribute( 'Target' ), //required
283
+ id: relsNode.getAttribute( 'Id' ), //required
284
+ type: relsNode.getAttribute( 'Type' ) //required
285
+ };
286
+
287
+ relationships.push( relationship );
288
+
289
+ }
290
+
291
+ return relationships;
292
+
293
+ }
294
+
295
+ function parseMetadataNodes( metadataNodes ) {
296
+
297
+ const metadataData = {};
298
+
299
+ for ( let i = 0; i < metadataNodes.length; i ++ ) {
300
+
301
+ const metadataNode = metadataNodes[ i ];
302
+ const name = metadataNode.getAttribute( 'name' );
303
+ const validNames = [
304
+ 'Title',
305
+ 'Designer',
306
+ 'Description',
307
+ 'Copyright',
308
+ 'LicenseTerms',
309
+ 'Rating',
310
+ 'CreationDate',
311
+ 'ModificationDate'
312
+ ];
313
+
314
+ if ( 0 <= validNames.indexOf( name ) ) {
315
+
316
+ metadataData[ name ] = metadataNode.textContent;
317
+
318
+ }
319
+
320
+ }
321
+
322
+ return metadataData;
323
+
324
+ }
325
+
326
+ function parseBasematerialsNode( basematerialsNode ) {
327
+
328
+ const basematerialsData = {
329
+ id: basematerialsNode.getAttribute( 'id' ), // required
330
+ basematerials: []
331
+ };
332
+
333
+ const basematerialNodes = basematerialsNode.querySelectorAll( 'base' );
334
+
335
+ for ( let i = 0; i < basematerialNodes.length; i ++ ) {
336
+
337
+ const basematerialNode = basematerialNodes[ i ];
338
+ const basematerialData = parseBasematerialNode( basematerialNode );
339
+ basematerialData.index = i; // the order and count of the material nodes form an implicit 0-based index
340
+ basematerialsData.basematerials.push( basematerialData );
341
+
342
+ }
343
+
344
+ return basematerialsData;
345
+
346
+ }
347
+
348
+ function parseTexture2DNode( texture2DNode ) {
349
+
350
+ const texture2dData = {
351
+ id: texture2DNode.getAttribute( 'id' ), // required
352
+ path: texture2DNode.getAttribute( 'path' ), // required
353
+ contenttype: texture2DNode.getAttribute( 'contenttype' ), // required
354
+ tilestyleu: texture2DNode.getAttribute( 'tilestyleu' ),
355
+ tilestylev: texture2DNode.getAttribute( 'tilestylev' ),
356
+ filter: texture2DNode.getAttribute( 'filter' ),
357
+ };
358
+
359
+ return texture2dData;
360
+
361
+ }
362
+
363
+ function parseTextures2DGroupNode( texture2DGroupNode ) {
364
+
365
+ const texture2DGroupData = {
366
+ id: texture2DGroupNode.getAttribute( 'id' ), // required
367
+ texid: texture2DGroupNode.getAttribute( 'texid' ), // required
368
+ displaypropertiesid: texture2DGroupNode.getAttribute( 'displaypropertiesid' )
369
+ };
370
+
371
+ const tex2coordNodes = texture2DGroupNode.querySelectorAll( 'tex2coord' );
372
+
373
+ const uvs = [];
374
+
375
+ for ( let i = 0; i < tex2coordNodes.length; i ++ ) {
376
+
377
+ const tex2coordNode = tex2coordNodes[ i ];
378
+ const u = tex2coordNode.getAttribute( 'u' );
379
+ const v = tex2coordNode.getAttribute( 'v' );
380
+
381
+ uvs.push( parseFloat( u ), parseFloat( v ) );
382
+
383
+ }
384
+
385
+ texture2DGroupData[ 'uvs' ] = new Float32Array( uvs );
386
+
387
+ return texture2DGroupData;
388
+
389
+ }
390
+
391
+ function parseColorGroupNode( colorGroupNode ) {
392
+
393
+ const colorGroupData = {
394
+ id: colorGroupNode.getAttribute( 'id' ), // required
395
+ displaypropertiesid: colorGroupNode.getAttribute( 'displaypropertiesid' )
396
+ };
397
+
398
+ const colorNodes = colorGroupNode.querySelectorAll( 'color' );
399
+
400
+ const colors = [];
401
+ const colorObject = new Color();
402
+
403
+ for ( let i = 0; i < colorNodes.length; i ++ ) {
404
+
405
+ const colorNode = colorNodes[ i ];
406
+ const color = colorNode.getAttribute( 'color' );
407
+
408
+ colorObject.setStyle( color.substring( 0, 7 ), COLOR_SPACE_3MF );
409
+
410
+ colors.push( colorObject.r, colorObject.g, colorObject.b );
411
+
412
+ }
413
+
414
+ colorGroupData[ 'colors' ] = new Float32Array( colors );
415
+
416
+ return colorGroupData;
417
+
418
+ }
419
+
420
+ function parseImplicitIONode( implicitIONode ) {
421
+
422
+ const portNodes = implicitIONode.children;
423
+ const portArguments = {};
424
+ for ( let i = 0; i < portNodes.length; i ++ ) {
425
+
426
+ const args = { type: portNodes[ i ].nodeName.substring( 2 ) };
427
+ for ( let j = 0; j < portNodes[ i ].attributes.length; j ++ ) {
428
+
429
+ const attrib = portNodes[ i ].attributes[ j ];
430
+ if ( attrib.specified ) {
431
+
432
+ args[ attrib.name ] = attrib.value;
433
+
434
+ }
435
+
436
+ }
437
+
438
+ portArguments[ portNodes[ i ].getAttribute( 'identifier' ) ] = args;
439
+
440
+ }
441
+
442
+ return portArguments;
443
+
444
+ }
445
+
446
+ function parseImplicitFunctionNode( implicitFunctionNode ) {
447
+
448
+ const implicitFunctionData = {
449
+ id: implicitFunctionNode.getAttribute( 'id' ),
450
+ displayname: implicitFunctionNode.getAttribute( 'displayname' )
451
+ };
452
+
453
+ const functionNodes = implicitFunctionNode.children;
454
+
455
+ const operations = {};
456
+
457
+ for ( let i = 0; i < functionNodes.length; i ++ ) {
458
+
459
+ const operatorNode = functionNodes[ i ];
460
+
461
+ if ( operatorNode.nodeName === 'i:in' || operatorNode.nodeName === 'i:out' ) {
462
+
463
+ operations[ operatorNode.nodeName === 'i:in' ? 'inputs' : 'outputs' ] = parseImplicitIONode( operatorNode );
464
+
465
+ } else {
466
+
467
+ const inputNodes = operatorNode.children;
468
+ const portArguments = { 'op': operatorNode.nodeName.substring( 2 ), 'identifier': operatorNode.getAttribute( 'identifier' ) };
469
+ for ( let i = 0; i < inputNodes.length; i ++ ) {
470
+
471
+ portArguments[ inputNodes[ i ].nodeName.substring( 2 ) ] = parseImplicitIONode( inputNodes[ i ] );
472
+
473
+ }
474
+
475
+ operations[ portArguments[ 'identifier' ] ] = portArguments;
476
+
477
+ }
478
+
479
+ }
480
+
481
+ implicitFunctionData[ 'operations' ] = operations;
482
+
483
+ return implicitFunctionData;
484
+
485
+ }
486
+
487
+ function parseMetallicDisplaypropertiesNode( metallicDisplaypropetiesNode ) {
488
+
489
+ const metallicDisplaypropertiesData = {
490
+ id: metallicDisplaypropetiesNode.getAttribute( 'id' ) // required
491
+ };
492
+
493
+ const metallicNodes = metallicDisplaypropetiesNode.querySelectorAll( 'pbmetallic' );
494
+
495
+ const metallicData = [];
496
+
497
+ for ( let i = 0; i < metallicNodes.length; i ++ ) {
498
+
499
+ const metallicNode = metallicNodes[ i ];
500
+
501
+ metallicData.push( {
502
+ name: metallicNode.getAttribute( 'name' ), // required
503
+ metallicness: parseFloat( metallicNode.getAttribute( 'metallicness' ) ), // required
504
+ roughness: parseFloat( metallicNode.getAttribute( 'roughness' ) ) // required
505
+ } );
506
+
507
+ }
508
+
509
+ metallicDisplaypropertiesData.data = metallicData;
510
+
511
+ return metallicDisplaypropertiesData;
512
+
513
+ }
514
+
515
+ function parseBasematerialNode( basematerialNode ) {
516
+
517
+ const basematerialData = {};
518
+
519
+ basematerialData[ 'name' ] = basematerialNode.getAttribute( 'name' ); // required
520
+ basematerialData[ 'displaycolor' ] = basematerialNode.getAttribute( 'displaycolor' ); // required
521
+ basematerialData[ 'displaypropertiesid' ] = basematerialNode.getAttribute( 'displaypropertiesid' );
522
+
523
+ return basematerialData;
524
+
525
+ }
526
+
527
+ function parseMeshNode( meshNode ) {
528
+
529
+ const meshData = {};
530
+
531
+ const vertices = [];
532
+ const vertexNodes = meshNode.querySelectorAll( 'vertices vertex' );
533
+
534
+ for ( let i = 0; i < vertexNodes.length; i ++ ) {
535
+
536
+ const vertexNode = vertexNodes[ i ];
537
+ const x = vertexNode.getAttribute( 'x' );
538
+ const y = vertexNode.getAttribute( 'y' );
539
+ const z = vertexNode.getAttribute( 'z' );
540
+
541
+ vertices.push( parseFloat( x ), parseFloat( y ), parseFloat( z ) );
542
+
543
+ }
544
+
545
+ meshData[ 'vertices' ] = new Float32Array( vertices );
546
+
547
+ const triangleProperties = [];
548
+ const triangles = [];
549
+ const triangleNodes = meshNode.querySelectorAll( 'triangles triangle' );
550
+
551
+ for ( let i = 0; i < triangleNodes.length; i ++ ) {
552
+
553
+ const triangleNode = triangleNodes[ i ];
554
+ const v1 = triangleNode.getAttribute( 'v1' );
555
+ const v2 = triangleNode.getAttribute( 'v2' );
556
+ const v3 = triangleNode.getAttribute( 'v3' );
557
+ const p1 = triangleNode.getAttribute( 'p1' );
558
+ const p2 = triangleNode.getAttribute( 'p2' );
559
+ const p3 = triangleNode.getAttribute( 'p3' );
560
+ const pid = triangleNode.getAttribute( 'pid' );
561
+
562
+ const triangleProperty = {};
563
+
564
+ triangleProperty[ 'v1' ] = parseInt( v1, 10 );
565
+ triangleProperty[ 'v2' ] = parseInt( v2, 10 );
566
+ triangleProperty[ 'v3' ] = parseInt( v3, 10 );
567
+
568
+ triangles.push( triangleProperty[ 'v1' ], triangleProperty[ 'v2' ], triangleProperty[ 'v3' ] );
569
+
570
+ // optional
571
+
572
+ if ( p1 ) {
573
+
574
+ triangleProperty[ 'p1' ] = parseInt( p1, 10 );
575
+
576
+ }
577
+
578
+ if ( p2 ) {
579
+
580
+ triangleProperty[ 'p2' ] = parseInt( p2, 10 );
581
+
582
+ }
583
+
584
+ if ( p3 ) {
585
+
586
+ triangleProperty[ 'p3' ] = parseInt( p3, 10 );
587
+
588
+ }
589
+
590
+ if ( pid ) {
591
+
592
+ triangleProperty[ 'pid' ] = pid;
593
+
594
+ }
595
+
596
+ if ( 0 < Object.keys( triangleProperty ).length ) {
597
+
598
+ triangleProperties.push( triangleProperty );
599
+
600
+ }
601
+
602
+ }
603
+
604
+ meshData[ 'triangleProperties' ] = triangleProperties;
605
+ meshData[ 'triangles' ] = new Uint32Array( triangles );
606
+
607
+ return meshData;
608
+
609
+ }
610
+
611
+ function parseComponentsNode( componentsNode ) {
612
+
613
+ const components = [];
614
+
615
+ const componentNodes = componentsNode.querySelectorAll( 'component' );
616
+
617
+ for ( let i = 0; i < componentNodes.length; i ++ ) {
618
+
619
+ const componentNode = componentNodes[ i ];
620
+ const componentData = parseComponentNode( componentNode );
621
+ components.push( componentData );
622
+
623
+ }
624
+
625
+ return components;
626
+
627
+ }
628
+
629
+ function parseComponentNode( componentNode ) {
630
+
631
+ const componentData = {};
632
+
633
+ componentData[ 'objectId' ] = componentNode.getAttribute( 'objectid' ); // required
634
+
635
+ const transform = componentNode.getAttribute( 'transform' );
636
+
637
+ if ( transform ) {
638
+
639
+ componentData[ 'transform' ] = parseTransform( transform );
640
+
641
+ }
642
+
643
+ return componentData;
644
+
645
+ }
646
+
647
+ function parseTransform( transform ) {
648
+
649
+ const t = [];
650
+ transform.split( ' ' ).forEach( function ( s ) {
651
+
652
+ t.push( parseFloat( s ) );
653
+
654
+ } );
655
+
656
+ const matrix = new Matrix4();
657
+ matrix.set(
658
+ t[ 0 ], t[ 3 ], t[ 6 ], t[ 9 ],
659
+ t[ 1 ], t[ 4 ], t[ 7 ], t[ 10 ],
660
+ t[ 2 ], t[ 5 ], t[ 8 ], t[ 11 ],
661
+ 0.0, 0.0, 0.0, 1.0
662
+ );
663
+
664
+ return matrix;
665
+
666
+ }
667
+
668
+ function parseObjectNode( objectNode ) {
669
+
670
+ const objectData = {
671
+ type: objectNode.getAttribute( 'type' )
672
+ };
673
+
674
+ const id = objectNode.getAttribute( 'id' );
675
+
676
+ if ( id ) {
677
+
678
+ objectData[ 'id' ] = id;
679
+
680
+ }
681
+
682
+ const pid = objectNode.getAttribute( 'pid' );
683
+
684
+ if ( pid ) {
685
+
686
+ objectData[ 'pid' ] = pid;
687
+
688
+ }
689
+
690
+ const pindex = objectNode.getAttribute( 'pindex' );
691
+
692
+ if ( pindex ) {
693
+
694
+ objectData[ 'pindex' ] = pindex;
695
+
696
+ }
697
+
698
+ const thumbnail = objectNode.getAttribute( 'thumbnail' );
699
+
700
+ if ( thumbnail ) {
701
+
702
+ objectData[ 'thumbnail' ] = thumbnail;
703
+
704
+ }
705
+
706
+ const partnumber = objectNode.getAttribute( 'partnumber' );
707
+
708
+ if ( partnumber ) {
709
+
710
+ objectData[ 'partnumber' ] = partnumber;
711
+
712
+ }
713
+
714
+ const name = objectNode.getAttribute( 'name' );
715
+
716
+ if ( name ) {
717
+
718
+ objectData[ 'name' ] = name;
719
+
720
+ }
721
+
722
+ const meshNode = objectNode.querySelector( 'mesh' );
723
+
724
+ if ( meshNode ) {
725
+
726
+ objectData[ 'mesh' ] = parseMeshNode( meshNode );
727
+
728
+ }
729
+
730
+ const componentsNode = objectNode.querySelector( 'components' );
731
+
732
+ if ( componentsNode ) {
733
+
734
+ objectData[ 'components' ] = parseComponentsNode( componentsNode );
735
+
736
+ }
737
+
738
+ return objectData;
739
+
740
+ }
741
+
742
+ function parseResourcesNode( resourcesNode ) {
743
+
744
+ const resourcesData = {};
745
+
746
+ resourcesData[ 'basematerials' ] = {};
747
+ const basematerialsNodes = resourcesNode.querySelectorAll( 'basematerials' );
748
+
749
+ for ( let i = 0; i < basematerialsNodes.length; i ++ ) {
750
+
751
+ const basematerialsNode = basematerialsNodes[ i ];
752
+ const basematerialsData = parseBasematerialsNode( basematerialsNode );
753
+ resourcesData[ 'basematerials' ][ basematerialsData[ 'id' ] ] = basematerialsData;
754
+
755
+ }
756
+
757
+ //
758
+
759
+ resourcesData[ 'texture2d' ] = {};
760
+ const textures2DNodes = resourcesNode.querySelectorAll( 'texture2d' );
761
+
762
+ for ( let i = 0; i < textures2DNodes.length; i ++ ) {
763
+
764
+ const textures2DNode = textures2DNodes[ i ];
765
+ const texture2DData = parseTexture2DNode( textures2DNode );
766
+ resourcesData[ 'texture2d' ][ texture2DData[ 'id' ] ] = texture2DData;
767
+
768
+ }
769
+
770
+ //
771
+
772
+ resourcesData[ 'colorgroup' ] = {};
773
+ const colorGroupNodes = resourcesNode.querySelectorAll( 'colorgroup' );
774
+
775
+ for ( let i = 0; i < colorGroupNodes.length; i ++ ) {
776
+
777
+ const colorGroupNode = colorGroupNodes[ i ];
778
+ const colorGroupData = parseColorGroupNode( colorGroupNode );
779
+ resourcesData[ 'colorgroup' ][ colorGroupData[ 'id' ] ] = colorGroupData;
780
+
781
+ }
782
+
783
+ //
784
+
785
+ const implicitFunctionNodes = resourcesNode.querySelectorAll( 'implicitfunction' );
786
+
787
+ if ( implicitFunctionNodes.length > 0 ) {
788
+
789
+ resourcesData[ 'implicitfunction' ] = {};
790
+
791
+ }
792
+
793
+
794
+ for ( let i = 0; i < implicitFunctionNodes.length; i ++ ) {
795
+
796
+ const implicitFunctionNode = implicitFunctionNodes[ i ];
797
+ const implicitFunctionData = parseImplicitFunctionNode( implicitFunctionNode );
798
+ resourcesData[ 'implicitfunction' ][ implicitFunctionData[ 'id' ] ] = implicitFunctionData;
799
+
800
+ }
801
+
802
+ //
803
+
804
+ resourcesData[ 'pbmetallicdisplayproperties' ] = {};
805
+ const pbmetallicdisplaypropertiesNodes = resourcesNode.querySelectorAll( 'pbmetallicdisplayproperties' );
806
+
807
+ for ( let i = 0; i < pbmetallicdisplaypropertiesNodes.length; i ++ ) {
808
+
809
+ const pbmetallicdisplaypropertiesNode = pbmetallicdisplaypropertiesNodes[ i ];
810
+ const pbmetallicdisplaypropertiesData = parseMetallicDisplaypropertiesNode( pbmetallicdisplaypropertiesNode );
811
+ resourcesData[ 'pbmetallicdisplayproperties' ][ pbmetallicdisplaypropertiesData[ 'id' ] ] = pbmetallicdisplaypropertiesData;
812
+
813
+ }
814
+
815
+ //
816
+
817
+ resourcesData[ 'texture2dgroup' ] = {};
818
+ const textures2DGroupNodes = resourcesNode.querySelectorAll( 'texture2dgroup' );
819
+
820
+ for ( let i = 0; i < textures2DGroupNodes.length; i ++ ) {
821
+
822
+ const textures2DGroupNode = textures2DGroupNodes[ i ];
823
+ const textures2DGroupData = parseTextures2DGroupNode( textures2DGroupNode );
824
+ resourcesData[ 'texture2dgroup' ][ textures2DGroupData[ 'id' ] ] = textures2DGroupData;
825
+
826
+ }
827
+
828
+ //
829
+
830
+ resourcesData[ 'object' ] = {};
831
+ const objectNodes = resourcesNode.querySelectorAll( 'object' );
832
+
833
+ for ( let i = 0; i < objectNodes.length; i ++ ) {
834
+
835
+ const objectNode = objectNodes[ i ];
836
+ const objectData = parseObjectNode( objectNode );
837
+ resourcesData[ 'object' ][ objectData[ 'id' ] ] = objectData;
838
+
839
+ }
840
+
841
+ return resourcesData;
842
+
843
+ }
844
+
845
+ function parseBuildNode( buildNode ) {
846
+
847
+ const buildData = [];
848
+ const itemNodes = buildNode.querySelectorAll( 'item' );
849
+
850
+ for ( let i = 0; i < itemNodes.length; i ++ ) {
851
+
852
+ const itemNode = itemNodes[ i ];
853
+ const buildItem = {
854
+ objectId: itemNode.getAttribute( 'objectid' )
855
+ };
856
+ const transform = itemNode.getAttribute( 'transform' );
857
+
858
+ if ( transform ) {
859
+
860
+ buildItem[ 'transform' ] = parseTransform( transform );
861
+
862
+ }
863
+
864
+ buildData.push( buildItem );
865
+
866
+ }
867
+
868
+ return buildData;
869
+
870
+ }
871
+
872
+ function parseModelNode( modelNode ) {
873
+
874
+ const modelData = { unit: modelNode.getAttribute( 'unit' ) || 'millimeter' };
875
+ const metadataNodes = modelNode.querySelectorAll( 'metadata' );
876
+
877
+ if ( metadataNodes ) {
878
+
879
+ modelData[ 'metadata' ] = parseMetadataNodes( metadataNodes );
880
+
881
+ }
882
+
883
+ const resourcesNode = modelNode.querySelector( 'resources' );
884
+
885
+ if ( resourcesNode ) {
886
+
887
+ modelData[ 'resources' ] = parseResourcesNode( resourcesNode );
888
+
889
+ }
890
+
891
+ const buildNode = modelNode.querySelector( 'build' );
892
+
893
+ if ( buildNode ) {
894
+
895
+ modelData[ 'build' ] = parseBuildNode( buildNode );
896
+
897
+ }
898
+
899
+ return modelData;
900
+
901
+ }
902
+
903
+ function buildTexture( texture2dgroup, objects, modelData, textureData ) {
904
+
905
+ const texid = texture2dgroup.texid;
906
+ const texture2ds = modelData.resources.texture2d;
907
+ const texture2d = texture2ds[ texid ];
908
+
909
+ if ( texture2d ) {
910
+
911
+ const data = textureData[ texture2d.path ];
912
+ const type = texture2d.contenttype;
913
+
914
+ const blob = new Blob( [ data ], { type: type } );
915
+ const sourceURI = URL.createObjectURL( blob );
916
+
917
+ const texture = textureLoader.load( sourceURI, function () {
918
+
919
+ URL.revokeObjectURL( sourceURI );
920
+
921
+ } );
922
+
923
+ texture.colorSpace = COLOR_SPACE_3MF;
924
+
925
+ // texture parameters
926
+
927
+ switch ( texture2d.tilestyleu ) {
928
+
929
+ case 'wrap':
930
+ texture.wrapS = RepeatWrapping;
931
+ break;
932
+
933
+ case 'mirror':
934
+ texture.wrapS = MirroredRepeatWrapping;
935
+ break;
936
+
937
+ case 'none':
938
+ case 'clamp':
939
+ texture.wrapS = ClampToEdgeWrapping;
940
+ break;
941
+
942
+ default:
943
+ texture.wrapS = RepeatWrapping;
944
+
945
+ }
946
+
947
+ switch ( texture2d.tilestylev ) {
948
+
949
+ case 'wrap':
950
+ texture.wrapT = RepeatWrapping;
951
+ break;
952
+
953
+ case 'mirror':
954
+ texture.wrapT = MirroredRepeatWrapping;
955
+ break;
956
+
957
+ case 'none':
958
+ case 'clamp':
959
+ texture.wrapT = ClampToEdgeWrapping;
960
+ break;
961
+
962
+ default:
963
+ texture.wrapT = RepeatWrapping;
964
+
965
+ }
966
+
967
+ switch ( texture2d.filter ) {
968
+
969
+ case 'auto':
970
+ texture.magFilter = LinearFilter;
971
+ texture.minFilter = LinearMipmapLinearFilter;
972
+ break;
973
+
974
+ case 'linear':
975
+ texture.magFilter = LinearFilter;
976
+ texture.minFilter = LinearFilter;
977
+ texture.generateMipmaps = false;
978
+ break;
979
+
980
+ case 'nearest':
981
+ texture.magFilter = NearestFilter;
982
+ texture.minFilter = NearestFilter;
983
+ texture.generateMipmaps = false;
984
+ break;
985
+
986
+ default:
987
+ texture.magFilter = LinearFilter;
988
+ texture.minFilter = LinearMipmapLinearFilter;
989
+
990
+ }
991
+
992
+ return texture;
993
+
994
+ } else {
995
+
996
+ return null;
997
+
998
+ }
999
+
1000
+ }
1001
+
1002
+ function buildBasematerialsMeshes( basematerials, triangleProperties, meshData, objects, modelData, textureData, objectData ) {
1003
+
1004
+ const objectPindex = objectData.pindex;
1005
+
1006
+ const materialMap = {};
1007
+
1008
+ for ( let i = 0, l = triangleProperties.length; i < l; i ++ ) {
1009
+
1010
+ const triangleProperty = triangleProperties[ i ];
1011
+ const pindex = ( triangleProperty.p1 !== undefined ) ? triangleProperty.p1 : objectPindex;
1012
+
1013
+ if ( materialMap[ pindex ] === undefined ) materialMap[ pindex ] = [];
1014
+
1015
+ materialMap[ pindex ].push( triangleProperty );
1016
+
1017
+ }
1018
+
1019
+ //
1020
+
1021
+ const keys = Object.keys( materialMap );
1022
+ const meshes = [];
1023
+
1024
+ for ( let i = 0, l = keys.length; i < l; i ++ ) {
1025
+
1026
+ const materialIndex = keys[ i ];
1027
+ const trianglePropertiesProps = materialMap[ materialIndex ];
1028
+ const basematerialData = basematerials.basematerials[ materialIndex ];
1029
+ const material = getBuild( basematerialData, objects, modelData, textureData, objectData, buildBasematerial );
1030
+
1031
+ //
1032
+
1033
+ const geometry = new BufferGeometry();
1034
+
1035
+ const positionData = [];
1036
+
1037
+ const vertices = meshData.vertices;
1038
+
1039
+ for ( let j = 0, jl = trianglePropertiesProps.length; j < jl; j ++ ) {
1040
+
1041
+ const triangleProperty = trianglePropertiesProps[ j ];
1042
+
1043
+ positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 0 ] );
1044
+ positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 1 ] );
1045
+ positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 2 ] );
1046
+
1047
+ positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 0 ] );
1048
+ positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 1 ] );
1049
+ positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 2 ] );
1050
+
1051
+ positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 0 ] );
1052
+ positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 1 ] );
1053
+ positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 2 ] );
1054
+
1055
+
1056
+ }
1057
+
1058
+ geometry.setAttribute( 'position', new Float32BufferAttribute( positionData, 3 ) );
1059
+
1060
+ //
1061
+
1062
+ const mesh = new Mesh( geometry, material );
1063
+ meshes.push( mesh );
1064
+
1065
+ }
1066
+
1067
+ return meshes;
1068
+
1069
+ }
1070
+
1071
+ function buildTexturedMesh( texture2dgroup, triangleProperties, meshData, objects, modelData, textureData, objectData ) {
1072
+
1073
+ // geometry
1074
+
1075
+ const geometry = new BufferGeometry();
1076
+
1077
+ const positionData = [];
1078
+ const uvData = [];
1079
+
1080
+ const vertices = meshData.vertices;
1081
+ const uvs = texture2dgroup.uvs;
1082
+
1083
+ for ( let i = 0, l = triangleProperties.length; i < l; i ++ ) {
1084
+
1085
+ const triangleProperty = triangleProperties[ i ];
1086
+
1087
+ positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 0 ] );
1088
+ positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 1 ] );
1089
+ positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 2 ] );
1090
+
1091
+ positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 0 ] );
1092
+ positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 1 ] );
1093
+ positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 2 ] );
1094
+
1095
+ positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 0 ] );
1096
+ positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 1 ] );
1097
+ positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 2 ] );
1098
+
1099
+ //
1100
+
1101
+ uvData.push( uvs[ ( triangleProperty.p1 * 2 ) + 0 ] );
1102
+ uvData.push( uvs[ ( triangleProperty.p1 * 2 ) + 1 ] );
1103
+
1104
+ uvData.push( uvs[ ( triangleProperty.p2 * 2 ) + 0 ] );
1105
+ uvData.push( uvs[ ( triangleProperty.p2 * 2 ) + 1 ] );
1106
+
1107
+ uvData.push( uvs[ ( triangleProperty.p3 * 2 ) + 0 ] );
1108
+ uvData.push( uvs[ ( triangleProperty.p3 * 2 ) + 1 ] );
1109
+
1110
+ }
1111
+
1112
+ geometry.setAttribute( 'position', new Float32BufferAttribute( positionData, 3 ) );
1113
+ geometry.setAttribute( 'uv', new Float32BufferAttribute( uvData, 2 ) );
1114
+
1115
+ // material
1116
+
1117
+ const texture = getBuild( texture2dgroup, objects, modelData, textureData, objectData, buildTexture );
1118
+
1119
+ const material = new MeshPhongMaterial( { map: texture, flatShading: true } );
1120
+
1121
+ // mesh
1122
+
1123
+ const mesh = new Mesh( geometry, material );
1124
+
1125
+ return mesh;
1126
+
1127
+ }
1128
+
1129
+ function buildVertexColorMesh( colorgroup, triangleProperties, meshData, objectData ) {
1130
+
1131
+ // geometry
1132
+
1133
+ const geometry = new BufferGeometry();
1134
+
1135
+ const positionData = [];
1136
+ const colorData = [];
1137
+
1138
+ const vertices = meshData.vertices;
1139
+ const colors = colorgroup.colors;
1140
+
1141
+ for ( let i = 0, l = triangleProperties.length; i < l; i ++ ) {
1142
+
1143
+ const triangleProperty = triangleProperties[ i ];
1144
+
1145
+ const v1 = triangleProperty.v1;
1146
+ const v2 = triangleProperty.v2;
1147
+ const v3 = triangleProperty.v3;
1148
+
1149
+ positionData.push( vertices[ ( v1 * 3 ) + 0 ] );
1150
+ positionData.push( vertices[ ( v1 * 3 ) + 1 ] );
1151
+ positionData.push( vertices[ ( v1 * 3 ) + 2 ] );
1152
+
1153
+ positionData.push( vertices[ ( v2 * 3 ) + 0 ] );
1154
+ positionData.push( vertices[ ( v2 * 3 ) + 1 ] );
1155
+ positionData.push( vertices[ ( v2 * 3 ) + 2 ] );
1156
+
1157
+ positionData.push( vertices[ ( v3 * 3 ) + 0 ] );
1158
+ positionData.push( vertices[ ( v3 * 3 ) + 1 ] );
1159
+ positionData.push( vertices[ ( v3 * 3 ) + 2 ] );
1160
+
1161
+ //
1162
+
1163
+ const p1 = ( triangleProperty.p1 !== undefined ) ? triangleProperty.p1 : objectData.pindex;
1164
+ const p2 = ( triangleProperty.p2 !== undefined ) ? triangleProperty.p2 : p1;
1165
+ const p3 = ( triangleProperty.p3 !== undefined ) ? triangleProperty.p3 : p1;
1166
+
1167
+ colorData.push( colors[ ( p1 * 3 ) + 0 ] );
1168
+ colorData.push( colors[ ( p1 * 3 ) + 1 ] );
1169
+ colorData.push( colors[ ( p1 * 3 ) + 2 ] );
1170
+
1171
+ colorData.push( colors[ ( p2 * 3 ) + 0 ] );
1172
+ colorData.push( colors[ ( p2 * 3 ) + 1 ] );
1173
+ colorData.push( colors[ ( p2 * 3 ) + 2 ] );
1174
+
1175
+ colorData.push( colors[ ( p3 * 3 ) + 0 ] );
1176
+ colorData.push( colors[ ( p3 * 3 ) + 1 ] );
1177
+ colorData.push( colors[ ( p3 * 3 ) + 2 ] );
1178
+
1179
+ }
1180
+
1181
+ geometry.setAttribute( 'position', new Float32BufferAttribute( positionData, 3 ) );
1182
+ geometry.setAttribute( 'color', new Float32BufferAttribute( colorData, 3 ) );
1183
+
1184
+ // material
1185
+
1186
+ const material = new MeshPhongMaterial( { vertexColors: true, flatShading: true } );
1187
+
1188
+ // mesh
1189
+
1190
+ const mesh = new Mesh( geometry, material );
1191
+
1192
+ return mesh;
1193
+
1194
+ }
1195
+
1196
+ function buildDefaultMesh( meshData ) {
1197
+
1198
+ const geometry = new BufferGeometry();
1199
+ geometry.setIndex( new BufferAttribute( meshData[ 'triangles' ], 1 ) );
1200
+ geometry.setAttribute( 'position', new BufferAttribute( meshData[ 'vertices' ], 3 ) );
1201
+
1202
+ const material = new MeshPhongMaterial( {
1203
+ name: Loader.DEFAULT_MATERIAL_NAME,
1204
+ color: 0xffffff,
1205
+ flatShading: true
1206
+ } );
1207
+
1208
+ const mesh = new Mesh( geometry, material );
1209
+
1210
+ return mesh;
1211
+
1212
+ }
1213
+
1214
+ function buildMeshes( resourceMap, meshData, objects, modelData, textureData, objectData ) {
1215
+
1216
+ const keys = Object.keys( resourceMap );
1217
+ const meshes = [];
1218
+
1219
+ for ( let i = 0, il = keys.length; i < il; i ++ ) {
1220
+
1221
+ const resourceId = keys[ i ];
1222
+ const triangleProperties = resourceMap[ resourceId ];
1223
+ const resourceType = getResourceType( resourceId, modelData );
1224
+
1225
+ switch ( resourceType ) {
1226
+
1227
+ case 'material':
1228
+ const basematerials = modelData.resources.basematerials[ resourceId ];
1229
+ const newMeshes = buildBasematerialsMeshes( basematerials, triangleProperties, meshData, objects, modelData, textureData, objectData );
1230
+
1231
+ for ( let j = 0, jl = newMeshes.length; j < jl; j ++ ) {
1232
+
1233
+ meshes.push( newMeshes[ j ] );
1234
+
1235
+ }
1236
+
1237
+ break;
1238
+
1239
+ case 'texture':
1240
+ const texture2dgroup = modelData.resources.texture2dgroup[ resourceId ];
1241
+ meshes.push( buildTexturedMesh( texture2dgroup, triangleProperties, meshData, objects, modelData, textureData, objectData ) );
1242
+ break;
1243
+
1244
+ case 'vertexColors':
1245
+ const colorgroup = modelData.resources.colorgroup[ resourceId ];
1246
+ meshes.push( buildVertexColorMesh( colorgroup, triangleProperties, meshData, objectData ) );
1247
+ break;
1248
+
1249
+ case 'default':
1250
+ meshes.push( buildDefaultMesh( meshData ) );
1251
+ break;
1252
+
1253
+ default:
1254
+ console.error( 'THREE.3MFLoader: Unsupported resource type.' );
1255
+
1256
+ }
1257
+
1258
+ }
1259
+
1260
+ if ( objectData.name ) {
1261
+
1262
+ for ( let i = 0; i < meshes.length; i ++ ) {
1263
+
1264
+ meshes[ i ].name = objectData.name;
1265
+
1266
+ }
1267
+
1268
+ }
1269
+
1270
+ return meshes;
1271
+
1272
+ }
1273
+
1274
+ function getResourceType( pid, modelData ) {
1275
+
1276
+ if ( modelData.resources.texture2dgroup[ pid ] !== undefined ) {
1277
+
1278
+ return 'texture';
1279
+
1280
+ } else if ( modelData.resources.basematerials[ pid ] !== undefined ) {
1281
+
1282
+ return 'material';
1283
+
1284
+ } else if ( modelData.resources.colorgroup[ pid ] !== undefined ) {
1285
+
1286
+ return 'vertexColors';
1287
+
1288
+ } else if ( pid === 'default' ) {
1289
+
1290
+ return 'default';
1291
+
1292
+ } else {
1293
+
1294
+ return undefined;
1295
+
1296
+ }
1297
+
1298
+ }
1299
+
1300
+ function analyzeObject( meshData, objectData ) {
1301
+
1302
+ const resourceMap = {};
1303
+
1304
+ const triangleProperties = meshData[ 'triangleProperties' ];
1305
+
1306
+ const objectPid = objectData.pid;
1307
+
1308
+ for ( let i = 0, l = triangleProperties.length; i < l; i ++ ) {
1309
+
1310
+ const triangleProperty = triangleProperties[ i ];
1311
+ let pid = ( triangleProperty.pid !== undefined ) ? triangleProperty.pid : objectPid;
1312
+
1313
+ if ( pid === undefined ) pid = 'default';
1314
+
1315
+ if ( resourceMap[ pid ] === undefined ) resourceMap[ pid ] = [];
1316
+
1317
+ resourceMap[ pid ].push( triangleProperty );
1318
+
1319
+ }
1320
+
1321
+ return resourceMap;
1322
+
1323
+ }
1324
+
1325
+ function buildGroup( meshData, objects, modelData, textureData, objectData ) {
1326
+
1327
+ const group = new Group();
1328
+
1329
+ const resourceMap = analyzeObject( meshData, objectData );
1330
+ const meshes = buildMeshes( resourceMap, meshData, objects, modelData, textureData, objectData );
1331
+
1332
+ for ( let i = 0, l = meshes.length; i < l; i ++ ) {
1333
+
1334
+ group.add( meshes[ i ] );
1335
+
1336
+ }
1337
+
1338
+ return group;
1339
+
1340
+ }
1341
+
1342
+ function applyExtensions( extensions, meshData, modelXml ) {
1343
+
1344
+ if ( ! extensions ) {
1345
+
1346
+ return;
1347
+
1348
+ }
1349
+
1350
+ const availableExtensions = [];
1351
+ const keys = Object.keys( extensions );
1352
+
1353
+ for ( let i = 0; i < keys.length; i ++ ) {
1354
+
1355
+ const ns = keys[ i ];
1356
+
1357
+ for ( let j = 0; j < scope.availableExtensions.length; j ++ ) {
1358
+
1359
+ const extension = scope.availableExtensions[ j ];
1360
+
1361
+ if ( extension.ns === ns ) {
1362
+
1363
+ availableExtensions.push( extension );
1364
+
1365
+ }
1366
+
1367
+ }
1368
+
1369
+ }
1370
+
1371
+ for ( let i = 0; i < availableExtensions.length; i ++ ) {
1372
+
1373
+ const extension = availableExtensions[ i ];
1374
+ extension.apply( modelXml, extensions[ extension[ 'ns' ] ], meshData );
1375
+
1376
+ }
1377
+
1378
+ }
1379
+
1380
+ function getBuild( data, objects, modelData, textureData, objectData, builder ) {
1381
+
1382
+ if ( data.build !== undefined ) return data.build;
1383
+
1384
+ data.build = builder( data, objects, modelData, textureData, objectData );
1385
+
1386
+ return data.build;
1387
+
1388
+ }
1389
+
1390
+ function buildBasematerial( materialData, objects, modelData ) {
1391
+
1392
+ let material;
1393
+
1394
+ const displaypropertiesid = materialData.displaypropertiesid;
1395
+ const pbmetallicdisplayproperties = modelData.resources.pbmetallicdisplayproperties;
1396
+
1397
+ if ( displaypropertiesid !== null && pbmetallicdisplayproperties[ displaypropertiesid ] !== undefined ) {
1398
+
1399
+ // metallic display property, use StandardMaterial
1400
+
1401
+ const pbmetallicdisplayproperty = pbmetallicdisplayproperties[ displaypropertiesid ];
1402
+ const metallicData = pbmetallicdisplayproperty.data[ materialData.index ];
1403
+
1404
+ material = new MeshStandardMaterial( { flatShading: true, roughness: metallicData.roughness, metalness: metallicData.metallicness } );
1405
+
1406
+ } else {
1407
+
1408
+ // otherwise use PhongMaterial
1409
+
1410
+ material = new MeshPhongMaterial( { flatShading: true } );
1411
+
1412
+ }
1413
+
1414
+ material.name = materialData.name;
1415
+
1416
+ // displaycolor MUST be specified with a value of a 6 or 8 digit hexadecimal number, e.g. "#RRGGBB" or "#RRGGBBAA"
1417
+
1418
+ const displaycolor = materialData.displaycolor;
1419
+
1420
+ const color = displaycolor.substring( 0, 7 );
1421
+ material.color.setStyle( color, COLOR_SPACE_3MF );
1422
+
1423
+ // process alpha if set
1424
+
1425
+ if ( displaycolor.length === 9 ) {
1426
+
1427
+ material.opacity = parseInt( displaycolor.charAt( 7 ) + displaycolor.charAt( 8 ), 16 ) / 255;
1428
+
1429
+ }
1430
+
1431
+ return material;
1432
+
1433
+ }
1434
+
1435
+ function buildComposite( compositeData, objects, modelData, textureData ) {
1436
+
1437
+ const composite = new Group();
1438
+
1439
+ for ( let j = 0; j < compositeData.length; j ++ ) {
1440
+
1441
+ const component = compositeData[ j ];
1442
+ let build = objects[ component.objectId ];
1443
+
1444
+ if ( build === undefined ) {
1445
+
1446
+ buildObject( component.objectId, objects, modelData, textureData );
1447
+ build = objects[ component.objectId ];
1448
+
1449
+ }
1450
+
1451
+ const object3D = build.clone();
1452
+
1453
+ // apply component transform
1454
+
1455
+ const transform = component.transform;
1456
+
1457
+ if ( transform ) {
1458
+
1459
+ object3D.applyMatrix4( transform );
1460
+
1461
+ }
1462
+
1463
+ composite.add( object3D );
1464
+
1465
+ }
1466
+
1467
+ return composite;
1468
+
1469
+ }
1470
+
1471
+ function buildObject( objectId, objects, modelData, textureData ) {
1472
+
1473
+ const objectData = modelData[ 'resources' ][ 'object' ][ objectId ];
1474
+
1475
+ if ( objectData[ 'mesh' ] ) {
1476
+
1477
+ const meshData = objectData[ 'mesh' ];
1478
+
1479
+ const extensions = modelData[ 'extensions' ];
1480
+ const modelXml = modelData[ 'xml' ];
1481
+
1482
+ applyExtensions( extensions, meshData, modelXml );
1483
+
1484
+ objects[ objectData.id ] = getBuild( meshData, objects, modelData, textureData, objectData, buildGroup );
1485
+
1486
+ } else {
1487
+
1488
+ const compositeData = objectData[ 'components' ];
1489
+
1490
+ objects[ objectData.id ] = getBuild( compositeData, objects, modelData, textureData, objectData, buildComposite );
1491
+
1492
+ }
1493
+
1494
+ if ( objectData.name ) {
1495
+
1496
+ objects[ objectData.id ].name = objectData.name;
1497
+
1498
+ }
1499
+
1500
+ if ( modelData.resources.implicitfunction ) {
1501
+
1502
+ console.warn( 'THREE.ThreeMFLoader: Implicit Functions are implemented in data-only.', modelData.resources.implicitfunction );
1503
+
1504
+ }
1505
+
1506
+ }
1507
+
1508
+ function buildObjects( data3mf ) {
1509
+
1510
+ const modelsData = data3mf.model;
1511
+ const modelRels = data3mf.modelRels;
1512
+ const objects = {};
1513
+ const modelsKeys = Object.keys( modelsData );
1514
+ const textureData = {};
1515
+
1516
+ // evaluate model relationships to textures
1517
+
1518
+ if ( modelRels ) {
1519
+
1520
+ for ( let i = 0, l = modelRels.length; i < l; i ++ ) {
1521
+
1522
+ const modelRel = modelRels[ i ];
1523
+ const textureKey = modelRel.target.substring( 1 );
1524
+
1525
+ if ( data3mf.texture[ textureKey ] ) {
1526
+
1527
+ textureData[ modelRel.target ] = data3mf.texture[ textureKey ];
1528
+
1529
+ }
1530
+
1531
+ }
1532
+
1533
+ }
1534
+
1535
+ // start build
1536
+
1537
+ for ( let i = 0; i < modelsKeys.length; i ++ ) {
1538
+
1539
+ const modelsKey = modelsKeys[ i ];
1540
+ const modelData = modelsData[ modelsKey ];
1541
+
1542
+ const objectIds = Object.keys( modelData[ 'resources' ][ 'object' ] );
1543
+
1544
+ for ( let j = 0; j < objectIds.length; j ++ ) {
1545
+
1546
+ const objectId = objectIds[ j ];
1547
+
1548
+ buildObject( objectId, objects, modelData, textureData );
1549
+
1550
+ }
1551
+
1552
+ }
1553
+
1554
+ return objects;
1555
+
1556
+ }
1557
+
1558
+ function fetch3DModelPart( rels ) {
1559
+
1560
+ for ( let i = 0; i < rels.length; i ++ ) {
1561
+
1562
+ const rel = rels[ i ];
1563
+ const extension = rel.target.split( '.' ).pop();
1564
+
1565
+ if ( extension.toLowerCase() === 'model' ) return rel;
1566
+
1567
+ }
1568
+
1569
+ }
1570
+
1571
+ function build( objects, data3mf ) {
1572
+
1573
+ const group = new Group();
1574
+
1575
+ const relationship = fetch3DModelPart( data3mf[ 'rels' ] );
1576
+ const buildData = data3mf.model[ relationship[ 'target' ].substring( 1 ) ][ 'build' ];
1577
+
1578
+ for ( let i = 0; i < buildData.length; i ++ ) {
1579
+
1580
+ const buildItem = buildData[ i ];
1581
+ const object3D = objects[ buildItem[ 'objectId' ] ].clone();
1582
+
1583
+ // apply transform
1584
+
1585
+ const transform = buildItem[ 'transform' ];
1586
+
1587
+ if ( transform ) {
1588
+
1589
+ object3D.applyMatrix4( transform );
1590
+
1591
+ }
1592
+
1593
+ group.add( object3D );
1594
+
1595
+ }
1596
+
1597
+ return group;
1598
+
1599
+ }
1600
+
1601
+ const data3mf = loadDocument( data );
1602
+ const objects = buildObjects( data3mf );
1603
+
1604
+ return build( objects, data3mf );
1605
+
1606
+ }
1607
+
1608
+ /**
1609
+ * Adds a 3MF extension.
1610
+ *
1611
+ * @param {Object} extension - The extension to add.
1612
+ */
1613
+ addExtension( extension ) {
1614
+
1615
+ this.availableExtensions.push( extension );
1616
+
1617
+ }
1618
+
1619
+ }
1620
+
1621
+ export { ThreeMFLoader };