redhotmagma-visualization 1.28.6 → 1.29.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 (88) hide show
  1. package/AlignTargetProvider.js +129 -0
  2. package/CommonUtils/Deferred.js +135 -0
  3. package/CommonUtils/Observable.js +126 -0
  4. package/CommonUtils/PropertyObserver.js +61 -0
  5. package/CommonUtils/SyncCurrentFunction.js +59 -0
  6. package/CommonUtils/SyncObservableEvent.js +19 -0
  7. package/CommonUtils/pointerEvent.js +415 -0
  8. package/Constants.js +23 -0
  9. package/DevApp.js +1049 -0
  10. package/ExposedModules.js +26 -0
  11. package/FallbackVisualization.js +26 -0
  12. package/PrintingEffects/ColorEmbossingEffect.js +58 -0
  13. package/PrintingEffects/DomingEffect.js +150 -0
  14. package/PrintingEffects/EmbossingEffect.js +65 -0
  15. package/PrintingEffects/EmbroideryEffect.js +541 -0
  16. package/PrintingEffects/EngravingEffect.js +65 -0
  17. package/PrintingEffects/PrintingEffects.js +117 -0
  18. package/PrintingEffects/PrintingEffectsUtils.js +53 -0
  19. package/PrintingEffects/resources/embroidery_multiply.jpg +0 -0
  20. package/PrintingEffects/resources/embroidery_screen.jpg +0 -0
  21. package/README.md +11 -4
  22. package/React/ReactBase.js +111 -0
  23. package/Three/Controls/OrbitControls.js +745 -0
  24. package/Three/Exporters/glTFExporter.js +48 -0
  25. package/Three/Loaders/ColladaLoader.js +2916 -0
  26. package/Three/Loaders/MTLLoader.js +449 -0
  27. package/Three/Loaders/OBJLoader.js +548 -0
  28. package/Three/Three2D.js +1790 -0
  29. package/Three/Three2DLayers.js +504 -0
  30. package/Three/Three3D.js +1412 -0
  31. package/Three/Three3DScene.js +1432 -0
  32. package/Three/ThreeBase.js +724 -0
  33. package/Utils/DesignArea/getDesignAreaCanvasSize.js +32 -0
  34. package/Utils/TextureBuilder/createTextureBuilder.js +334 -0
  35. package/Utils/TextureBuilder/textureBuilderFunctions.js +87 -0
  36. package/Utils/alignToElement.js +58 -0
  37. package/Utils/createAlphaMapFromAlphaChannel.js +50 -0
  38. package/Utils/createCache.js +46 -0
  39. package/Utils/createCanvas.js +29 -0
  40. package/Utils/createImageRepository.js +124 -0
  41. package/Utils/disposeMaterial.js +41 -0
  42. package/Utils/getImageSize.js +15 -0
  43. package/Utils/imagePreloader.js +76 -0
  44. package/Utils/initTextureCanvas.js +49 -0
  45. package/Utils/isMobileDevice.js +19 -0
  46. package/Utils/optimizeTextureImage.js +73 -0
  47. package/Utils/rememberCameraViewOffset.js +21 -0
  48. package/Utils/removeObject.js +22 -0
  49. package/Utils/restrictCameraMovement.js +45 -0
  50. package/Utils/setOrthographicCameraSize.js +16 -0
  51. package/Utils/updateFitSizeToElement.js +39 -0
  52. package/VisualizationContainer.js +279 -0
  53. package/VisualizationInterface.js +298 -0
  54. package/VisualizationProvider.js +38 -0
  55. package/__mocks__/exportedSample.svg +45 -0
  56. package/index.js +16 -0
  57. package/package.json +10 -70
  58. package/scripts/cpPublic.js +9 -12
  59. package/scripts/cpPublicLocal.js +30 -0
  60. package/src/CommonUtils/Observable.js +1 -0
  61. package/src/CommonUtils/pointerEvent.js +2 -1
  62. package/src/DevApp.js +2 -1
  63. package/src/FallbackVisualization.js +1 -5
  64. package/src/PrintingEffects/DomingEffect.js +1 -0
  65. package/src/PrintingEffects/EmbroideryEffect.js +3 -2
  66. package/src/React/ReactBase.js +1 -1
  67. package/src/Three/Controls/OrbitControls.js +2 -0
  68. package/src/Three/Loaders/ColladaLoader.js +111 -294
  69. package/src/Three/Loaders/MTLLoader.js +2 -0
  70. package/src/Three/Loaders/OBJLoader.js +2 -0
  71. package/src/Three/Three2D.js +18 -11
  72. package/src/Three/Three3D.js +9 -1
  73. package/src/Three/ThreeBase.js +14 -2
  74. package/src/Utils/DesignArea/getDesignAreaCanvasSize.js +1 -0
  75. package/src/Utils/TextureBuilder/createTextureBuilder.js +2 -0
  76. package/src/Utils/imagePreloader.js +1 -0
  77. package/src/Utils/initTextureCanvas.js +3 -0
  78. package/src/Utils/isMobileDevice.js +2 -0
  79. package/src/Utils/optimizeTextureImage.js +1 -0
  80. package/src/VisualizationContainer.js +3 -1
  81. package/src/VisualizationInterface.js +10 -1
  82. package/visualizationAdapterCreator.js +76 -0
  83. package/babel.config.js +0 -41
  84. package/scripts/cpPath.js +0 -151
  85. package/scripts/moveLibToPackageRoot.js +0 -44
  86. package/scripts/utils/fileSystem.js +0 -69
  87. package/scripts/utils/process.js +0 -19
  88. package/tsconfig.json +0 -22
@@ -0,0 +1,2916 @@
1
+ "use strict";
2
+
3
+ function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports["default"] = void 0;
9
+
10
+ var THREE_imp = _interopRequireWildcard(require("three"));
11
+
12
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
13
+
14
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
15
+
16
+ /* eslint-disable */
17
+ // original source: three/examples/js/loaders/ColladaLoader
18
+ var THREE = THREE_imp; // important: update file from here if needed
19
+
20
+ /**
21
+ * @author mrdoob / http://mrdoob.com/
22
+ * @author Mugen87 / https://github.com/Mugen87
23
+ */
24
+
25
+ THREE.ColladaLoader = function (manager) {
26
+ this.manager = manager !== undefined ? manager : THREE.DefaultLoadingManager;
27
+ };
28
+
29
+ THREE.ColladaLoader.prototype = {
30
+ constructor: THREE.ColladaLoader,
31
+ crossOrigin: "anonymous",
32
+ load: function load(url, onLoad, onProgress, onError) {
33
+ var scope = this;
34
+ var path = scope.path === undefined ? THREE.LoaderUtils.extractUrlBase(url) : scope.path;
35
+ var loader = new THREE.FileLoader(scope.manager);
36
+ loader.setPath(scope.path);
37
+ loader.load(url, function (text) {
38
+ onLoad(scope.parse(text, path));
39
+ }, onProgress, onError);
40
+ },
41
+ setPath: function setPath(value) {
42
+ this.path = value;
43
+ return this;
44
+ },
45
+ setResourcePath: function setResourcePath(value) {
46
+ this.resourcePath = value;
47
+ return this;
48
+ },
49
+ options: {
50
+ set convertUpAxis(value) {
51
+ console.warn("THREE.ColladaLoader: options.convertUpAxis() has been removed. Up axis is converted automatically.");
52
+ }
53
+
54
+ },
55
+ setCrossOrigin: function setCrossOrigin(value) {
56
+ this.crossOrigin = value;
57
+ return this;
58
+ },
59
+ parse: function parse(text, path) {
60
+ function getElementsByTagName(xml, name) {
61
+ // Non recursive xml.getElementsByTagName() ...
62
+ var array = [];
63
+ var childNodes = xml.childNodes;
64
+
65
+ for (var i = 0, l = childNodes.length; i < l; i++) {
66
+ var child = childNodes[i];
67
+
68
+ if (child.nodeName === name) {
69
+ array.push(child);
70
+ }
71
+ }
72
+
73
+ return array;
74
+ }
75
+
76
+ function parseStrings(text) {
77
+ if (text.length === 0) return [];
78
+ var parts = text.trim().split(/\s+/);
79
+ var array = new Array(parts.length);
80
+
81
+ for (var i = 0, l = parts.length; i < l; i++) {
82
+ array[i] = parts[i];
83
+ }
84
+
85
+ return array;
86
+ }
87
+
88
+ function parseFloats(text) {
89
+ if (text.length === 0) return [];
90
+ var parts = text.trim().split(/\s+/);
91
+ var array = new Array(parts.length);
92
+
93
+ for (var i = 0, l = parts.length; i < l; i++) {
94
+ array[i] = parseFloat(parts[i]);
95
+ }
96
+
97
+ return array;
98
+ }
99
+
100
+ function parseInts(text) {
101
+ if (text.length === 0) return [];
102
+ var parts = text.trim().split(/\s+/);
103
+ var array = new Array(parts.length);
104
+
105
+ for (var i = 0, l = parts.length; i < l; i++) {
106
+ array[i] = parseInt(parts[i]);
107
+ }
108
+
109
+ return array;
110
+ }
111
+
112
+ function parseId(text) {
113
+ return text.substring(1);
114
+ }
115
+
116
+ function generateId() {
117
+ return "three_default_" + count++;
118
+ }
119
+
120
+ function isEmpty(object) {
121
+ return Object.keys(object).length === 0;
122
+ } // asset
123
+
124
+
125
+ function parseAsset(xml) {
126
+ return {
127
+ unit: parseAssetUnit(getElementsByTagName(xml, "unit")[0]),
128
+ upAxis: parseAssetUpAxis(getElementsByTagName(xml, "up_axis")[0])
129
+ };
130
+ }
131
+
132
+ function parseAssetUnit(xml) {
133
+ if (xml !== undefined && xml.hasAttribute("meter") === true) {
134
+ return parseFloat(xml.getAttribute("meter"));
135
+ } else {
136
+ return 1; // default 1 meter
137
+ }
138
+ }
139
+
140
+ function parseAssetUpAxis(xml) {
141
+ return xml !== undefined ? xml.textContent : "Y_UP";
142
+ } // library
143
+
144
+
145
+ function parseLibrary(xml, libraryName, nodeName, parser) {
146
+ var library = getElementsByTagName(xml, libraryName)[0];
147
+
148
+ if (library !== undefined) {
149
+ var elements = getElementsByTagName(library, nodeName);
150
+
151
+ for (var i = 0; i < elements.length; i++) {
152
+ parser(elements[i]);
153
+ }
154
+ }
155
+ }
156
+
157
+ function buildLibrary(data, builder) {
158
+ for (var name in data) {
159
+ var object = data[name];
160
+ object.build = builder(data[name]);
161
+ }
162
+ } // get
163
+
164
+
165
+ function getBuild(data, builder) {
166
+ if (data.build !== undefined) return data.build;
167
+ data.build = builder(data);
168
+ return data.build;
169
+ } // animation
170
+
171
+
172
+ function parseAnimation(xml) {
173
+ var data = {
174
+ sources: {},
175
+ samplers: {},
176
+ channels: {}
177
+ };
178
+
179
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
180
+ var child = xml.childNodes[i];
181
+ if (child.nodeType !== 1) continue;
182
+ var id;
183
+
184
+ switch (child.nodeName) {
185
+ case "source":
186
+ id = child.getAttribute("id");
187
+ data.sources[id] = parseSource(child);
188
+ break;
189
+
190
+ case "sampler":
191
+ id = child.getAttribute("id");
192
+ data.samplers[id] = parseAnimationSampler(child);
193
+ break;
194
+
195
+ case "channel":
196
+ id = child.getAttribute("target");
197
+ data.channels[id] = parseAnimationChannel(child);
198
+ break;
199
+
200
+ default:
201
+ console.log(child);
202
+ }
203
+ }
204
+
205
+ library.animations[xml.getAttribute("id")] = data;
206
+ }
207
+
208
+ function parseAnimationSampler(xml) {
209
+ var data = {
210
+ inputs: {}
211
+ };
212
+
213
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
214
+ var child = xml.childNodes[i];
215
+ if (child.nodeType !== 1) continue;
216
+
217
+ switch (child.nodeName) {
218
+ case "input":
219
+ var id = parseId(child.getAttribute("source"));
220
+ var semantic = child.getAttribute("semantic");
221
+ data.inputs[semantic] = id;
222
+ break;
223
+ }
224
+ }
225
+
226
+ return data;
227
+ }
228
+
229
+ function parseAnimationChannel(xml) {
230
+ var data = {};
231
+ var target = xml.getAttribute("target"); // parsing SID Addressing Syntax
232
+
233
+ var parts = target.split("/");
234
+ var id = parts.shift();
235
+ var sid = parts.shift(); // check selection syntax
236
+
237
+ var arraySyntax = sid.indexOf("(") !== -1;
238
+ var memberSyntax = sid.indexOf(".") !== -1;
239
+
240
+ if (memberSyntax) {
241
+ // member selection access
242
+ parts = sid.split(".");
243
+ sid = parts.shift();
244
+ data.member = parts.shift();
245
+ } else if (arraySyntax) {
246
+ // array-access syntax. can be used to express fields in one-dimensional vectors or two-dimensional matrices.
247
+ var indices = sid.split("(");
248
+ sid = indices.shift();
249
+
250
+ for (var i = 0; i < indices.length; i++) {
251
+ indices[i] = parseInt(indices[i].replace(/\)/, ""));
252
+ }
253
+
254
+ data.indices = indices;
255
+ }
256
+
257
+ data.id = id;
258
+ data.sid = sid;
259
+ data.arraySyntax = arraySyntax;
260
+ data.memberSyntax = memberSyntax;
261
+ data.sampler = parseId(xml.getAttribute("source"));
262
+ return data;
263
+ }
264
+
265
+ function buildAnimation(data) {
266
+ var tracks = [];
267
+ var channels = data.channels;
268
+ var samplers = data.samplers;
269
+ var sources = data.sources;
270
+
271
+ for (var target in channels) {
272
+ if (channels.hasOwnProperty(target)) {
273
+ var channel = channels[target];
274
+ var sampler = samplers[channel.sampler];
275
+ var inputId = sampler.inputs.INPUT;
276
+ var outputId = sampler.inputs.OUTPUT;
277
+ var inputSource = sources[inputId];
278
+ var outputSource = sources[outputId];
279
+ var animation = buildAnimationChannel(channel, inputSource, outputSource);
280
+ createKeyframeTracks(animation, tracks);
281
+ }
282
+ }
283
+
284
+ return tracks;
285
+ }
286
+
287
+ function getAnimation(id) {
288
+ return getBuild(library.animations[id], buildAnimation);
289
+ }
290
+
291
+ function buildAnimationChannel(channel, inputSource, outputSource) {
292
+ var node = library.nodes[channel.id];
293
+ var object3D = getNode(node.id);
294
+ var transform = node.transforms[channel.sid];
295
+ var defaultMatrix = node.matrix.clone().transpose();
296
+ var time, stride;
297
+ var i, il, j, jl;
298
+ var data = {}; // the collada spec allows the animation of data in various ways.
299
+ // depending on the transform type (matrix, translate, rotate, scale), we execute different logic
300
+
301
+ switch (transform) {
302
+ case "matrix":
303
+ for (i = 0, il = inputSource.array.length; i < il; i++) {
304
+ time = inputSource.array[i];
305
+ stride = i * outputSource.stride;
306
+ if (data[time] === undefined) data[time] = {};
307
+
308
+ if (channel.arraySyntax === true) {
309
+ var value = outputSource.array[stride];
310
+ var index = channel.indices[0] + 4 * channel.indices[1];
311
+ data[time][index] = value;
312
+ } else {
313
+ for (j = 0, jl = outputSource.stride; j < jl; j++) {
314
+ data[time][j] = outputSource.array[stride + j];
315
+ }
316
+ }
317
+ }
318
+
319
+ break;
320
+
321
+ case "translate":
322
+ console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform);
323
+ break;
324
+
325
+ case "rotate":
326
+ console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform);
327
+ break;
328
+
329
+ case "scale":
330
+ console.warn('THREE.ColladaLoader: Animation transform type "%s" not yet implemented.', transform);
331
+ break;
332
+ }
333
+
334
+ var keyframes = prepareAnimationData(data, defaultMatrix);
335
+ var animation = {
336
+ name: object3D.uuid,
337
+ keyframes: keyframes
338
+ };
339
+ return animation;
340
+ }
341
+
342
+ function prepareAnimationData(data, defaultMatrix) {
343
+ var keyframes = []; // transfer data into a sortable array
344
+
345
+ for (var time in data) {
346
+ keyframes.push({
347
+ time: parseFloat(time),
348
+ value: data[time]
349
+ });
350
+ } // ensure keyframes are sorted by time
351
+
352
+
353
+ keyframes.sort(ascending); // now we clean up all animation data, so we can use them for keyframe tracks
354
+
355
+ for (var i = 0; i < 16; i++) {
356
+ transformAnimationData(keyframes, i, defaultMatrix.elements[i]);
357
+ }
358
+
359
+ return keyframes; // array sort function
360
+
361
+ function ascending(a, b) {
362
+ return a.time - b.time;
363
+ }
364
+ }
365
+
366
+ var position = new THREE.Vector3();
367
+ var scale = new THREE.Vector3();
368
+ var quaternion = new THREE.Quaternion();
369
+
370
+ function createKeyframeTracks(animation, tracks) {
371
+ var keyframes = animation.keyframes;
372
+ var name = animation.name;
373
+ var times = [];
374
+ var positionData = [];
375
+ var quaternionData = [];
376
+ var scaleData = [];
377
+
378
+ for (var i = 0, l = keyframes.length; i < l; i++) {
379
+ var keyframe = keyframes[i];
380
+ var time = keyframe.time;
381
+ var value = keyframe.value;
382
+ matrix.fromArray(value).transpose();
383
+ matrix.decompose(position, quaternion, scale);
384
+ times.push(time);
385
+ positionData.push(position.x, position.y, position.z);
386
+ quaternionData.push(quaternion.x, quaternion.y, quaternion.z, quaternion.w);
387
+ scaleData.push(scale.x, scale.y, scale.z);
388
+ }
389
+
390
+ if (positionData.length > 0) tracks.push(new THREE.VectorKeyframeTrack(name + ".position", times, positionData));
391
+ if (quaternionData.length > 0) tracks.push(new THREE.QuaternionKeyframeTrack(name + ".quaternion", times, quaternionData));
392
+ if (scaleData.length > 0) tracks.push(new THREE.VectorKeyframeTrack(name + ".scale", times, scaleData));
393
+ return tracks;
394
+ }
395
+
396
+ function transformAnimationData(keyframes, property, defaultValue) {
397
+ var keyframe;
398
+ var empty = true;
399
+ var i, l; // check, if values of a property are missing in our keyframes
400
+
401
+ for (i = 0, l = keyframes.length; i < l; i++) {
402
+ keyframe = keyframes[i];
403
+
404
+ if (keyframe.value[property] === undefined) {
405
+ keyframe.value[property] = null; // mark as missing
406
+ } else {
407
+ empty = false;
408
+ }
409
+ }
410
+
411
+ if (empty === true) {
412
+ // no values at all, so we set a default value
413
+ for (i = 0, l = keyframes.length; i < l; i++) {
414
+ keyframe = keyframes[i];
415
+ keyframe.value[property] = defaultValue;
416
+ }
417
+ } else {
418
+ // filling gaps
419
+ createMissingKeyframes(keyframes, property);
420
+ }
421
+ }
422
+
423
+ function createMissingKeyframes(keyframes, property) {
424
+ var prev, next;
425
+
426
+ for (var i = 0, l = keyframes.length; i < l; i++) {
427
+ var keyframe = keyframes[i];
428
+
429
+ if (keyframe.value[property] === null) {
430
+ prev = getPrev(keyframes, i, property);
431
+ next = getNext(keyframes, i, property);
432
+
433
+ if (prev === null) {
434
+ keyframe.value[property] = next.value[property];
435
+ continue;
436
+ }
437
+
438
+ if (next === null) {
439
+ keyframe.value[property] = prev.value[property];
440
+ continue;
441
+ }
442
+
443
+ interpolate(keyframe, prev, next, property);
444
+ }
445
+ }
446
+ }
447
+
448
+ function getPrev(keyframes, i, property) {
449
+ while (i >= 0) {
450
+ var keyframe = keyframes[i];
451
+ if (keyframe.value[property] !== null) return keyframe;
452
+ i--;
453
+ }
454
+
455
+ return null;
456
+ }
457
+
458
+ function getNext(keyframes, i, property) {
459
+ while (i < keyframes.length) {
460
+ var keyframe = keyframes[i];
461
+ if (keyframe.value[property] !== null) return keyframe;
462
+ i++;
463
+ }
464
+
465
+ return null;
466
+ }
467
+
468
+ function interpolate(key, prev, next, property) {
469
+ if (next.time - prev.time === 0) {
470
+ key.value[property] = prev.value[property];
471
+ return;
472
+ }
473
+
474
+ key.value[property] = (key.time - prev.time) * (next.value[property] - prev.value[property]) / (next.time - prev.time) + prev.value[property];
475
+ } // animation clips
476
+
477
+
478
+ function parseAnimationClip(xml) {
479
+ var data = {
480
+ name: xml.getAttribute("id") || "default",
481
+ start: parseFloat(xml.getAttribute("start") || 0),
482
+ end: parseFloat(xml.getAttribute("end") || 0),
483
+ animations: []
484
+ };
485
+
486
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
487
+ var child = xml.childNodes[i];
488
+ if (child.nodeType !== 1) continue;
489
+
490
+ switch (child.nodeName) {
491
+ case "instance_animation":
492
+ data.animations.push(parseId(child.getAttribute("url")));
493
+ break;
494
+ }
495
+ }
496
+
497
+ library.clips[xml.getAttribute("id")] = data;
498
+ }
499
+
500
+ function buildAnimationClip(data) {
501
+ var tracks = [];
502
+ var name = data.name;
503
+ var duration = data.end - data.start || -1;
504
+ var animations = data.animations;
505
+
506
+ for (var i = 0, il = animations.length; i < il; i++) {
507
+ var animationTracks = getAnimation(animations[i]);
508
+
509
+ for (var j = 0, jl = animationTracks.length; j < jl; j++) {
510
+ tracks.push(animationTracks[j]);
511
+ }
512
+ }
513
+
514
+ return new THREE.AnimationClip(name, duration, tracks);
515
+ }
516
+
517
+ function getAnimationClip(id) {
518
+ return getBuild(library.clips[id], buildAnimationClip);
519
+ } // controller
520
+
521
+
522
+ function parseController(xml) {
523
+ var data = {};
524
+
525
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
526
+ var child = xml.childNodes[i];
527
+ if (child.nodeType !== 1) continue;
528
+
529
+ switch (child.nodeName) {
530
+ case "skin":
531
+ // there is exactly one skin per controller
532
+ data.id = parseId(child.getAttribute("source"));
533
+ data.skin = parseSkin(child);
534
+ break;
535
+
536
+ case "morph":
537
+ data.id = parseId(child.getAttribute("source"));
538
+ console.warn("THREE.ColladaLoader: Morph target animation not supported yet.");
539
+ break;
540
+ }
541
+ }
542
+
543
+ library.controllers[xml.getAttribute("id")] = data;
544
+ }
545
+
546
+ function parseSkin(xml) {
547
+ var data = {
548
+ sources: {}
549
+ };
550
+
551
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
552
+ var child = xml.childNodes[i];
553
+ if (child.nodeType !== 1) continue;
554
+
555
+ switch (child.nodeName) {
556
+ case "bind_shape_matrix":
557
+ data.bindShapeMatrix = parseFloats(child.textContent);
558
+ break;
559
+
560
+ case "source":
561
+ var id = child.getAttribute("id");
562
+ data.sources[id] = parseSource(child);
563
+ break;
564
+
565
+ case "joints":
566
+ data.joints = parseJoints(child);
567
+ break;
568
+
569
+ case "vertex_weights":
570
+ data.vertexWeights = parseVertexWeights(child);
571
+ break;
572
+ }
573
+ }
574
+
575
+ return data;
576
+ }
577
+
578
+ function parseJoints(xml) {
579
+ var data = {
580
+ inputs: {}
581
+ };
582
+
583
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
584
+ var child = xml.childNodes[i];
585
+ if (child.nodeType !== 1) continue;
586
+
587
+ switch (child.nodeName) {
588
+ case "input":
589
+ var semantic = child.getAttribute("semantic");
590
+ var id = parseId(child.getAttribute("source"));
591
+ data.inputs[semantic] = id;
592
+ break;
593
+ }
594
+ }
595
+
596
+ return data;
597
+ }
598
+
599
+ function parseVertexWeights(xml) {
600
+ var data = {
601
+ inputs: {}
602
+ };
603
+
604
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
605
+ var child = xml.childNodes[i];
606
+ if (child.nodeType !== 1) continue;
607
+
608
+ switch (child.nodeName) {
609
+ case "input":
610
+ var semantic = child.getAttribute("semantic");
611
+ var id = parseId(child.getAttribute("source"));
612
+ var offset = parseInt(child.getAttribute("offset"));
613
+ data.inputs[semantic] = {
614
+ id: id,
615
+ offset: offset
616
+ };
617
+ break;
618
+
619
+ case "vcount":
620
+ data.vcount = parseInts(child.textContent);
621
+ break;
622
+
623
+ case "v":
624
+ data.v = parseInts(child.textContent);
625
+ break;
626
+ }
627
+ }
628
+
629
+ return data;
630
+ }
631
+
632
+ function buildController(data) {
633
+ var build = {
634
+ id: data.id
635
+ };
636
+ var geometry = library.geometries[build.id];
637
+
638
+ if (data.skin !== undefined) {
639
+ build.skin = buildSkin(data.skin); // we enhance the 'sources' property of the corresponding geometry with our skin data
640
+
641
+ geometry.sources.skinIndices = build.skin.indices;
642
+ geometry.sources.skinWeights = build.skin.weights;
643
+ }
644
+
645
+ return build;
646
+ }
647
+
648
+ function buildSkin(data) {
649
+ var BONE_LIMIT = 4;
650
+ var build = {
651
+ joints: [],
652
+ // this must be an array to preserve the joint order
653
+ indices: {
654
+ array: [],
655
+ stride: BONE_LIMIT
656
+ },
657
+ weights: {
658
+ array: [],
659
+ stride: BONE_LIMIT
660
+ }
661
+ };
662
+ var sources = data.sources;
663
+ var vertexWeights = data.vertexWeights;
664
+ var vcount = vertexWeights.vcount;
665
+ var v = vertexWeights.v;
666
+ var jointOffset = vertexWeights.inputs.JOINT.offset;
667
+ var weightOffset = vertexWeights.inputs.WEIGHT.offset;
668
+ var jointSource = data.sources[data.joints.inputs.JOINT];
669
+ var inverseSource = data.sources[data.joints.inputs.INV_BIND_MATRIX];
670
+ var weights = sources[vertexWeights.inputs.WEIGHT.id].array;
671
+ var stride = 0;
672
+ var i, j, l; // procces skin data for each vertex
673
+
674
+ for (i = 0, l = vcount.length; i < l; i++) {
675
+ var jointCount = vcount[i]; // this is the amount of joints that affect a single vertex
676
+
677
+ var vertexSkinData = [];
678
+
679
+ for (j = 0; j < jointCount; j++) {
680
+ var skinIndex = v[stride + jointOffset];
681
+ var weightId = v[stride + weightOffset];
682
+ var skinWeight = weights[weightId];
683
+ vertexSkinData.push({
684
+ index: skinIndex,
685
+ weight: skinWeight
686
+ });
687
+ stride += 2;
688
+ } // we sort the joints in descending order based on the weights.
689
+ // this ensures, we only procced the most important joints of the vertex
690
+
691
+
692
+ vertexSkinData.sort(descending); // now we provide for each vertex a set of four index and weight values.
693
+ // the order of the skin data matches the order of vertices
694
+
695
+ for (j = 0; j < BONE_LIMIT; j++) {
696
+ var d = vertexSkinData[j];
697
+
698
+ if (d !== undefined) {
699
+ build.indices.array.push(d.index);
700
+ build.weights.array.push(d.weight);
701
+ } else {
702
+ build.indices.array.push(0);
703
+ build.weights.array.push(0);
704
+ }
705
+ }
706
+ } // setup bind matrix
707
+
708
+
709
+ if (data.bindShapeMatrix) {
710
+ build.bindMatrix = new THREE.Matrix4().fromArray(data.bindShapeMatrix).transpose();
711
+ } else {
712
+ build.bindMatrix = new THREE.Matrix4().identity();
713
+ } // process bones and inverse bind matrix data
714
+
715
+
716
+ for (i = 0, l = jointSource.array.length; i < l; i++) {
717
+ var name = jointSource.array[i];
718
+ var boneInverse = new THREE.Matrix4().fromArray(inverseSource.array, i * inverseSource.stride).transpose();
719
+ build.joints.push({
720
+ name: name,
721
+ boneInverse: boneInverse
722
+ });
723
+ }
724
+
725
+ return build; // array sort function
726
+
727
+ function descending(a, b) {
728
+ return b.weight - a.weight;
729
+ }
730
+ }
731
+
732
+ function getController(id) {
733
+ return getBuild(library.controllers[id], buildController);
734
+ } // image
735
+
736
+
737
+ function parseImage(xml) {
738
+ var data = {
739
+ init_from: getElementsByTagName(xml, "init_from")[0].textContent
740
+ };
741
+ library.images[xml.getAttribute("id")] = data;
742
+ }
743
+
744
+ function buildImage(data) {
745
+ if (data.build !== undefined) return data.build;
746
+ return data.init_from;
747
+ }
748
+
749
+ function getImage(id) {
750
+ var data = library.images[id];
751
+
752
+ if (data !== undefined) {
753
+ return getBuild(data, buildImage);
754
+ }
755
+
756
+ console.warn("THREE.ColladaLoader: Couldn't find image with ID:", id);
757
+ return null;
758
+ } // effect
759
+
760
+
761
+ function parseEffect(xml) {
762
+ var data = {};
763
+
764
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
765
+ var child = xml.childNodes[i];
766
+ if (child.nodeType !== 1) continue;
767
+
768
+ switch (child.nodeName) {
769
+ case "profile_COMMON":
770
+ data.profile = parseEffectProfileCOMMON(child);
771
+ break;
772
+ }
773
+ }
774
+
775
+ library.effects[xml.getAttribute("id")] = data;
776
+ }
777
+
778
+ function parseEffectProfileCOMMON(xml) {
779
+ var data = {
780
+ surfaces: {},
781
+ samplers: {}
782
+ };
783
+
784
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
785
+ var child = xml.childNodes[i];
786
+ if (child.nodeType !== 1) continue;
787
+
788
+ switch (child.nodeName) {
789
+ case "newparam":
790
+ parseEffectNewparam(child, data);
791
+ break;
792
+
793
+ case "technique":
794
+ data.technique = parseEffectTechnique(child);
795
+ break;
796
+
797
+ case "extra":
798
+ data.extra = parseEffectExtra(child);
799
+ break;
800
+ }
801
+ }
802
+
803
+ return data;
804
+ }
805
+
806
+ function parseEffectNewparam(xml, data) {
807
+ var sid = xml.getAttribute("sid");
808
+
809
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
810
+ var child = xml.childNodes[i];
811
+ if (child.nodeType !== 1) continue;
812
+
813
+ switch (child.nodeName) {
814
+ case "surface":
815
+ data.surfaces[sid] = parseEffectSurface(child);
816
+ break;
817
+
818
+ case "sampler2D":
819
+ data.samplers[sid] = parseEffectSampler(child);
820
+ break;
821
+ }
822
+ }
823
+ }
824
+
825
+ function parseEffectSurface(xml) {
826
+ var data = {};
827
+
828
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
829
+ var child = xml.childNodes[i];
830
+ if (child.nodeType !== 1) continue;
831
+
832
+ switch (child.nodeName) {
833
+ case "init_from":
834
+ data.init_from = child.textContent;
835
+ break;
836
+ }
837
+ }
838
+
839
+ return data;
840
+ }
841
+
842
+ function parseEffectSampler(xml) {
843
+ var data = {};
844
+
845
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
846
+ var child = xml.childNodes[i];
847
+ if (child.nodeType !== 1) continue;
848
+
849
+ switch (child.nodeName) {
850
+ case "source":
851
+ data.source = child.textContent;
852
+ break;
853
+ }
854
+ }
855
+
856
+ return data;
857
+ }
858
+
859
+ function parseEffectTechnique(xml) {
860
+ var data = {};
861
+
862
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
863
+ var child = xml.childNodes[i];
864
+ if (child.nodeType !== 1) continue;
865
+
866
+ switch (child.nodeName) {
867
+ case "constant":
868
+ case "lambert":
869
+ case "blinn":
870
+ case "phong":
871
+ data.type = child.nodeName;
872
+ data.parameters = parseEffectParameters(child);
873
+ break;
874
+ }
875
+ }
876
+
877
+ return data;
878
+ }
879
+
880
+ function parseEffectParameters(xml) {
881
+ var data = {};
882
+
883
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
884
+ var child = xml.childNodes[i];
885
+ if (child.nodeType !== 1) continue;
886
+
887
+ switch (child.nodeName) {
888
+ case "emission":
889
+ case "diffuse":
890
+ case "specular":
891
+ case "bump":
892
+ case "ambient":
893
+ case "shininess":
894
+ case "transparency":
895
+ data[child.nodeName] = parseEffectParameter(child);
896
+ break;
897
+
898
+ case "transparent":
899
+ data[child.nodeName] = {
900
+ opaque: child.getAttribute("opaque"),
901
+ data: parseEffectParameter(child)
902
+ };
903
+ break;
904
+ }
905
+ }
906
+
907
+ return data;
908
+ }
909
+
910
+ function parseEffectParameter(xml) {
911
+ var data = {};
912
+
913
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
914
+ var child = xml.childNodes[i];
915
+ if (child.nodeType !== 1) continue;
916
+
917
+ switch (child.nodeName) {
918
+ case "color":
919
+ data[child.nodeName] = parseFloats(child.textContent);
920
+ break;
921
+
922
+ case "float":
923
+ data[child.nodeName] = parseFloat(child.textContent);
924
+ break;
925
+
926
+ case "texture":
927
+ data[child.nodeName] = {
928
+ id: child.getAttribute("texture"),
929
+ extra: parseEffectParameterTexture(child)
930
+ };
931
+ break;
932
+ }
933
+ }
934
+
935
+ return data;
936
+ }
937
+
938
+ function parseEffectParameterTexture(xml) {
939
+ var data = {
940
+ technique: {}
941
+ };
942
+
943
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
944
+ var child = xml.childNodes[i];
945
+ if (child.nodeType !== 1) continue;
946
+
947
+ switch (child.nodeName) {
948
+ case "extra":
949
+ parseEffectParameterTextureExtra(child, data);
950
+ break;
951
+ }
952
+ }
953
+
954
+ return data;
955
+ }
956
+
957
+ function parseEffectParameterTextureExtra(xml, data) {
958
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
959
+ var child = xml.childNodes[i];
960
+ if (child.nodeType !== 1) continue;
961
+
962
+ switch (child.nodeName) {
963
+ case "technique":
964
+ parseEffectParameterTextureExtraTechnique(child, data);
965
+ break;
966
+ }
967
+ }
968
+ }
969
+
970
+ function parseEffectParameterTextureExtraTechnique(xml, data) {
971
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
972
+ var child = xml.childNodes[i];
973
+ if (child.nodeType !== 1) continue;
974
+
975
+ switch (child.nodeName) {
976
+ case "repeatU":
977
+ case "repeatV":
978
+ case "offsetU":
979
+ case "offsetV":
980
+ data.technique[child.nodeName] = parseFloat(child.textContent);
981
+ break;
982
+
983
+ case "wrapU":
984
+ case "wrapV":
985
+ // some files have values for wrapU/wrapV which become NaN via parseInt
986
+ if (child.textContent.toUpperCase() === "TRUE") {
987
+ data.technique[child.nodeName] = 1;
988
+ } else if (child.textContent.toUpperCase() === "FALSE") {
989
+ data.technique[child.nodeName] = 0;
990
+ } else {
991
+ data.technique[child.nodeName] = parseInt(child.textContent);
992
+ }
993
+
994
+ break;
995
+ }
996
+ }
997
+ }
998
+
999
+ function parseEffectExtra(xml) {
1000
+ var data = {};
1001
+
1002
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
1003
+ var child = xml.childNodes[i];
1004
+ if (child.nodeType !== 1) continue;
1005
+
1006
+ switch (child.nodeName) {
1007
+ case "technique":
1008
+ data.technique = parseEffectExtraTechnique(child);
1009
+ break;
1010
+ }
1011
+ }
1012
+
1013
+ return data;
1014
+ }
1015
+
1016
+ function parseEffectExtraTechnique(xml) {
1017
+ var data = {};
1018
+
1019
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
1020
+ var child = xml.childNodes[i];
1021
+ if (child.nodeType !== 1) continue;
1022
+
1023
+ switch (child.nodeName) {
1024
+ case "double_sided":
1025
+ data[child.nodeName] = parseInt(child.textContent);
1026
+ break;
1027
+ }
1028
+ }
1029
+
1030
+ return data;
1031
+ }
1032
+
1033
+ function buildEffect(data) {
1034
+ return data;
1035
+ }
1036
+
1037
+ function getEffect(id) {
1038
+ return getBuild(library.effects[id], buildEffect);
1039
+ } // material
1040
+
1041
+
1042
+ function parseMaterial(xml) {
1043
+ var data = {
1044
+ name: xml.getAttribute("name")
1045
+ };
1046
+
1047
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
1048
+ var child = xml.childNodes[i];
1049
+ if (child.nodeType !== 1) continue;
1050
+
1051
+ switch (child.nodeName) {
1052
+ case "instance_effect":
1053
+ data.url = parseId(child.getAttribute("url"));
1054
+ break;
1055
+ }
1056
+ }
1057
+
1058
+ library.materials[xml.getAttribute("id")] = data;
1059
+ }
1060
+
1061
+ function getTextureLoader(image) {
1062
+ var loader;
1063
+ var extension = image.slice((image.lastIndexOf(".") - 1 >>> 0) + 2); // http://www.jstips.co/en/javascript/get-file-extension/
1064
+
1065
+ extension = extension.toLowerCase();
1066
+
1067
+ switch (extension) {
1068
+ case "tga":
1069
+ loader = tgaLoader;
1070
+ break;
1071
+
1072
+ default:
1073
+ loader = textureLoader;
1074
+ }
1075
+
1076
+ return loader;
1077
+ }
1078
+
1079
+ function buildMaterial(data) {
1080
+ var effect = getEffect(data.url);
1081
+ var technique = effect.profile.technique;
1082
+ var extra = effect.profile.extra;
1083
+ var material;
1084
+
1085
+ switch (technique.type) {
1086
+ case "phong":
1087
+ case "blinn":
1088
+ material = new THREE.MeshPhongMaterial();
1089
+ break;
1090
+
1091
+ case "lambert":
1092
+ material = new THREE.MeshLambertMaterial();
1093
+ break;
1094
+
1095
+ default:
1096
+ material = new THREE.MeshBasicMaterial();
1097
+ break;
1098
+ }
1099
+
1100
+ material.name = data.name;
1101
+
1102
+ function getTexture(textureObject) {
1103
+ var sampler = effect.profile.samplers[textureObject.id];
1104
+ var image = null; // get image
1105
+
1106
+ if (sampler !== undefined) {
1107
+ var surface = effect.profile.surfaces[sampler.source];
1108
+ image = getImage(surface.init_from);
1109
+ } else {
1110
+ console.warn("THREE.ColladaLoader: Undefined sampler. Access image directly (see #12530).");
1111
+ image = getImage(textureObject.id);
1112
+ } // create texture if image is avaiable
1113
+
1114
+
1115
+ if (image !== null) {
1116
+ var loader = getTextureLoader(image);
1117
+
1118
+ if (loader !== undefined) {
1119
+ var texture = loader.load(image);
1120
+ var extra = textureObject.extra;
1121
+
1122
+ if (extra !== undefined && extra.technique !== undefined && isEmpty(extra.technique) === false) {
1123
+ var technique = extra.technique;
1124
+ texture.wrapS = technique.wrapU ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
1125
+ texture.wrapT = technique.wrapV ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
1126
+ texture.offset.set(technique.offsetU || 0, technique.offsetV || 0);
1127
+ texture.repeat.set(technique.repeatU || 1, technique.repeatV || 1);
1128
+ } else {
1129
+ texture.wrapS = THREE.RepeatWrapping;
1130
+ texture.wrapT = THREE.RepeatWrapping;
1131
+ }
1132
+
1133
+ return texture;
1134
+ } else {
1135
+ console.warn("THREE.ColladaLoader: Loader for texture %s not found.", image);
1136
+ return null;
1137
+ }
1138
+ } else {
1139
+ console.warn("THREE.ColladaLoader: Couldn't create texture with ID:", textureObject.id);
1140
+ return null;
1141
+ }
1142
+ }
1143
+
1144
+ var parameters = technique.parameters;
1145
+
1146
+ for (var key in parameters) {
1147
+ var parameter = parameters[key];
1148
+
1149
+ switch (key) {
1150
+ case "diffuse":
1151
+ if (parameter.color) material.color.fromArray(parameter.color);
1152
+ if (parameter.texture) material.map = getTexture(parameter.texture);
1153
+ break;
1154
+
1155
+ case "specular":
1156
+ if (parameter.color && material.specular) material.specular.fromArray(parameter.color);
1157
+ if (parameter.texture) material.specularMap = getTexture(parameter.texture);
1158
+ break;
1159
+
1160
+ case "bump":
1161
+ if (parameter.texture) material.normalMap = getTexture(parameter.texture);
1162
+ break;
1163
+
1164
+ case "ambient":
1165
+ if (parameter.texture) material.lightMap = getTexture(parameter.texture);
1166
+ break;
1167
+
1168
+ case "shininess":
1169
+ if (parameter["float"] && material.shininess) material.shininess = parameter["float"];
1170
+ break;
1171
+
1172
+ case "emission":
1173
+ if (parameter.color && material.emissive) material.emissive.fromArray(parameter.color);
1174
+ if (parameter.texture) material.emissiveMap = getTexture(parameter.texture);
1175
+ break;
1176
+ }
1177
+ } //
1178
+
1179
+
1180
+ var transparent = parameters["transparent"];
1181
+ var transparency = parameters["transparency"]; // <transparency> does not exist but <transparent>
1182
+
1183
+ if (transparency === undefined && transparent) {
1184
+ transparency = {
1185
+ "float": 1
1186
+ };
1187
+ } // <transparent> does not exist but <transparency>
1188
+
1189
+
1190
+ if (transparent === undefined && transparency) {
1191
+ transparent = {
1192
+ opaque: "A_ONE",
1193
+ data: {
1194
+ color: [1, 1, 1, 1]
1195
+ }
1196
+ };
1197
+ }
1198
+
1199
+ if (transparent && transparency) {
1200
+ // handle case if a texture exists but no color
1201
+ if (transparent.data.texture) {
1202
+ // we do not set an alpha map (see #13792)
1203
+ material.transparent = true;
1204
+ } else {
1205
+ var color = transparent.data.color;
1206
+
1207
+ switch (transparent.opaque) {
1208
+ case "A_ONE":
1209
+ material.opacity = color[3] * transparency["float"];
1210
+ break;
1211
+
1212
+ case "RGB_ZERO":
1213
+ material.opacity = 1 - color[0] * transparency["float"];
1214
+ break;
1215
+
1216
+ case "A_ZERO":
1217
+ material.opacity = 1 - color[3] * transparency["float"];
1218
+ break;
1219
+
1220
+ case "RGB_ONE":
1221
+ material.opacity = color[0] * transparency["float"];
1222
+ break;
1223
+
1224
+ default:
1225
+ console.warn('THREE.ColladaLoader: Invalid opaque type "%s" of transparent tag.', transparent.opaque);
1226
+ }
1227
+
1228
+ if (material.opacity < 1) material.transparent = true;
1229
+ }
1230
+ } //
1231
+
1232
+
1233
+ if (extra !== undefined && extra.technique !== undefined && extra.technique.double_sided === 1) {
1234
+ material.side = THREE.DoubleSide;
1235
+ }
1236
+
1237
+ return material;
1238
+ }
1239
+
1240
+ function getMaterial(id) {
1241
+ return getBuild(library.materials[id], buildMaterial);
1242
+ } // camera
1243
+
1244
+
1245
+ function parseCamera(xml) {
1246
+ var data = {
1247
+ name: xml.getAttribute("name")
1248
+ };
1249
+
1250
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
1251
+ var child = xml.childNodes[i];
1252
+ if (child.nodeType !== 1) continue;
1253
+
1254
+ switch (child.nodeName) {
1255
+ case "optics":
1256
+ data.optics = parseCameraOptics(child);
1257
+ break;
1258
+ }
1259
+ }
1260
+
1261
+ library.cameras[xml.getAttribute("id")] = data;
1262
+ }
1263
+
1264
+ function parseCameraOptics(xml) {
1265
+ for (var i = 0; i < xml.childNodes.length; i++) {
1266
+ var child = xml.childNodes[i];
1267
+
1268
+ switch (child.nodeName) {
1269
+ case "technique_common":
1270
+ return parseCameraTechnique(child);
1271
+ }
1272
+ }
1273
+
1274
+ return {};
1275
+ }
1276
+
1277
+ function parseCameraTechnique(xml) {
1278
+ var data = {};
1279
+
1280
+ for (var i = 0; i < xml.childNodes.length; i++) {
1281
+ var child = xml.childNodes[i];
1282
+
1283
+ switch (child.nodeName) {
1284
+ case "perspective":
1285
+ case "orthographic":
1286
+ data.technique = child.nodeName;
1287
+ data.parameters = parseCameraParameters(child);
1288
+ break;
1289
+ }
1290
+ }
1291
+
1292
+ return data;
1293
+ }
1294
+
1295
+ function parseCameraParameters(xml) {
1296
+ var data = {};
1297
+
1298
+ for (var i = 0; i < xml.childNodes.length; i++) {
1299
+ var child = xml.childNodes[i];
1300
+
1301
+ switch (child.nodeName) {
1302
+ case "xfov":
1303
+ case "yfov":
1304
+ case "xmag":
1305
+ case "ymag":
1306
+ case "znear":
1307
+ case "zfar":
1308
+ case "aspect_ratio":
1309
+ data[child.nodeName] = parseFloat(child.textContent);
1310
+ break;
1311
+ }
1312
+ }
1313
+
1314
+ return data;
1315
+ }
1316
+
1317
+ function buildCamera(data) {
1318
+ var camera;
1319
+
1320
+ switch (data.optics.technique) {
1321
+ case "perspective":
1322
+ camera = new THREE.PerspectiveCamera(data.optics.parameters.yfov, data.optics.parameters.aspect_ratio, data.optics.parameters.znear, data.optics.parameters.zfar);
1323
+ break;
1324
+
1325
+ case "orthographic":
1326
+ var ymag = data.optics.parameters.ymag;
1327
+ var xmag = data.optics.parameters.xmag;
1328
+ var aspectRatio = data.optics.parameters.aspect_ratio;
1329
+ xmag = xmag === undefined ? ymag * aspectRatio : xmag;
1330
+ ymag = ymag === undefined ? xmag / aspectRatio : ymag;
1331
+ xmag *= 0.5;
1332
+ ymag *= 0.5;
1333
+ camera = new THREE.OrthographicCamera(-xmag, xmag, ymag, -ymag, // left, right, top, bottom
1334
+ data.optics.parameters.znear, data.optics.parameters.zfar);
1335
+ break;
1336
+
1337
+ default:
1338
+ camera = new THREE.PerspectiveCamera();
1339
+ break;
1340
+ }
1341
+
1342
+ camera.name = data.name;
1343
+ return camera;
1344
+ }
1345
+
1346
+ function getCamera(id) {
1347
+ var data = library.cameras[id];
1348
+
1349
+ if (data !== undefined) {
1350
+ return getBuild(data, buildCamera);
1351
+ }
1352
+
1353
+ console.warn("THREE.ColladaLoader: Couldn't find camera with ID:", id);
1354
+ return null;
1355
+ } // light
1356
+
1357
+
1358
+ function parseLight(xml) {
1359
+ var data = {};
1360
+
1361
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
1362
+ var child = xml.childNodes[i];
1363
+ if (child.nodeType !== 1) continue;
1364
+
1365
+ switch (child.nodeName) {
1366
+ case "technique_common":
1367
+ data = parseLightTechnique(child);
1368
+ break;
1369
+ }
1370
+ }
1371
+
1372
+ library.lights[xml.getAttribute("id")] = data;
1373
+ }
1374
+
1375
+ function parseLightTechnique(xml) {
1376
+ var data = {};
1377
+
1378
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
1379
+ var child = xml.childNodes[i];
1380
+ if (child.nodeType !== 1) continue;
1381
+
1382
+ switch (child.nodeName) {
1383
+ case "directional":
1384
+ case "point":
1385
+ case "spot":
1386
+ case "ambient":
1387
+ data.technique = child.nodeName;
1388
+ data.parameters = parseLightParameters(child);
1389
+ }
1390
+ }
1391
+
1392
+ return data;
1393
+ }
1394
+
1395
+ function parseLightParameters(xml) {
1396
+ var data = {};
1397
+
1398
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
1399
+ var child = xml.childNodes[i];
1400
+ if (child.nodeType !== 1) continue;
1401
+
1402
+ switch (child.nodeName) {
1403
+ case "color":
1404
+ var array = parseFloats(child.textContent);
1405
+ data.color = new THREE.Color().fromArray(array);
1406
+ break;
1407
+
1408
+ case "falloff_angle":
1409
+ data.falloffAngle = parseFloat(child.textContent);
1410
+ break;
1411
+
1412
+ case "quadratic_attenuation":
1413
+ var f = parseFloat(child.textContent);
1414
+ data.distance = f ? Math.sqrt(1 / f) : 0;
1415
+ break;
1416
+ }
1417
+ }
1418
+
1419
+ return data;
1420
+ }
1421
+
1422
+ function buildLight(data) {
1423
+ var light;
1424
+
1425
+ switch (data.technique) {
1426
+ case "directional":
1427
+ light = new THREE.DirectionalLight();
1428
+ break;
1429
+
1430
+ case "point":
1431
+ light = new THREE.PointLight();
1432
+ break;
1433
+
1434
+ case "spot":
1435
+ light = new THREE.SpotLight();
1436
+ break;
1437
+
1438
+ case "ambient":
1439
+ light = new THREE.AmbientLight();
1440
+ break;
1441
+ }
1442
+
1443
+ if (data.parameters.color) light.color.copy(data.parameters.color);
1444
+ if (data.parameters.distance) light.distance = data.parameters.distance;
1445
+ return light;
1446
+ }
1447
+
1448
+ function getLight(id) {
1449
+ var data = library.lights[id];
1450
+
1451
+ if (data !== undefined) {
1452
+ return getBuild(data, buildLight);
1453
+ }
1454
+
1455
+ console.warn("THREE.ColladaLoader: Couldn't find light with ID:", id);
1456
+ return null;
1457
+ } // geometry
1458
+
1459
+
1460
+ function parseGeometry(xml) {
1461
+ var data = {
1462
+ name: xml.getAttribute("name"),
1463
+ sources: {},
1464
+ vertices: {},
1465
+ primitives: []
1466
+ };
1467
+ var mesh = getElementsByTagName(xml, "mesh")[0]; // the following tags inside geometry are not supported yet (see https://github.com/mrdoob/three.js/pull/12606): convex_mesh, spline, brep
1468
+
1469
+ if (mesh === undefined) return;
1470
+
1471
+ for (var i = 0; i < mesh.childNodes.length; i++) {
1472
+ var child = mesh.childNodes[i];
1473
+ if (child.nodeType !== 1) continue;
1474
+ var id = child.getAttribute("id");
1475
+
1476
+ switch (child.nodeName) {
1477
+ case "source":
1478
+ data.sources[id] = parseSource(child);
1479
+ break;
1480
+
1481
+ case "vertices":
1482
+ // data.sources[ id ] = data.sources[ parseId( getElementsByTagName( child, 'input' )[ 0 ].getAttribute( 'source' ) ) ];
1483
+ data.vertices = parseGeometryVertices(child);
1484
+ break;
1485
+
1486
+ case "polygons":
1487
+ console.warn("THREE.ColladaLoader: Unsupported primitive type: ", child.nodeName);
1488
+ break;
1489
+
1490
+ case "lines":
1491
+ case "linestrips":
1492
+ case "polylist":
1493
+ case "triangles":
1494
+ data.primitives.push(parseGeometryPrimitive(child));
1495
+ break;
1496
+
1497
+ default:
1498
+ console.log(child);
1499
+ }
1500
+ }
1501
+
1502
+ library.geometries[xml.getAttribute("id")] = data;
1503
+ }
1504
+
1505
+ function parseSource(xml) {
1506
+ var data = {
1507
+ array: [],
1508
+ stride: 3
1509
+ };
1510
+
1511
+ for (var i = 0; i < xml.childNodes.length; i++) {
1512
+ var child = xml.childNodes[i];
1513
+ if (child.nodeType !== 1) continue;
1514
+
1515
+ switch (child.nodeName) {
1516
+ case "float_array":
1517
+ data.array = parseFloats(child.textContent);
1518
+ break;
1519
+
1520
+ case "Name_array":
1521
+ data.array = parseStrings(child.textContent);
1522
+ break;
1523
+
1524
+ case "technique_common":
1525
+ var accessor = getElementsByTagName(child, "accessor")[0];
1526
+
1527
+ if (accessor !== undefined) {
1528
+ data.stride = parseInt(accessor.getAttribute("stride"));
1529
+ }
1530
+
1531
+ break;
1532
+ }
1533
+ }
1534
+
1535
+ return data;
1536
+ }
1537
+
1538
+ function parseGeometryVertices(xml) {
1539
+ var data = {};
1540
+
1541
+ for (var i = 0; i < xml.childNodes.length; i++) {
1542
+ var child = xml.childNodes[i];
1543
+ if (child.nodeType !== 1) continue;
1544
+ data[child.getAttribute("semantic")] = parseId(child.getAttribute("source"));
1545
+ }
1546
+
1547
+ return data;
1548
+ }
1549
+
1550
+ function parseGeometryPrimitive(xml) {
1551
+ var primitive = {
1552
+ type: xml.nodeName,
1553
+ material: xml.getAttribute("material"),
1554
+ count: parseInt(xml.getAttribute("count")),
1555
+ inputs: {},
1556
+ stride: 0,
1557
+ hasUV: false
1558
+ };
1559
+
1560
+ for (var i = 0, l = xml.childNodes.length; i < l; i++) {
1561
+ var child = xml.childNodes[i];
1562
+ if (child.nodeType !== 1) continue;
1563
+
1564
+ switch (child.nodeName) {
1565
+ case "input":
1566
+ var id = parseId(child.getAttribute("source"));
1567
+ var semantic = child.getAttribute("semantic");
1568
+ var offset = parseInt(child.getAttribute("offset"));
1569
+ var set = parseInt(child.getAttribute("set"));
1570
+ var inputname = set > 0 ? semantic + set : semantic;
1571
+ primitive.inputs[inputname] = {
1572
+ id: id,
1573
+ offset: offset
1574
+ };
1575
+ primitive.stride = Math.max(primitive.stride, offset + 1);
1576
+ if (semantic === "TEXCOORD") primitive.hasUV = true;
1577
+ break;
1578
+
1579
+ case "vcount":
1580
+ primitive.vcount = parseInts(child.textContent);
1581
+ break;
1582
+
1583
+ case "p":
1584
+ primitive.p = parseInts(child.textContent);
1585
+ break;
1586
+ }
1587
+ }
1588
+
1589
+ return primitive;
1590
+ }
1591
+
1592
+ function groupPrimitives(primitives) {
1593
+ var build = {};
1594
+
1595
+ for (var i = 0; i < primitives.length; i++) {
1596
+ var primitive = primitives[i];
1597
+ if (build[primitive.type] === undefined) build[primitive.type] = [];
1598
+ build[primitive.type].push(primitive);
1599
+ }
1600
+
1601
+ return build;
1602
+ }
1603
+
1604
+ function checkUVCoordinates(primitives) {
1605
+ var count = 0;
1606
+
1607
+ for (var i = 0, l = primitives.length; i < l; i++) {
1608
+ var primitive = primitives[i];
1609
+
1610
+ if (primitive.hasUV === true) {
1611
+ count++;
1612
+ }
1613
+ }
1614
+
1615
+ if (count > 0 && count < primitives.length) {
1616
+ primitives.uvsNeedsFix = true;
1617
+ }
1618
+ }
1619
+
1620
+ function buildGeometry(data) {
1621
+ var build = {};
1622
+ var sources = data.sources;
1623
+ var vertices = data.vertices;
1624
+ var primitives = data.primitives;
1625
+ if (primitives.length === 0) return {}; // our goal is to create one buffer geometry for a single type of primitives
1626
+ // first, we group all primitives by their type
1627
+
1628
+ var groupedPrimitives = groupPrimitives(primitives);
1629
+
1630
+ for (var type in groupedPrimitives) {
1631
+ var primitiveType = groupedPrimitives[type]; // second, ensure consistent uv coordinates for each type of primitives (polylist,triangles or lines)
1632
+
1633
+ checkUVCoordinates(primitiveType); // third, create a buffer geometry for each type of primitives
1634
+
1635
+ build[type] = buildGeometryType(primitiveType, sources, vertices);
1636
+ }
1637
+
1638
+ return build;
1639
+ }
1640
+
1641
+ function buildGeometryType(primitives, sources, vertices) {
1642
+ var build = {};
1643
+ var position = {
1644
+ array: [],
1645
+ stride: 0
1646
+ };
1647
+ var normal = {
1648
+ array: [],
1649
+ stride: 0
1650
+ };
1651
+ var uv = {
1652
+ array: [],
1653
+ stride: 0
1654
+ };
1655
+ var uv2 = {
1656
+ array: [],
1657
+ stride: 0
1658
+ };
1659
+ var color = {
1660
+ array: [],
1661
+ stride: 0
1662
+ };
1663
+ var skinIndex = {
1664
+ array: [],
1665
+ stride: 4
1666
+ };
1667
+ var skinWeight = {
1668
+ array: [],
1669
+ stride: 4
1670
+ };
1671
+ var geometry = new THREE.BufferGeometry();
1672
+ var materialKeys = [];
1673
+ var start = 0;
1674
+
1675
+ for (var p = 0; p < primitives.length; p++) {
1676
+ var primitive = primitives[p];
1677
+ var inputs = primitive.inputs; // groups
1678
+
1679
+ var count = 0;
1680
+
1681
+ switch (primitive.type) {
1682
+ case "lines":
1683
+ case "linestrips":
1684
+ count = primitive.count * 2;
1685
+ break;
1686
+
1687
+ case "triangles":
1688
+ count = primitive.count * 3;
1689
+ break;
1690
+
1691
+ case "polylist":
1692
+ for (var g = 0; g < primitive.count; g++) {
1693
+ var vc = primitive.vcount[g];
1694
+
1695
+ switch (vc) {
1696
+ case 3:
1697
+ count += 3; // single triangle
1698
+
1699
+ break;
1700
+
1701
+ case 4:
1702
+ count += 6; // quad, subdivided into two triangles
1703
+
1704
+ break;
1705
+
1706
+ default:
1707
+ count += (vc - 2) * 3; // polylist with more than four vertices
1708
+
1709
+ break;
1710
+ }
1711
+ }
1712
+
1713
+ break;
1714
+
1715
+ default:
1716
+ console.warn("THREE.ColladaLoader: Unknow primitive type:", primitive.type);
1717
+ }
1718
+
1719
+ geometry.addGroup(start, count, p);
1720
+ start += count; // material
1721
+
1722
+ if (primitive.material) {
1723
+ materialKeys.push(primitive.material);
1724
+ } // geometry data
1725
+
1726
+
1727
+ for (var name in inputs) {
1728
+ var input = inputs[name];
1729
+
1730
+ switch (name) {
1731
+ case "VERTEX":
1732
+ for (var key in vertices) {
1733
+ var id = vertices[key];
1734
+
1735
+ switch (key) {
1736
+ case "POSITION":
1737
+ var prevLength = position.array.length;
1738
+ buildGeometryData(primitive, sources[id], input.offset, position.array);
1739
+ position.stride = sources[id].stride;
1740
+
1741
+ if (sources.skinWeights && sources.skinIndices) {
1742
+ buildGeometryData(primitive, sources.skinIndices, input.offset, skinIndex.array);
1743
+ buildGeometryData(primitive, sources.skinWeights, input.offset, skinWeight.array);
1744
+ } // see #3803
1745
+
1746
+
1747
+ if (primitive.hasUV === false && primitives.uvsNeedsFix === true) {
1748
+ var count = (position.array.length - prevLength) / position.stride;
1749
+
1750
+ for (var i = 0; i < count; i++) {
1751
+ // fill missing uv coordinates
1752
+ uv.array.push(0, 0);
1753
+ }
1754
+ }
1755
+
1756
+ break;
1757
+
1758
+ case "NORMAL":
1759
+ buildGeometryData(primitive, sources[id], input.offset, normal.array);
1760
+ normal.stride = sources[id].stride;
1761
+ break;
1762
+
1763
+ case "COLOR":
1764
+ buildGeometryData(primitive, sources[id], input.offset, color.array);
1765
+ color.stride = sources[id].stride;
1766
+ break;
1767
+
1768
+ case "TEXCOORD":
1769
+ buildGeometryData(primitive, sources[id], input.offset, uv.array);
1770
+ uv.stride = sources[id].stride;
1771
+ break;
1772
+
1773
+ case "TEXCOORD1":
1774
+ buildGeometryData(primitive, sources[id], input.offset, uv2.array);
1775
+ uv.stride = sources[id].stride;
1776
+ break;
1777
+
1778
+ default:
1779
+ console.warn('THREE.ColladaLoader: Semantic "%s" not handled in geometry build process.', key);
1780
+ }
1781
+ }
1782
+
1783
+ break;
1784
+
1785
+ case "NORMAL":
1786
+ buildGeometryData(primitive, sources[input.id], input.offset, normal.array);
1787
+ normal.stride = sources[input.id].stride;
1788
+ break;
1789
+
1790
+ case "COLOR":
1791
+ buildGeometryData(primitive, sources[input.id], input.offset, color.array);
1792
+ color.stride = sources[input.id].stride;
1793
+ break;
1794
+
1795
+ case "TEXCOORD":
1796
+ buildGeometryData(primitive, sources[input.id], input.offset, uv.array);
1797
+ uv.stride = sources[input.id].stride;
1798
+ break;
1799
+
1800
+ case "TEXCOORD1":
1801
+ buildGeometryData(primitive, sources[input.id], input.offset, uv2.array);
1802
+ uv2.stride = sources[input.id].stride;
1803
+ break;
1804
+ }
1805
+ }
1806
+ } // build geometry
1807
+
1808
+
1809
+ if (position.array.length > 0) geometry.addAttribute("position", new THREE.Float32BufferAttribute(position.array, position.stride));
1810
+ if (normal.array.length > 0) geometry.addAttribute("normal", new THREE.Float32BufferAttribute(normal.array, normal.stride));
1811
+ if (color.array.length > 0) geometry.addAttribute("color", new THREE.Float32BufferAttribute(color.array, color.stride));
1812
+ if (uv.array.length > 0) geometry.addAttribute("uv", new THREE.Float32BufferAttribute(uv.array, uv.stride));
1813
+ if (uv2.array.length > 0) geometry.addAttribute("uv2", new THREE.Float32BufferAttribute(uv2.array, uv2.stride));
1814
+ if (skinIndex.array.length > 0) geometry.addAttribute("skinIndex", new THREE.Float32BufferAttribute(skinIndex.array, skinIndex.stride));
1815
+ if (skinWeight.array.length > 0) geometry.addAttribute("skinWeight", new THREE.Float32BufferAttribute(skinWeight.array, skinWeight.stride));
1816
+ build.data = geometry;
1817
+ build.type = primitives[0].type;
1818
+ build.materialKeys = materialKeys;
1819
+ return build;
1820
+ }
1821
+
1822
+ function buildGeometryData(primitive, source, offset, array) {
1823
+ var indices = primitive.p;
1824
+ var stride = primitive.stride;
1825
+ var vcount = primitive.vcount;
1826
+
1827
+ function pushVector(i) {
1828
+ var index = indices[i + offset] * sourceStride;
1829
+ var length = index + sourceStride;
1830
+
1831
+ for (; index < length; index++) {
1832
+ array.push(sourceArray[index]);
1833
+ }
1834
+ }
1835
+
1836
+ var sourceArray = source.array;
1837
+ var sourceStride = source.stride;
1838
+
1839
+ if (primitive.vcount !== undefined) {
1840
+ var index = 0;
1841
+
1842
+ for (var i = 0, l = vcount.length; i < l; i++) {
1843
+ var count = vcount[i];
1844
+
1845
+ if (count === 4) {
1846
+ var a = index + stride * 0;
1847
+ var b = index + stride * 1;
1848
+ var c = index + stride * 2;
1849
+ var d = index + stride * 3;
1850
+ pushVector(a);
1851
+ pushVector(b);
1852
+ pushVector(d);
1853
+ pushVector(b);
1854
+ pushVector(c);
1855
+ pushVector(d);
1856
+ } else if (count === 3) {
1857
+ var a = index + stride * 0;
1858
+ var b = index + stride * 1;
1859
+ var c = index + stride * 2;
1860
+ pushVector(a);
1861
+ pushVector(b);
1862
+ pushVector(c);
1863
+ } else if (count > 4) {
1864
+ for (var k = 1, kl = count - 2; k <= kl; k++) {
1865
+ var a = index + stride * 0;
1866
+ var b = index + stride * k;
1867
+ var c = index + stride * (k + 1);
1868
+ pushVector(a);
1869
+ pushVector(b);
1870
+ pushVector(c);
1871
+ }
1872
+ }
1873
+
1874
+ index += stride * count;
1875
+ }
1876
+ } else {
1877
+ for (var i = 0, l = indices.length; i < l; i += stride) {
1878
+ pushVector(i);
1879
+ }
1880
+ }
1881
+ }
1882
+
1883
+ function getGeometry(id) {
1884
+ return getBuild(library.geometries[id], buildGeometry);
1885
+ } // kinematics
1886
+
1887
+
1888
+ function parseKinematicsModel(xml) {
1889
+ var data = {
1890
+ name: xml.getAttribute("name") || "",
1891
+ joints: {},
1892
+ links: []
1893
+ };
1894
+
1895
+ for (var i = 0; i < xml.childNodes.length; i++) {
1896
+ var child = xml.childNodes[i];
1897
+ if (child.nodeType !== 1) continue;
1898
+
1899
+ switch (child.nodeName) {
1900
+ case "technique_common":
1901
+ parseKinematicsTechniqueCommon(child, data);
1902
+ break;
1903
+ }
1904
+ }
1905
+
1906
+ library.kinematicsModels[xml.getAttribute("id")] = data;
1907
+ }
1908
+
1909
+ function buildKinematicsModel(data) {
1910
+ if (data.build !== undefined) return data.build;
1911
+ return data;
1912
+ }
1913
+
1914
+ function getKinematicsModel(id) {
1915
+ return getBuild(library.kinematicsModels[id], buildKinematicsModel);
1916
+ }
1917
+
1918
+ function parseKinematicsTechniqueCommon(xml, data) {
1919
+ for (var i = 0; i < xml.childNodes.length; i++) {
1920
+ var child = xml.childNodes[i];
1921
+ if (child.nodeType !== 1) continue;
1922
+
1923
+ switch (child.nodeName) {
1924
+ case "joint":
1925
+ data.joints[child.getAttribute("sid")] = parseKinematicsJoint(child);
1926
+ break;
1927
+
1928
+ case "link":
1929
+ data.links.push(parseKinematicsLink(child));
1930
+ break;
1931
+ }
1932
+ }
1933
+ }
1934
+
1935
+ function parseKinematicsJoint(xml) {
1936
+ var data;
1937
+
1938
+ for (var i = 0; i < xml.childNodes.length; i++) {
1939
+ var child = xml.childNodes[i];
1940
+ if (child.nodeType !== 1) continue;
1941
+
1942
+ switch (child.nodeName) {
1943
+ case "prismatic":
1944
+ case "revolute":
1945
+ data = parseKinematicsJointParameter(child);
1946
+ break;
1947
+ }
1948
+ }
1949
+
1950
+ return data;
1951
+ }
1952
+
1953
+ function parseKinematicsJointParameter(xml, data) {
1954
+ var data = {
1955
+ sid: xml.getAttribute("sid"),
1956
+ name: xml.getAttribute("name") || "",
1957
+ axis: new THREE.Vector3(),
1958
+ limits: {
1959
+ min: 0,
1960
+ max: 0
1961
+ },
1962
+ type: xml.nodeName,
1963
+ "static": false,
1964
+ zeroPosition: 0,
1965
+ middlePosition: 0
1966
+ };
1967
+
1968
+ for (var i = 0; i < xml.childNodes.length; i++) {
1969
+ var child = xml.childNodes[i];
1970
+ if (child.nodeType !== 1) continue;
1971
+
1972
+ switch (child.nodeName) {
1973
+ case "axis":
1974
+ var array = parseFloats(child.textContent);
1975
+ data.axis.fromArray(array);
1976
+ break;
1977
+
1978
+ case "limits":
1979
+ var max = child.getElementsByTagName("max")[0];
1980
+ var min = child.getElementsByTagName("min")[0];
1981
+ data.limits.max = parseFloat(max.textContent);
1982
+ data.limits.min = parseFloat(min.textContent);
1983
+ break;
1984
+ }
1985
+ } // if min is equal to or greater than max, consider the joint static
1986
+
1987
+
1988
+ if (data.limits.min >= data.limits.max) {
1989
+ data["static"] = true;
1990
+ } // calculate middle position
1991
+
1992
+
1993
+ data.middlePosition = (data.limits.min + data.limits.max) / 2.0;
1994
+ return data;
1995
+ }
1996
+
1997
+ function parseKinematicsLink(xml) {
1998
+ var data = {
1999
+ sid: xml.getAttribute("sid"),
2000
+ name: xml.getAttribute("name") || "",
2001
+ attachments: [],
2002
+ transforms: []
2003
+ };
2004
+
2005
+ for (var i = 0; i < xml.childNodes.length; i++) {
2006
+ var child = xml.childNodes[i];
2007
+ if (child.nodeType !== 1) continue;
2008
+
2009
+ switch (child.nodeName) {
2010
+ case "attachment_full":
2011
+ data.attachments.push(parseKinematicsAttachment(child));
2012
+ break;
2013
+
2014
+ case "matrix":
2015
+ case "translate":
2016
+ case "rotate":
2017
+ data.transforms.push(parseKinematicsTransform(child));
2018
+ break;
2019
+ }
2020
+ }
2021
+
2022
+ return data;
2023
+ }
2024
+
2025
+ function parseKinematicsAttachment(xml) {
2026
+ var data = {
2027
+ joint: xml.getAttribute("joint").split("/").pop(),
2028
+ transforms: [],
2029
+ links: []
2030
+ };
2031
+
2032
+ for (var i = 0; i < xml.childNodes.length; i++) {
2033
+ var child = xml.childNodes[i];
2034
+ if (child.nodeType !== 1) continue;
2035
+
2036
+ switch (child.nodeName) {
2037
+ case "link":
2038
+ data.links.push(parseKinematicsLink(child));
2039
+ break;
2040
+
2041
+ case "matrix":
2042
+ case "translate":
2043
+ case "rotate":
2044
+ data.transforms.push(parseKinematicsTransform(child));
2045
+ break;
2046
+ }
2047
+ }
2048
+
2049
+ return data;
2050
+ }
2051
+
2052
+ function parseKinematicsTransform(xml) {
2053
+ var data = {
2054
+ type: xml.nodeName
2055
+ };
2056
+ var array = parseFloats(xml.textContent);
2057
+
2058
+ switch (data.type) {
2059
+ case "matrix":
2060
+ data.obj = new THREE.Matrix4();
2061
+ data.obj.fromArray(array).transpose();
2062
+ break;
2063
+
2064
+ case "translate":
2065
+ data.obj = new THREE.Vector3();
2066
+ data.obj.fromArray(array);
2067
+ break;
2068
+
2069
+ case "rotate":
2070
+ data.obj = new THREE.Vector3();
2071
+ data.obj.fromArray(array);
2072
+ data.angle = THREE.Math.degToRad(array[3]);
2073
+ break;
2074
+ }
2075
+
2076
+ return data;
2077
+ } // physics
2078
+
2079
+
2080
+ function parsePhysicsModel(xml) {
2081
+ var data = {
2082
+ name: xml.getAttribute("name") || "",
2083
+ rigidBodies: {}
2084
+ };
2085
+
2086
+ for (var i = 0; i < xml.childNodes.length; i++) {
2087
+ var child = xml.childNodes[i];
2088
+ if (child.nodeType !== 1) continue;
2089
+
2090
+ switch (child.nodeName) {
2091
+ case "rigid_body":
2092
+ data.rigidBodies[child.getAttribute("name")] = {};
2093
+ parsePhysicsRigidBody(child, data.rigidBodies[child.getAttribute("name")]);
2094
+ break;
2095
+ }
2096
+ }
2097
+
2098
+ library.physicsModels[xml.getAttribute("id")] = data;
2099
+ }
2100
+
2101
+ function parsePhysicsRigidBody(xml, data) {
2102
+ for (var i = 0; i < xml.childNodes.length; i++) {
2103
+ var child = xml.childNodes[i];
2104
+ if (child.nodeType !== 1) continue;
2105
+
2106
+ switch (child.nodeName) {
2107
+ case "technique_common":
2108
+ parsePhysicsTechniqueCommon(child, data);
2109
+ break;
2110
+ }
2111
+ }
2112
+ }
2113
+
2114
+ function parsePhysicsTechniqueCommon(xml, data) {
2115
+ for (var i = 0; i < xml.childNodes.length; i++) {
2116
+ var child = xml.childNodes[i];
2117
+ if (child.nodeType !== 1) continue;
2118
+
2119
+ switch (child.nodeName) {
2120
+ case "inertia":
2121
+ data.inertia = parseFloats(child.textContent);
2122
+ break;
2123
+
2124
+ case "mass":
2125
+ data.mass = parseFloats(child.textContent)[0];
2126
+ break;
2127
+ }
2128
+ }
2129
+ } // scene
2130
+
2131
+
2132
+ function parseKinematicsScene(xml) {
2133
+ var data = {
2134
+ bindJointAxis: []
2135
+ };
2136
+
2137
+ for (var i = 0; i < xml.childNodes.length; i++) {
2138
+ var child = xml.childNodes[i];
2139
+ if (child.nodeType !== 1) continue;
2140
+
2141
+ switch (child.nodeName) {
2142
+ case "bind_joint_axis":
2143
+ data.bindJointAxis.push(parseKinematicsBindJointAxis(child));
2144
+ break;
2145
+ }
2146
+ }
2147
+
2148
+ library.kinematicsScenes[parseId(xml.getAttribute("url"))] = data;
2149
+ }
2150
+
2151
+ function parseKinematicsBindJointAxis(xml) {
2152
+ var data = {
2153
+ target: xml.getAttribute("target").split("/").pop()
2154
+ };
2155
+
2156
+ for (var i = 0; i < xml.childNodes.length; i++) {
2157
+ var child = xml.childNodes[i];
2158
+ if (child.nodeType !== 1) continue;
2159
+
2160
+ switch (child.nodeName) {
2161
+ case "axis":
2162
+ var param = child.getElementsByTagName("param")[0];
2163
+ data.axis = param.textContent;
2164
+ var tmpJointIndex = data.axis.split("inst_").pop().split("axis")[0];
2165
+ data.jointIndex = tmpJointIndex.substr(0, tmpJointIndex.length - 1);
2166
+ break;
2167
+ }
2168
+ }
2169
+
2170
+ return data;
2171
+ }
2172
+
2173
+ function buildKinematicsScene(data) {
2174
+ if (data.build !== undefined) return data.build;
2175
+ return data;
2176
+ }
2177
+
2178
+ function getKinematicsScene(id) {
2179
+ return getBuild(library.kinematicsScenes[id], buildKinematicsScene);
2180
+ }
2181
+
2182
+ function setupKinematics() {
2183
+ var kinematicsModelId = Object.keys(library.kinematicsModels)[0];
2184
+ var kinematicsSceneId = Object.keys(library.kinematicsScenes)[0];
2185
+ var visualSceneId = Object.keys(library.visualScenes)[0];
2186
+ if (kinematicsModelId === undefined || kinematicsSceneId === undefined) return;
2187
+ var kinematicsModel = getKinematicsModel(kinematicsModelId);
2188
+ var kinematicsScene = getKinematicsScene(kinematicsSceneId);
2189
+ var visualScene = getVisualScene(visualSceneId);
2190
+ var bindJointAxis = kinematicsScene.bindJointAxis;
2191
+ var jointMap = {};
2192
+
2193
+ for (var i = 0, l = bindJointAxis.length; i < l; i++) {
2194
+ var axis = bindJointAxis[i]; // the result of the following query is an element of type 'translate', 'rotate','scale' or 'matrix'
2195
+
2196
+ var targetElement = collada.querySelector('[sid="' + axis.target + '"]');
2197
+
2198
+ if (targetElement) {
2199
+ // get the parent of the transfrom element
2200
+ var parentVisualElement = targetElement.parentElement; // connect the joint of the kinematics model with the element in the visual scene
2201
+
2202
+ connect(axis.jointIndex, parentVisualElement);
2203
+ }
2204
+ }
2205
+
2206
+ function connect(jointIndex, visualElement) {
2207
+ var visualElementName = visualElement.getAttribute("name");
2208
+ var joint = kinematicsModel.joints[jointIndex];
2209
+ visualScene.traverse(function (object) {
2210
+ if (object.name === visualElementName) {
2211
+ jointMap[jointIndex] = {
2212
+ object: object,
2213
+ transforms: buildTransformList(visualElement),
2214
+ joint: joint,
2215
+ position: joint.zeroPosition
2216
+ };
2217
+ }
2218
+ });
2219
+ }
2220
+
2221
+ var m0 = new THREE.Matrix4();
2222
+ kinematics = {
2223
+ joints: kinematicsModel && kinematicsModel.joints,
2224
+ getJointValue: function getJointValue(jointIndex) {
2225
+ var jointData = jointMap[jointIndex];
2226
+
2227
+ if (jointData) {
2228
+ return jointData.position;
2229
+ } else {
2230
+ console.warn("THREE.ColladaLoader: Joint " + jointIndex + " doesn't exist.");
2231
+ }
2232
+ },
2233
+ setJointValue: function setJointValue(jointIndex, value) {
2234
+ var jointData = jointMap[jointIndex];
2235
+
2236
+ if (jointData) {
2237
+ var joint = jointData.joint;
2238
+
2239
+ if (value > joint.limits.max || value < joint.limits.min) {
2240
+ console.warn("THREE.ColladaLoader: Joint " + jointIndex + " value " + value + " outside of limits (min: " + joint.limits.min + ", max: " + joint.limits.max + ").");
2241
+ } else if (joint["static"]) {
2242
+ console.warn("THREE.ColladaLoader: Joint " + jointIndex + " is static.");
2243
+ } else {
2244
+ var object = jointData.object;
2245
+ var axis = joint.axis;
2246
+ var transforms = jointData.transforms;
2247
+ matrix.identity(); // each update, we have to apply all transforms in the correct order
2248
+
2249
+ for (var i = 0; i < transforms.length; i++) {
2250
+ var transform = transforms[i]; // if there is a connection of the transform node with a joint, apply the joint value
2251
+
2252
+ if (transform.sid && transform.sid.indexOf(jointIndex) !== -1) {
2253
+ switch (joint.type) {
2254
+ case "revolute":
2255
+ matrix.multiply(m0.makeRotationAxis(axis, THREE.Math.degToRad(value)));
2256
+ break;
2257
+
2258
+ case "prismatic":
2259
+ matrix.multiply(m0.makeTranslation(axis.x * value, axis.y * value, axis.z * value));
2260
+ break;
2261
+
2262
+ default:
2263
+ console.warn("THREE.ColladaLoader: Unknown joint type: " + joint.type);
2264
+ break;
2265
+ }
2266
+ } else {
2267
+ switch (transform.type) {
2268
+ case "matrix":
2269
+ matrix.multiply(transform.obj);
2270
+ break;
2271
+
2272
+ case "translate":
2273
+ matrix.multiply(m0.makeTranslation(transform.obj.x, transform.obj.y, transform.obj.z));
2274
+ break;
2275
+
2276
+ case "scale":
2277
+ matrix.scale(transform.obj);
2278
+ break;
2279
+
2280
+ case "rotate":
2281
+ matrix.multiply(m0.makeRotationAxis(transform.obj, transform.angle));
2282
+ break;
2283
+ }
2284
+ }
2285
+ }
2286
+
2287
+ object.matrix.copy(matrix);
2288
+ object.matrix.decompose(object.position, object.quaternion, object.scale);
2289
+ jointMap[jointIndex].position = value;
2290
+ }
2291
+ } else {
2292
+ console.log("THREE.ColladaLoader: " + jointIndex + " does not exist.");
2293
+ }
2294
+ }
2295
+ };
2296
+ }
2297
+
2298
+ function buildTransformList(node) {
2299
+ var transforms = [];
2300
+ var xml = collada.querySelector('[id="' + node.id + '"]');
2301
+
2302
+ for (var i = 0; i < xml.childNodes.length; i++) {
2303
+ var child = xml.childNodes[i];
2304
+ if (child.nodeType !== 1) continue;
2305
+
2306
+ switch (child.nodeName) {
2307
+ case "matrix":
2308
+ var array = parseFloats(child.textContent);
2309
+ var matrix = new THREE.Matrix4().fromArray(array).transpose();
2310
+ transforms.push({
2311
+ sid: child.getAttribute("sid"),
2312
+ type: child.nodeName,
2313
+ obj: matrix
2314
+ });
2315
+ break;
2316
+
2317
+ case "translate":
2318
+ case "scale":
2319
+ var array = parseFloats(child.textContent);
2320
+ var vector = new THREE.Vector3().fromArray(array);
2321
+ transforms.push({
2322
+ sid: child.getAttribute("sid"),
2323
+ type: child.nodeName,
2324
+ obj: vector
2325
+ });
2326
+ break;
2327
+
2328
+ case "rotate":
2329
+ var array = parseFloats(child.textContent);
2330
+ var vector = new THREE.Vector3().fromArray(array);
2331
+ var angle = THREE.Math.degToRad(array[3]);
2332
+ transforms.push({
2333
+ sid: child.getAttribute("sid"),
2334
+ type: child.nodeName,
2335
+ obj: vector,
2336
+ angle: angle
2337
+ });
2338
+ break;
2339
+ }
2340
+ }
2341
+
2342
+ return transforms;
2343
+ } // nodes
2344
+
2345
+
2346
+ function prepareNodes(xml) {
2347
+ var elements = xml.getElementsByTagName("node"); // ensure all node elements have id attributes
2348
+
2349
+ for (var i = 0; i < elements.length; i++) {
2350
+ var element = elements[i];
2351
+
2352
+ if (element.hasAttribute("id") === false) {
2353
+ element.setAttribute("id", generateId());
2354
+ }
2355
+ }
2356
+ }
2357
+
2358
+ var matrix = new THREE.Matrix4();
2359
+ var vector = new THREE.Vector3();
2360
+
2361
+ function parseNode(xml) {
2362
+ var data = {
2363
+ name: xml.getAttribute("name") || "",
2364
+ type: xml.getAttribute("type"),
2365
+ id: xml.getAttribute("id"),
2366
+ sid: xml.getAttribute("sid"),
2367
+ matrix: new THREE.Matrix4(),
2368
+ nodes: [],
2369
+ instanceCameras: [],
2370
+ instanceControllers: [],
2371
+ instanceLights: [],
2372
+ instanceGeometries: [],
2373
+ instanceNodes: [],
2374
+ transforms: {}
2375
+ };
2376
+
2377
+ for (var i = 0; i < xml.childNodes.length; i++) {
2378
+ var child = xml.childNodes[i];
2379
+ if (child.nodeType !== 1) continue;
2380
+
2381
+ switch (child.nodeName) {
2382
+ case "node":
2383
+ data.nodes.push(child.getAttribute("id"));
2384
+ parseNode(child);
2385
+ break;
2386
+
2387
+ case "instance_camera":
2388
+ data.instanceCameras.push(parseId(child.getAttribute("url")));
2389
+ break;
2390
+
2391
+ case "instance_controller":
2392
+ data.instanceControllers.push(parseNodeInstance(child));
2393
+ break;
2394
+
2395
+ case "instance_light":
2396
+ data.instanceLights.push(parseId(child.getAttribute("url")));
2397
+ break;
2398
+
2399
+ case "instance_geometry":
2400
+ data.instanceGeometries.push(parseNodeInstance(child));
2401
+ break;
2402
+
2403
+ case "instance_node":
2404
+ data.instanceNodes.push(parseId(child.getAttribute("url")));
2405
+ break;
2406
+
2407
+ case "matrix":
2408
+ var array = parseFloats(child.textContent);
2409
+ data.matrix.multiply(matrix.fromArray(array).transpose());
2410
+ data.transforms[child.getAttribute("sid")] = child.nodeName;
2411
+ break;
2412
+
2413
+ case "translate":
2414
+ var array = parseFloats(child.textContent);
2415
+ vector.fromArray(array);
2416
+ data.matrix.multiply(matrix.makeTranslation(vector.x, vector.y, vector.z));
2417
+ data.transforms[child.getAttribute("sid")] = child.nodeName;
2418
+ break;
2419
+
2420
+ case "rotate":
2421
+ var array = parseFloats(child.textContent);
2422
+ var angle = THREE.Math.degToRad(array[3]);
2423
+ data.matrix.multiply(matrix.makeRotationAxis(vector.fromArray(array), angle));
2424
+ data.transforms[child.getAttribute("sid")] = child.nodeName;
2425
+ break;
2426
+
2427
+ case "scale":
2428
+ var array = parseFloats(child.textContent);
2429
+ data.matrix.scale(vector.fromArray(array));
2430
+ data.transforms[child.getAttribute("sid")] = child.nodeName;
2431
+ break;
2432
+
2433
+ case "extra":
2434
+ break;
2435
+
2436
+ default:
2437
+ console.log(child);
2438
+ }
2439
+ }
2440
+
2441
+ if (hasNode(data.id)) {
2442
+ console.warn("THREE.ColladaLoader: There is already a node with ID %s. Exclude current node from further processing.", data.id);
2443
+ } else {
2444
+ library.nodes[data.id] = data;
2445
+ }
2446
+
2447
+ return data;
2448
+ }
2449
+
2450
+ function parseNodeInstance(xml) {
2451
+ var data = {
2452
+ id: parseId(xml.getAttribute("url")),
2453
+ materials: {},
2454
+ skeletons: []
2455
+ };
2456
+
2457
+ for (var i = 0; i < xml.childNodes.length; i++) {
2458
+ var child = xml.childNodes[i];
2459
+
2460
+ switch (child.nodeName) {
2461
+ case "bind_material":
2462
+ var instances = child.getElementsByTagName("instance_material");
2463
+
2464
+ for (var j = 0; j < instances.length; j++) {
2465
+ var instance = instances[j];
2466
+ var symbol = instance.getAttribute("symbol");
2467
+ var target = instance.getAttribute("target");
2468
+ data.materials[symbol] = parseId(target);
2469
+ }
2470
+
2471
+ break;
2472
+
2473
+ case "skeleton":
2474
+ data.skeletons.push(parseId(child.textContent));
2475
+ break;
2476
+
2477
+ default:
2478
+ break;
2479
+ }
2480
+ }
2481
+
2482
+ return data;
2483
+ }
2484
+
2485
+ function buildSkeleton(skeletons, joints) {
2486
+ var boneData = [];
2487
+ var sortedBoneData = [];
2488
+ var i, j, data; // a skeleton can have multiple root bones. collada expresses this
2489
+ // situtation with multiple "skeleton" tags per controller instance
2490
+
2491
+ for (i = 0; i < skeletons.length; i++) {
2492
+ var skeleton = skeletons[i];
2493
+ var root;
2494
+
2495
+ if (hasNode(skeleton)) {
2496
+ root = getNode(skeleton);
2497
+ buildBoneHierarchy(root, joints, boneData);
2498
+ } else if (hasVisualScene(skeleton)) {
2499
+ // handle case where the skeleton refers to the visual scene (#13335)
2500
+ var visualScene = library.visualScenes[skeleton];
2501
+ var children = visualScene.children;
2502
+
2503
+ for (var j = 0; j < children.length; j++) {
2504
+ var child = children[j];
2505
+
2506
+ if (child.type === "JOINT") {
2507
+ var root = getNode(child.id);
2508
+ buildBoneHierarchy(root, joints, boneData);
2509
+ }
2510
+ }
2511
+ } else {
2512
+ console.error("THREE.ColladaLoader: Unable to find root bone of skeleton with ID:", skeleton);
2513
+ }
2514
+ } // sort bone data (the order is defined in the corresponding controller)
2515
+
2516
+
2517
+ for (i = 0; i < joints.length; i++) {
2518
+ for (j = 0; j < boneData.length; j++) {
2519
+ data = boneData[j];
2520
+
2521
+ if (data.bone.name === joints[i].name) {
2522
+ sortedBoneData[i] = data;
2523
+ data.processed = true;
2524
+ break;
2525
+ }
2526
+ }
2527
+ } // add unprocessed bone data at the end of the list
2528
+
2529
+
2530
+ for (i = 0; i < boneData.length; i++) {
2531
+ data = boneData[i];
2532
+
2533
+ if (data.processed === false) {
2534
+ sortedBoneData.push(data);
2535
+ data.processed = true;
2536
+ }
2537
+ } // setup arrays for skeleton creation
2538
+
2539
+
2540
+ var bones = [];
2541
+ var boneInverses = [];
2542
+
2543
+ for (i = 0; i < sortedBoneData.length; i++) {
2544
+ data = sortedBoneData[i];
2545
+ bones.push(data.bone);
2546
+ boneInverses.push(data.boneInverse);
2547
+ }
2548
+
2549
+ return new THREE.Skeleton(bones, boneInverses);
2550
+ }
2551
+
2552
+ function buildBoneHierarchy(root, joints, boneData) {
2553
+ // setup bone data from visual scene
2554
+ root.traverse(function (object) {
2555
+ if (object.isBone === true) {
2556
+ var boneInverse; // retrieve the boneInverse from the controller data
2557
+
2558
+ for (var i = 0; i < joints.length; i++) {
2559
+ var joint = joints[i];
2560
+
2561
+ if (joint.name === object.name) {
2562
+ boneInverse = joint.boneInverse;
2563
+ break;
2564
+ }
2565
+ }
2566
+
2567
+ if (boneInverse === undefined) {
2568
+ // Unfortunately, there can be joints in the visual scene that are not part of the
2569
+ // corresponding controller. In this case, we have to create a dummy boneInverse matrix
2570
+ // for the respective bone. This bone won't affect any vertices, because there are no skin indices
2571
+ // and weights defined for it. But we still have to add the bone to the sorted bone list in order to
2572
+ // ensure a correct animation of the model.
2573
+ boneInverse = new THREE.Matrix4();
2574
+ }
2575
+
2576
+ boneData.push({
2577
+ bone: object,
2578
+ boneInverse: boneInverse,
2579
+ processed: false
2580
+ });
2581
+ }
2582
+ });
2583
+ }
2584
+
2585
+ function buildNode(data) {
2586
+ var objects = [];
2587
+ var matrix = data.matrix;
2588
+ var nodes = data.nodes;
2589
+ var type = data.type;
2590
+ var instanceCameras = data.instanceCameras;
2591
+ var instanceControllers = data.instanceControllers;
2592
+ var instanceLights = data.instanceLights;
2593
+ var instanceGeometries = data.instanceGeometries;
2594
+ var instanceNodes = data.instanceNodes; // nodes
2595
+
2596
+ for (var i = 0, l = nodes.length; i < l; i++) {
2597
+ objects.push(getNode(nodes[i]));
2598
+ } // instance cameras
2599
+
2600
+
2601
+ for (var i = 0, l = instanceCameras.length; i < l; i++) {
2602
+ var instanceCamera = getCamera(instanceCameras[i]);
2603
+
2604
+ if (instanceCamera !== null) {
2605
+ objects.push(instanceCamera.clone());
2606
+ }
2607
+ } // instance controllers
2608
+
2609
+
2610
+ for (var i = 0, l = instanceControllers.length; i < l; i++) {
2611
+ var instance = instanceControllers[i];
2612
+ var controller = getController(instance.id);
2613
+ var geometries = getGeometry(controller.id);
2614
+ var newObjects = buildObjects(geometries, instance.materials);
2615
+ var skeletons = instance.skeletons;
2616
+ var joints = controller.skin.joints;
2617
+ var skeleton = buildSkeleton(skeletons, joints);
2618
+
2619
+ for (var j = 0, jl = newObjects.length; j < jl; j++) {
2620
+ var object = newObjects[j];
2621
+
2622
+ if (object.isSkinnedMesh) {
2623
+ object.bind(skeleton, controller.skin.bindMatrix);
2624
+ object.normalizeSkinWeights();
2625
+ }
2626
+
2627
+ objects.push(object);
2628
+ }
2629
+ } // instance lights
2630
+
2631
+
2632
+ for (var i = 0, l = instanceLights.length; i < l; i++) {
2633
+ var instanceLight = getLight(instanceLights[i]);
2634
+
2635
+ if (instanceLight !== null) {
2636
+ objects.push(instanceLight.clone());
2637
+ }
2638
+ } // instance geometries
2639
+
2640
+
2641
+ for (var i = 0, l = instanceGeometries.length; i < l; i++) {
2642
+ var instance = instanceGeometries[i]; // a single geometry instance in collada can lead to multiple object3Ds.
2643
+ // this is the case when primitives are combined like triangles and lines
2644
+
2645
+ var geometries = getGeometry(instance.id);
2646
+ var newObjects = buildObjects(geometries, instance.materials);
2647
+
2648
+ for (var j = 0, jl = newObjects.length; j < jl; j++) {
2649
+ objects.push(newObjects[j]);
2650
+ }
2651
+ } // instance nodes
2652
+
2653
+
2654
+ for (var i = 0, l = instanceNodes.length; i < l; i++) {
2655
+ objects.push(getNode(instanceNodes[i]).clone());
2656
+ }
2657
+
2658
+ var object;
2659
+
2660
+ if (nodes.length === 0 && objects.length === 1) {
2661
+ object = objects[0];
2662
+ } else {
2663
+ object = type === "JOINT" ? new THREE.Bone() : new THREE.Group();
2664
+
2665
+ for (var i = 0; i < objects.length; i++) {
2666
+ object.add(objects[i]);
2667
+ }
2668
+ }
2669
+
2670
+ if (object.name === "") {
2671
+ object.name = type === "JOINT" ? data.sid : data.name;
2672
+ }
2673
+
2674
+ object.matrix.copy(matrix);
2675
+ object.matrix.decompose(object.position, object.quaternion, object.scale);
2676
+ return object;
2677
+ }
2678
+
2679
+ var fallbackMaterial = new THREE.MeshBasicMaterial({
2680
+ color: 0xff00ff
2681
+ });
2682
+
2683
+ function resolveMaterialBinding(keys, instanceMaterials) {
2684
+ var materials = [];
2685
+
2686
+ for (var i = 0, l = keys.length; i < l; i++) {
2687
+ var id = instanceMaterials[keys[i]];
2688
+
2689
+ if (id === undefined) {
2690
+ console.warn("THREE.ColladaLoader: Material with key %s not found. Apply fallback material.", keys[i]);
2691
+ materials.push(fallbackMaterial);
2692
+ } else {
2693
+ materials.push(getMaterial(id));
2694
+ }
2695
+ }
2696
+
2697
+ return materials;
2698
+ }
2699
+
2700
+ function buildObjects(geometries, instanceMaterials) {
2701
+ var objects = [];
2702
+
2703
+ for (var type in geometries) {
2704
+ var geometry = geometries[type];
2705
+ var materials = resolveMaterialBinding(geometry.materialKeys, instanceMaterials); // handle case if no materials are defined
2706
+
2707
+ if (materials.length === 0) {
2708
+ if (type === "lines" || type === "linestrips") {
2709
+ materials.push(new THREE.LineBasicMaterial());
2710
+ } else {
2711
+ materials.push(new THREE.MeshPhongMaterial());
2712
+ }
2713
+ } // regard skinning
2714
+
2715
+
2716
+ var skinning = geometry.data.attributes.skinIndex !== undefined;
2717
+
2718
+ if (skinning) {
2719
+ for (var i = 0, l = materials.length; i < l; i++) {
2720
+ materials[i].skinning = true;
2721
+ }
2722
+ } // choose between a single or multi materials (material array)
2723
+
2724
+
2725
+ var material = materials.length === 1 ? materials[0] : materials; // now create a specific 3D object
2726
+
2727
+ var object;
2728
+
2729
+ switch (type) {
2730
+ case "lines":
2731
+ object = new THREE.LineSegments(geometry.data, material);
2732
+ break;
2733
+
2734
+ case "linestrips":
2735
+ object = new THREE.Line(geometry.data, material);
2736
+ break;
2737
+
2738
+ case "triangles":
2739
+ case "polylist":
2740
+ if (skinning) {
2741
+ object = new THREE.SkinnedMesh(geometry.data, material);
2742
+ } else {
2743
+ object = new THREE.Mesh(geometry.data, material);
2744
+ }
2745
+
2746
+ break;
2747
+ }
2748
+
2749
+ objects.push(object);
2750
+ }
2751
+
2752
+ return objects;
2753
+ }
2754
+
2755
+ function hasNode(id) {
2756
+ return library.nodes[id] !== undefined;
2757
+ }
2758
+
2759
+ function getNode(id) {
2760
+ return getBuild(library.nodes[id], buildNode);
2761
+ } // visual scenes
2762
+
2763
+
2764
+ function parseVisualScene(xml) {
2765
+ var data = {
2766
+ name: xml.getAttribute("name"),
2767
+ children: []
2768
+ };
2769
+ prepareNodes(xml);
2770
+ var elements = getElementsByTagName(xml, "node");
2771
+
2772
+ for (var i = 0; i < elements.length; i++) {
2773
+ data.children.push(parseNode(elements[i]));
2774
+ }
2775
+
2776
+ library.visualScenes[xml.getAttribute("id")] = data;
2777
+ }
2778
+
2779
+ function buildVisualScene(data) {
2780
+ var group = new THREE.Group();
2781
+ group.name = data.name;
2782
+ var children = data.children;
2783
+
2784
+ for (var i = 0; i < children.length; i++) {
2785
+ var child = children[i];
2786
+ group.add(getNode(child.id));
2787
+ }
2788
+
2789
+ return group;
2790
+ }
2791
+
2792
+ function hasVisualScene(id) {
2793
+ return library.visualScenes[id] !== undefined;
2794
+ }
2795
+
2796
+ function getVisualScene(id) {
2797
+ return getBuild(library.visualScenes[id], buildVisualScene);
2798
+ } // scenes
2799
+
2800
+
2801
+ function parseScene(xml) {
2802
+ var instance = getElementsByTagName(xml, "instance_visual_scene")[0];
2803
+ return getVisualScene(parseId(instance.getAttribute("url")));
2804
+ }
2805
+
2806
+ function setupAnimations() {
2807
+ var clips = library.clips;
2808
+
2809
+ if (isEmpty(clips) === true) {
2810
+ if (isEmpty(library.animations) === false) {
2811
+ // if there are animations but no clips, we create a default clip for playback
2812
+ var tracks = [];
2813
+
2814
+ for (var id in library.animations) {
2815
+ var animationTracks = getAnimation(id);
2816
+
2817
+ for (var i = 0, l = animationTracks.length; i < l; i++) {
2818
+ tracks.push(animationTracks[i]);
2819
+ }
2820
+ }
2821
+
2822
+ animations.push(new THREE.AnimationClip("default", -1, tracks));
2823
+ }
2824
+ } else {
2825
+ for (var id in clips) {
2826
+ animations.push(getAnimationClip(id));
2827
+ }
2828
+ }
2829
+ }
2830
+
2831
+ if (text.length === 0) {
2832
+ return {
2833
+ scene: new THREE.Scene()
2834
+ };
2835
+ }
2836
+
2837
+ var xml = new DOMParser().parseFromString(text, "application/xml");
2838
+ var collada = getElementsByTagName(xml, "COLLADA")[0]; // metadata
2839
+
2840
+ var version = collada.getAttribute("version");
2841
+ console.log("THREE.ColladaLoader: File version", version);
2842
+ var asset = parseAsset(getElementsByTagName(collada, "asset")[0]);
2843
+ var textureLoader = new THREE.TextureLoader(this.manager);
2844
+ textureLoader.setPath(this.resourcePath || path).setCrossOrigin(this.crossOrigin);
2845
+ var tgaLoader;
2846
+
2847
+ if (THREE.TGALoader) {
2848
+ tgaLoader = new THREE.TGALoader(this.manager);
2849
+ tgaLoader.setPath(this.resourcePath || path);
2850
+ } //
2851
+
2852
+
2853
+ var animations = [];
2854
+ var kinematics = {};
2855
+ var count = 0; //
2856
+
2857
+ var library = {
2858
+ animations: {},
2859
+ clips: {},
2860
+ controllers: {},
2861
+ images: {},
2862
+ effects: {},
2863
+ materials: {},
2864
+ cameras: {},
2865
+ lights: {},
2866
+ geometries: {},
2867
+ nodes: {},
2868
+ visualScenes: {},
2869
+ kinematicsModels: {},
2870
+ physicsModels: {},
2871
+ kinematicsScenes: {}
2872
+ };
2873
+ parseLibrary(collada, "library_animations", "animation", parseAnimation);
2874
+ parseLibrary(collada, "library_animation_clips", "animation_clip", parseAnimationClip);
2875
+ parseLibrary(collada, "library_controllers", "controller", parseController);
2876
+ parseLibrary(collada, "library_images", "image", parseImage);
2877
+ parseLibrary(collada, "library_effects", "effect", parseEffect);
2878
+ parseLibrary(collada, "library_materials", "material", parseMaterial);
2879
+ parseLibrary(collada, "library_cameras", "camera", parseCamera);
2880
+ parseLibrary(collada, "library_lights", "light", parseLight);
2881
+ parseLibrary(collada, "library_geometries", "geometry", parseGeometry);
2882
+ parseLibrary(collada, "library_nodes", "node", parseNode);
2883
+ parseLibrary(collada, "library_visual_scenes", "visual_scene", parseVisualScene);
2884
+ parseLibrary(collada, "library_kinematics_models", "kinematics_model", parseKinematicsModel);
2885
+ parseLibrary(collada, "library_physics_models", "physics_model", parsePhysicsModel);
2886
+ parseLibrary(collada, "scene", "instance_kinematics_scene", parseKinematicsScene);
2887
+ buildLibrary(library.animations, buildAnimation);
2888
+ buildLibrary(library.clips, buildAnimationClip);
2889
+ buildLibrary(library.controllers, buildController);
2890
+ buildLibrary(library.images, buildImage);
2891
+ buildLibrary(library.effects, buildEffect);
2892
+ buildLibrary(library.materials, buildMaterial);
2893
+ buildLibrary(library.cameras, buildCamera);
2894
+ buildLibrary(library.lights, buildLight);
2895
+ buildLibrary(library.geometries, buildGeometry);
2896
+ buildLibrary(library.visualScenes, buildVisualScene);
2897
+ setupAnimations();
2898
+ setupKinematics();
2899
+ var scene = parseScene(getElementsByTagName(collada, "scene")[0]);
2900
+
2901
+ if (asset.upAxis === "Z_UP") {
2902
+ scene.quaternion.setFromEuler(new THREE.Euler(-Math.PI / 2, 0, 0));
2903
+ }
2904
+
2905
+ scene.scale.multiplyScalar(asset.unit);
2906
+ return {
2907
+ animations: animations,
2908
+ kinematics: kinematics,
2909
+ library: library,
2910
+ scene: scene
2911
+ };
2912
+ }
2913
+ }; // important: don't forget to export it
2914
+
2915
+ var _default = THREE.ColladaLoader;
2916
+ exports["default"] = _default;