elation-engine 0.9.113 → 0.9.115

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 (91) hide show
  1. package/css/systems/render.css +5 -1
  2. package/package.json +1 -1
  3. package/scripts/assets.js +103 -20
  4. package/scripts/assetworker.js +18 -1
  5. package/scripts/external/holoplay.js +1494 -0
  6. package/scripts/external/octree.js +0 -0
  7. package/scripts/external/three/CSS3DRenderer.js +46 -43
  8. package/scripts/external/three/CubemapToEquirectangular.js +1 -1
  9. package/scripts/external/three/three-extras.js +1553 -392
  10. package/scripts/external/three/three-icosa.js +2575 -0
  11. package/scripts/external/three/three-loaders.js +925 -133
  12. package/scripts/external/three/three-postprocessing.js +3 -3
  13. package/scripts/external/three/three-r116dev.js +50930 -0
  14. package/scripts/external/three/three-spotlighttextures.js +50953 -0
  15. package/scripts/external/three/three-vrm.js +2 -2
  16. package/scripts/external/three/three-working.js +35968 -0
  17. package/scripts/external/three/three.js +38532 -24087
  18. package/scripts/external/three-mesh-bvh.js +5370 -0
  19. package/scripts/external/three-old/BVHLoader.js +406 -0
  20. package/scripts/external/three-old/ColladaLoader.js +5519 -0
  21. package/scripts/external/three-old/ColladaLoader2.js +1694 -0
  22. package/scripts/external/three-old/CubemapToEquirectangular.js +188 -0
  23. package/scripts/external/three-old/DDSLoader.js +269 -0
  24. package/scripts/external/three-old/FBXLoader-mine.js +5063 -0
  25. package/scripts/external/three-old/FBXLoader.js +5112 -0
  26. package/scripts/external/three-old/FlyControls.js +295 -0
  27. package/scripts/external/three-old/GLTF2Loader.js +2950 -0
  28. package/scripts/external/three-old/GLTFLoader.js +2213 -0
  29. package/scripts/external/three-old/JSONLoader.js +435 -0
  30. package/scripts/external/three-old/MTLLoader.js +533 -0
  31. package/scripts/external/three-old/OBJLoader-experimental.js +874 -0
  32. package/scripts/external/three-old/OBJLoader-working.js +727 -0
  33. package/scripts/external/three-old/OBJLoader.js +723 -0
  34. package/scripts/external/three-old/OBJMTLLoader.js +440 -0
  35. package/scripts/external/three-old/OrbitControls.js +592 -0
  36. package/scripts/external/three-old/PLYLoader.js +517 -0
  37. package/scripts/external/three-old/TransformControls.js +1100 -0
  38. package/scripts/external/three-old/VRMLLoader.js +1021 -0
  39. package/scripts/external/three-old/glTFLoader-combined.js +2513 -0
  40. package/scripts/external/three-old/nodethree.js +44018 -0
  41. package/scripts/external/three-old/render/BleachBypassShader.js +64 -0
  42. package/scripts/external/three-old/render/BloomPass.js +116 -0
  43. package/scripts/external/three-old/render/CSS3DRenderer.js +310 -0
  44. package/scripts/external/three-old/render/ClearPass.js +44 -0
  45. package/scripts/external/three-old/render/ConvolutionShader.js +101 -0
  46. package/scripts/external/three-old/render/CopyShader.js +46 -0
  47. package/scripts/external/three-old/render/EffectComposer.js +211 -0
  48. package/scripts/external/three-old/render/FXAAShader.js +88 -0
  49. package/scripts/external/three-old/render/FilmPass.js +60 -0
  50. package/scripts/external/three-old/render/FilmShader.js +104 -0
  51. package/scripts/external/three-old/render/ManualMSAARenderPass.js +168 -0
  52. package/scripts/external/three-old/render/MaskPass.js +97 -0
  53. package/scripts/external/three-old/render/OculusRenderPass.js +84 -0
  54. package/scripts/external/three-old/render/OculusRiftEffect.js +240 -0
  55. package/scripts/external/three-old/render/PortalRenderPass.js +166 -0
  56. package/scripts/external/three-old/render/RecordingPass.js +208 -0
  57. package/scripts/external/three-old/render/RenderPass.js +57 -0
  58. package/scripts/external/three-old/render/SSAOShader.js +259 -0
  59. package/scripts/external/three-old/render/SepiaShader.js +54 -0
  60. package/scripts/external/three-old/render/ShaderPass.js +66 -0
  61. package/scripts/external/three-old/render/VREffect.js +482 -0
  62. package/scripts/external/three-old/shimthree.js +23 -0
  63. package/scripts/external/three-old/stats.js +6 -0
  64. package/scripts/external/three-old/three-88dev.js +45004 -0
  65. package/scripts/external/three-old/three-backgroundoptimization.js +44432 -0
  66. package/scripts/external/three-old/three-updates.js +44735 -0
  67. package/scripts/external/three-old/three-working.js +44719 -0
  68. package/scripts/external/three-old/three.js +44431 -0
  69. package/scripts/external/three-old/threex.rendererstats.js +66 -0
  70. package/scripts/external/three-old/tween.js +13 -0
  71. package/scripts/external/webvr-polyfill-new.js +3497 -0
  72. package/scripts/external/webvr-polyfill-newest.js +3491 -0
  73. package/scripts/external/webvr-polyfill-old.js +6337 -0
  74. package/scripts/geometries.js +2 -2
  75. package/scripts/math.js +6 -6
  76. package/scripts/systems/admin.js +1 -1
  77. package/scripts/systems/controls.js +6 -4
  78. package/scripts/systems/physics.js +10 -10
  79. package/scripts/systems/render.js +58 -20
  80. package/scripts/systems/render2.js +38 -0
  81. package/scripts/things/camera.js +6 -1
  82. package/scripts/things/generic-trackedvectors.js +1875 -0
  83. package/scripts/things/generic.js +3 -4
  84. package/scripts/things/label2d.js +1 -1
  85. package/scripts/things/leapmotion.js +6 -6
  86. package/scripts/things/menu.js +1 -1
  87. package/scripts/things/player-bak.js +638 -0
  88. package/scripts/things/player.js +28 -10
  89. package/scripts/things/skysphere.js +1 -1
  90. package/scripts/things/terrain.js +1 -1
  91. package/scripts/things/text.js +1 -1
@@ -0,0 +1,2513 @@
1
+ // Copyright (c) 2013 Fabrice Robinet
2
+ // All rights reserved.
3
+ //
4
+ // Redistribution and use in source and binary forms, with or without
5
+ // modification, are permitted provided that the following conditions are met:
6
+ //
7
+ // * Redistributions of source code must retain the above copyright
8
+ // notice, this list of conditions and the following disclaimer.
9
+ // * Redistributions in binary form must reproduce the above copyright
10
+ // notice, this list of conditions and the following disclaimer in the
11
+ // documentation and/or other materials provided with the distribution.
12
+ //
13
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14
+ // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
+ // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16
+ // ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
17
+ // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
+ // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
+
24
+ /*
25
+ The Abstract Loader has two modes:
26
+ #1: [static] load all the JSON at once [as of now]
27
+ #2: [stream] stream and parse JSON progressively [not yet supported]
28
+
29
+ Whatever is the mechanism used to parse the JSON (#1 or #2),
30
+ The loader starts by resolving the paths to binaries and referenced json files (by replace the value of the path property with an absolute path if it was relative).
31
+
32
+ In case #1: it is guaranteed to call the concrete loader implementation methods in a order that solves the dependencies between the entries.
33
+ only the nodes requires an extra pass to set up the hirerarchy.
34
+ In case #2: the concrete implementation will have to solve the dependencies. no order is guaranteed.
35
+
36
+ When case #1 is used the followed dependency order is:
37
+
38
+ scenes -> nodes -> meshes -> materials -> techniques -> shaders
39
+ -> buffers
40
+ -> cameras
41
+ -> lights
42
+
43
+ The readers starts with the leafs, i.e:
44
+ shaders, techniques, materials, meshes, buffers, cameras, lights, nodes, scenes
45
+
46
+ For each called handle method called the client should return true if the next handle can be call right after returning,
47
+ or false if a callback on client side will notify the loader that the next handle method can be called.
48
+
49
+ */
50
+ var global = window;
51
+ (function (root, factory) {
52
+ if (typeof exports === 'object') {
53
+ // Node. Does not work with strict CommonJS, but
54
+ // only CommonJS-like enviroments that support module.exports,
55
+ // like Node.
56
+ factory(module.exports);
57
+ } else if (typeof define === 'function' && define.amd) {
58
+ // AMD. Register as an anonymous module.
59
+ define([], function () {
60
+ return factory(root);
61
+ });
62
+ } else {
63
+ // Browser globals
64
+ factory(root);
65
+ }
66
+ }(this, function (root) {
67
+ "use strict";
68
+
69
+ var categoriesDepsOrder = ["buffers", "bufferViews", "images", "videos", "samplers", "textures", "shaders", "programs", "techniques", "materials", "accessors", "meshes", "cameras", "lights", "skins", "nodes", "scenes", "animations"];
70
+
71
+ var glTFParser = Object.create(Object.prototype, {
72
+
73
+ _rootDescription: { value: null, writable: true },
74
+
75
+ rootDescription: {
76
+ set: function(value) {
77
+ this._rootDescription = value;
78
+ },
79
+ get: function() {
80
+ return this._rootDescription;
81
+ }
82
+ },
83
+
84
+ baseURL: { value: null, writable: true },
85
+
86
+ //detect absolute path following the same protocol than window.location
87
+ _isAbsolutePath: {
88
+ value: function(path) {
89
+ var isAbsolutePathRegExp = new RegExp("^"+window.location.protocol, "i");
90
+
91
+ return path.match(isAbsolutePathRegExp) ? true : false;
92
+ }
93
+ },
94
+
95
+ resolvePathIfNeeded: {
96
+ value: function(path) {
97
+ if (this._isAbsolutePath(path)) {
98
+ return path;
99
+ }
100
+
101
+ return this.baseURL + path;
102
+ }
103
+ },
104
+
105
+ _resolvePathsForCategories: {
106
+ value: function(categories) {
107
+ categories.forEach( function(category) {
108
+ var descriptions = this.json[category];
109
+ if (descriptions) {
110
+ var descriptionKeys = Object.keys(descriptions);
111
+ descriptionKeys.forEach( function(descriptionKey) {
112
+ var description = descriptions[descriptionKey];
113
+ description.path = this.resolvePathIfNeeded(description.path);
114
+ }, this);
115
+ }
116
+ }, this);
117
+ }
118
+ },
119
+
120
+ _json: {
121
+ value: null,
122
+ writable: true
123
+ },
124
+
125
+ json: {
126
+ enumerable: true,
127
+ get: function() {
128
+ return this._json;
129
+ },
130
+ set: function(value) {
131
+ if (this._json !== value) {
132
+ this._json = value;
133
+ this._resolvePathsForCategories(["buffers", "shaders", "images", "videos"]);
134
+ }
135
+ }
136
+ },
137
+
138
+ _path: {
139
+ value: null,
140
+ writable: true
141
+ },
142
+
143
+ getEntryDescription: {
144
+ value: function (entryID, entryType) {
145
+ var entries = null;
146
+
147
+ var category = entryType;
148
+ entries = this.rootDescription[category];
149
+ if (!entries) {
150
+ console.log("ERROR:CANNOT find expected category named:"+category);
151
+ return null;
152
+ }
153
+
154
+ return entries ? entries[entryID] : null;
155
+ }
156
+ },
157
+
158
+ _stepToNextCategory: {
159
+ value: function() {
160
+ this._state.categoryIndex = this.getNextCategoryIndex(this._state.categoryIndex + 1);
161
+ if (this._state.categoryIndex !== -1) {
162
+ this._state.categoryState.index = 0;
163
+ return true;
164
+ }
165
+
166
+ return false;
167
+ }
168
+ },
169
+
170
+ _stepToNextDescription: {
171
+ enumerable: false,
172
+ value: function() {
173
+ var categoryState = this._state.categoryState;
174
+ var keys = categoryState.keys;
175
+ if (!keys) {
176
+ console.log("INCONSISTENCY ERROR");
177
+ return false;
178
+ }
179
+
180
+ categoryState.index++;
181
+ categoryState.keys = null;
182
+ if (categoryState.index >= keys.length) {
183
+ return this._stepToNextCategory();
184
+ }
185
+ return false;
186
+ }
187
+ },
188
+
189
+ hasCategory: {
190
+ value: function(category) {
191
+ return this.rootDescription[category] ? true : false;
192
+ }
193
+ },
194
+
195
+ _handleState: {
196
+ value: function() {
197
+
198
+ var methodForType = {
199
+ "buffers" : this.handleBuffer,
200
+ "bufferViews" : this.handleBufferView,
201
+ "shaders" : this.handleShader,
202
+ "programs" : this.handleProgram,
203
+ "techniques" : this.handleTechnique,
204
+ "materials" : this.handleMaterial,
205
+ "meshes" : this.handleMesh,
206
+ "cameras" : this.handleCamera,
207
+ "lights" : this.handleLight,
208
+ "nodes" : this.handleNode,
209
+ "scenes" : this.handleScene,
210
+ "images" : this.handleImage,
211
+ "animations" : this.handleAnimation,
212
+ "accessors" : this.handleAccessor,
213
+ "skins" : this.handleSkin,
214
+ "samplers" : this.handleSampler,
215
+ "textures" : this.handleTexture,
216
+ "videos" : this.handleVideo
217
+
218
+ };
219
+
220
+ var success = true;
221
+ while (this._state.categoryIndex !== -1) {
222
+ var category = categoriesDepsOrder[this._state.categoryIndex];
223
+ var categoryState = this._state.categoryState;
224
+ var keys = categoryState.keys;
225
+ if (!keys) {
226
+ categoryState.keys = keys = Object.keys(this.rootDescription[category]);
227
+ if (keys) {
228
+ if (keys.length == 0) {
229
+ this._stepToNextDescription();
230
+ continue;
231
+ }
232
+ }
233
+ }
234
+
235
+ var type = category;
236
+ var entryID = keys[categoryState.index];
237
+ var description = this.getEntryDescription(entryID, type);
238
+ if (!description) {
239
+ if (this.handleError) {
240
+ this.handleError("INCONSISTENCY ERROR: no description found for entry "+entryID);
241
+ success = false;
242
+ break;
243
+ }
244
+ } else {
245
+
246
+ if (methodForType[type]) {
247
+ if (methodForType[type].call(this, entryID, description, this._state.userInfo) === false) {
248
+ success = false;
249
+ break;
250
+ }
251
+ }
252
+
253
+ this._stepToNextDescription();
254
+ }
255
+ }
256
+
257
+ if (this.handleLoadCompleted) {
258
+ this.handleLoadCompleted(success);
259
+ }
260
+
261
+ }
262
+ },
263
+
264
+ _loadJSONIfNeeded: {
265
+ enumerable: true,
266
+ value: function(callback) {
267
+ var self = this;
268
+ //FIXME: handle error
269
+ if (!this._json) {
270
+ var jsonPath = this._path;
271
+ var i = jsonPath.lastIndexOf("/");
272
+ this.baseURL = (i !== 0) ? jsonPath.substring(0, i + 1) : '';
273
+ var jsonfile = new XMLHttpRequest();
274
+ jsonfile.open("GET", jsonPath, true);
275
+ jsonfile.addEventListener( 'load', function ( event ) {
276
+ self.json = JSON.parse(jsonfile.responseText);
277
+ if (callback) {
278
+ callback(self.json);
279
+ }
280
+ }, false );
281
+ jsonfile.send(null);
282
+ } else {
283
+ if (callback) {
284
+ callback(this.json);
285
+ }
286
+ }
287
+ }
288
+ },
289
+
290
+ /* load JSON and assign it as description to the reader */
291
+ _buildLoader: {
292
+ value: function(callback) {
293
+ var self = this;
294
+ function JSONReady(json) {
295
+ self.rootDescription = json;
296
+ if (callback)
297
+ callback(this);
298
+ }
299
+
300
+ this._loadJSONIfNeeded(JSONReady);
301
+ }
302
+ },
303
+
304
+ _state: { value: null, writable: true },
305
+
306
+ _getEntryType: {
307
+ value: function(entryID) {
308
+ var rootKeys = categoriesDepsOrder;
309
+ for (var i = 0 ; i < rootKeys.length ; i++) {
310
+ var rootValues = this.rootDescription[rootKeys[i]];
311
+ if (rootValues) {
312
+ return rootKeys[i];
313
+ }
314
+ }
315
+ return null;
316
+ }
317
+ },
318
+
319
+ getNextCategoryIndex: {
320
+ value: function(currentIndex) {
321
+ for (var i = currentIndex ; i < categoriesDepsOrder.length ; i++) {
322
+ if (this.hasCategory(categoriesDepsOrder[i])) {
323
+ return i;
324
+ }
325
+ }
326
+
327
+ return -1;
328
+ }
329
+ },
330
+
331
+ load: {
332
+ enumerable: true,
333
+ value: function(userInfo, options) {
334
+ var self = this;
335
+ this._buildLoader(function loaderReady(reader) {
336
+ var startCategory = self.getNextCategoryIndex.call(self,0);
337
+ if (startCategory !== -1) {
338
+ self._state = { "userInfo" : userInfo,
339
+ "options" : options,
340
+ "categoryIndex" : startCategory,
341
+ "categoryState" : { "index" : "0" } };
342
+ self._handleState();
343
+ }
344
+ });
345
+ }
346
+ },
347
+
348
+ initWithPath: {
349
+ value: function(path) {
350
+ this._path = path;
351
+ this._json = null;
352
+ return this;
353
+ }
354
+ },
355
+
356
+ //this is meant to be global and common for all instances
357
+ _knownURLs: { writable: true, value: {} },
358
+
359
+ //to be invoked by subclass, so that ids can be ensured to not overlap
360
+ loaderContext: {
361
+ value: function() {
362
+ if (typeof this._knownURLs[this._path] === "undefined") {
363
+ this._knownURLs[this._path] = Object.keys(this._knownURLs).length;
364
+ }
365
+ return "__" + this._knownURLs[this._path];
366
+ }
367
+ },
368
+
369
+ initWithJSON: {
370
+ value: function(json, baseURL) {
371
+ this.json = json;
372
+ this.baseURL = baseURL;
373
+ if (!baseURL) {
374
+ console.log("WARNING: no base URL passed to Reader:initWithJSON");
375
+ }
376
+ return this;
377
+ }
378
+ }
379
+
380
+ });
381
+
382
+ if(root) {
383
+ root.glTFParser = glTFParser;
384
+ }
385
+
386
+ return glTFParser;
387
+
388
+ }));
389
+ /**
390
+ * @author Tony Parisi / http://www.tonyparisi.com/
391
+ */
392
+
393
+
394
+ THREE.glTFLoader = function (showStatus) {
395
+ this.useBufferGeometry = (THREE.glTFLoader.useBufferGeometry !== undefined ) ?
396
+ THREE.glTFLoader.useBufferGeometry : true;
397
+ this.meshesRequested = 0;
398
+ this.meshesLoaded = 0;
399
+ this.pendingMeshes = [];
400
+ this.animationsRequested = 0;
401
+ this.animationsLoaded = 0;
402
+ this.animations = [];
403
+ this.shadersRequested = 0;
404
+ this.shadersLoaded = 0;
405
+ this.shaders = {};
406
+ THREE.Loader.call( this, showStatus );
407
+ }
408
+
409
+ THREE.glTFLoader.prototype = new THREE.Loader();
410
+ THREE.glTFLoader.prototype.constructor = THREE.glTFLoader;
411
+
412
+ THREE.glTFLoader.prototype.load = function( url, callback ) {
413
+
414
+ var theLoader = this;
415
+ // Utilities
416
+
417
+ function RgbArraytoHex(colorArray) {
418
+ if(!colorArray) return 0xFFFFFFFF;
419
+ var r = Math.floor(colorArray[0] * 255),
420
+ g = Math.floor(colorArray[1] * 255),
421
+ b = Math.floor(colorArray[2] * 255),
422
+ a = 255;
423
+
424
+ var color = (a << 24) + (r << 16) + (g << 8) + b;
425
+
426
+ return color;
427
+ }
428
+
429
+ function convertAxisAngleToQuaternion(rotations, count)
430
+ {
431
+ var q = new THREE.Quaternion;
432
+ var axis = new THREE.Vector3;
433
+ var euler = new THREE.Vector3;
434
+
435
+ var i;
436
+ for (i = 0; i < count; i++) {
437
+ axis.set(rotations[i * 4], rotations[i * 4 + 1],
438
+ rotations[i * 4 + 2]).normalize();
439
+ var angle = rotations[i * 4 + 3];
440
+ q.setFromAxisAngle(axis, angle);
441
+ rotations[i * 4] = q.x;
442
+ rotations[i * 4 + 1] = q.y;
443
+ rotations[i * 4 + 2] = q.z;
444
+ rotations[i * 4 + 3] = q.w;
445
+ }
446
+ }
447
+
448
+ function componentsPerElementForGLType(glType) {
449
+ switch (glType) {
450
+ case WebGLRenderingContext.FLOAT :
451
+ case WebGLRenderingContext.UNSIGNED_BYTE :
452
+ case WebGLRenderingContext.UNSIGNED_SHORT :
453
+ return 1;
454
+ case WebGLRenderingContext.FLOAT_VEC2 :
455
+ return 2;
456
+ case WebGLRenderingContext.FLOAT_VEC3 :
457
+ return 3;
458
+ case WebGLRenderingContext.FLOAT_VEC4 :
459
+ return 4;
460
+ case WebGLRenderingContext.FLOAT_MAT4 :
461
+ return 16;
462
+ default:
463
+ return null;
464
+ }
465
+ }
466
+
467
+
468
+ function LoadTexture(src) {
469
+ if(!src) { return null; }
470
+ return THREE.ImageUtils.loadTexture(src);
471
+ }
472
+
473
+ // Geometry processing
474
+
475
+ var ClassicGeometry = function() {
476
+
477
+ if (theLoader.useBufferGeometry) {
478
+ this.geometry = new THREE.BufferGeometry;
479
+ }
480
+ else {
481
+ this.geometry = new THREE.Geometry;
482
+ }
483
+ this.totalAttributes = 0;
484
+ this.loadedAttributes = 0;
485
+ this.indicesLoaded = false;
486
+ this.finished = false;
487
+
488
+ this.onload = null;
489
+
490
+ this.uvs = null;
491
+ this.indexArray = null;
492
+ };
493
+
494
+ ClassicGeometry.prototype.constructor = ClassicGeometry;
495
+
496
+ ClassicGeometry.prototype.buildArrayGeometry = function() {
497
+
498
+ // Build indexed mesh
499
+ var geometry = this.geometry;
500
+ var normals = geometry.normals;
501
+ var indexArray = this.indexArray;
502
+ var uvs = this.uvs;
503
+ var a, b, c;
504
+ var i, l;
505
+ var faceNormals = null;
506
+ var faceTexcoords = null;
507
+
508
+ for(i = 0, l = this.indexArray.length; i < l; i += 3) {
509
+ a = indexArray[i];
510
+ b = indexArray[i+1];
511
+ c = indexArray[i+2];
512
+ if(normals) {
513
+ faceNormals = [normals[a], normals[b], normals[c]];
514
+ }
515
+ geometry.faces.push( new THREE.Face3( a, b, c, faceNormals, null, null ) );
516
+ if(uvs) {
517
+ geometry.faceVertexUvs[0].push([ uvs[a], uvs[b], uvs[c] ]);
518
+ }
519
+ }
520
+
521
+ // Allow Three.js to calculate some values for us
522
+ geometry.computeBoundingBox();
523
+ geometry.computeBoundingSphere();
524
+ geometry.computeFaceNormals();
525
+ if(!normals) {
526
+ geometry.computeVertexNormals();
527
+ }
528
+
529
+ }
530
+
531
+ ClassicGeometry.prototype.buildBufferGeometry = function() {
532
+ // Build indexed mesh
533
+ var geometry = this.geometry;
534
+ geometry.attributes.index = {
535
+ itemSize: 1,
536
+ array : this.indexArray
537
+ };
538
+
539
+ var offset = {
540
+ start: 0,
541
+ index: 0,
542
+ count: this.indexArray.length
543
+ };
544
+
545
+ geometry.offsets.push( offset );
546
+
547
+ geometry.computeBoundingSphere();
548
+ }
549
+
550
+ ClassicGeometry.prototype.checkFinished = function() {
551
+ if(this.indexArray && this.loadedAttributes === this.totalAttributes) {
552
+
553
+ if (theLoader.useBufferGeometry) {
554
+ this.buildBufferGeometry();
555
+ }
556
+ else {
557
+ this.buildArrayGeometry();
558
+ }
559
+
560
+ this.finished = true;
561
+
562
+ if(this.onload) {
563
+ this.onload();
564
+ }
565
+ }
566
+ };
567
+
568
+ // Delegate for processing index buffers
569
+ var IndicesDelegate = function() {};
570
+
571
+ IndicesDelegate.prototype.handleError = function(errorCode, info) {
572
+ // FIXME: report error
573
+ console.log("ERROR(IndicesDelegate):"+errorCode+":"+info);
574
+ };
575
+
576
+ IndicesDelegate.prototype.convert = function(resource, ctx) {
577
+ return new Uint16Array(resource, 0, ctx.indices.count);
578
+ };
579
+
580
+ IndicesDelegate.prototype.resourceAvailable = function(glResource, ctx) {
581
+ var geometry = ctx.geometry;
582
+ geometry.indexArray = glResource;
583
+ geometry.checkFinished();
584
+ return true;
585
+ };
586
+
587
+ var indicesDelegate = new IndicesDelegate();
588
+
589
+ var IndicesContext = function(indices, geometry) {
590
+ this.indices = indices;
591
+ this.geometry = geometry;
592
+ };
593
+
594
+ // Delegate for processing vertex attribute buffers
595
+ var VertexAttributeDelegate = function() {};
596
+
597
+ VertexAttributeDelegate.prototype.handleError = function(errorCode, info) {
598
+ // FIXME: report error
599
+ console.log("ERROR(VertexAttributeDelegate):"+errorCode+":"+info);
600
+ };
601
+
602
+ VertexAttributeDelegate.prototype.convert = function(resource, ctx) {
603
+ return resource;
604
+ };
605
+
606
+
607
+
608
+ VertexAttributeDelegate.prototype.arrayResourceAvailable = function(glResource, ctx) {
609
+ var geom = ctx.geometry;
610
+ var attribute = ctx.attribute;
611
+ var semantic = ctx.semantic;
612
+ var floatArray;
613
+ var i, l;
614
+ //FIXME: Float32 is assumed here, but should be checked.
615
+
616
+ if(semantic == "POSITION") {
617
+ // TODO: Should be easy to take strides into account here
618
+ floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
619
+ for(i = 0, l = floatArray.length; i < l; i += 3) {
620
+ geom.geometry.vertices.push( new THREE.Vector3( floatArray[i], floatArray[i+1], floatArray[i+2] ) );
621
+ }
622
+ } else if(semantic == "NORMAL") {
623
+ geom.geometry.normals = [];
624
+ floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
625
+ for(i = 0, l = floatArray.length; i < l; i += 3) {
626
+ geom.geometry.normals.push( new THREE.Vector3( floatArray[i], floatArray[i+1], floatArray[i+2] ) );
627
+ }
628
+ } else if ((semantic == "TEXCOORD_0") || (semantic == "TEXCOORD" )) {
629
+ geom.uvs = [];
630
+ floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
631
+ for(i = 0, l = floatArray.length; i < l; i += 2) {
632
+ geom.uvs.push( new THREE.Vector2( floatArray[i], 1.0 - floatArray[i+1] ) );
633
+ }
634
+ }
635
+ else if (semantic == "WEIGHT") {
636
+ nComponents = componentsPerElementForGLType(attribute.type);
637
+ floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
638
+ for(i = 0, l = floatArray.length; i < l; i += 4) {
639
+ geom.geometry.skinWeights.push( new THREE.Vector4( floatArray[i], floatArray[i+1], floatArray[i+2], floatArray[i+3] ) );
640
+ }
641
+ }
642
+ else if (semantic == "JOINT") {
643
+ nComponents = componentsPerElementForGLType(attribute.type);
644
+ floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
645
+ for(i = 0, l = floatArray.length; i < l; i += 4) {
646
+ geom.geometry.skinIndices.push( new THREE.Vector4( floatArray[i], floatArray[i+1], floatArray[i+2], floatArray[i+3] ) );
647
+ }
648
+ }
649
+ }
650
+
651
+ VertexAttributeDelegate.prototype.bufferResourceAvailable = function(glResource, ctx) {
652
+ var geom = ctx.geometry;
653
+ var attribute = ctx.attribute;
654
+ var semantic = ctx.semantic;
655
+ var floatArray;
656
+ var i, l;
657
+ var nComponents;
658
+ //FIXME: Float32 is assumed here, but should be checked.
659
+
660
+ if(semantic == "POSITION") {
661
+ // TODO: Should be easy to take strides into account here
662
+ floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
663
+ geom.geometry.attributes.position = {
664
+ itemSize: 3,
665
+ array : floatArray
666
+ };
667
+ } else if(semantic == "NORMAL") {
668
+ floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
669
+ geom.geometry.attributes.normal = {
670
+ itemSize: 3,
671
+ array : floatArray
672
+ };
673
+ } else if ((semantic == "TEXCOORD_0") || (semantic == "TEXCOORD" )) {
674
+
675
+ nComponents = componentsPerElementForGLType(attribute.type);
676
+ floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
677
+ // N.B.: flip Y value... should we just set texture.flipY everywhere?
678
+ for (i = 0; i < floatArray.length / 2; i++) {
679
+ floatArray[i*2+1] = 1.0 - floatArray[i*2+1];
680
+ }
681
+ geom.geometry.attributes.uv = {
682
+ itemSize: nComponents,
683
+ array : floatArray
684
+ };
685
+ }
686
+ else if (semantic == "WEIGHT") {
687
+ nComponents = componentsPerElementForGLType(attribute.type);
688
+ floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
689
+ geom.geometry.attributes.skinWeight = {
690
+ itemSize: nComponents,
691
+ array : floatArray
692
+ };
693
+ }
694
+ else if (semantic == "JOINT") {
695
+ nComponents = componentsPerElementForGLType(attribute.type);
696
+ floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
697
+ geom.geometry.attributes.skinIndex = {
698
+ itemSize: nComponents,
699
+ array : floatArray
700
+ };
701
+ }
702
+ }
703
+
704
+ VertexAttributeDelegate.prototype.resourceAvailable = function(glResource, ctx) {
705
+ if (theLoader.useBufferGeometry) {
706
+ this.bufferResourceAvailable(glResource, ctx);
707
+ }
708
+ else {
709
+ this.arrayResourceAvailable(glResource, ctx);
710
+ }
711
+
712
+ var geom = ctx.geometry;
713
+ geom.loadedAttributes++;
714
+ geom.checkFinished();
715
+ return true;
716
+ };
717
+
718
+ var vertexAttributeDelegate = new VertexAttributeDelegate();
719
+
720
+ var VertexAttributeContext = function(attribute, semantic, geometry) {
721
+ this.attribute = attribute;
722
+ this.semantic = semantic;
723
+ this.geometry = geometry;
724
+ };
725
+
726
+ var Mesh = function() {
727
+ this.primitives = [];
728
+ this.materialsPending = [];
729
+ this.loadedGeometry = 0;
730
+ this.onCompleteCallbacks = [];
731
+ };
732
+
733
+ Mesh.prototype.addPrimitive = function(geometry, material) {
734
+
735
+ var self = this;
736
+ geometry.onload = function() {
737
+ self.loadedGeometry++;
738
+ self.checkComplete();
739
+ };
740
+
741
+ this.primitives.push({
742
+ geometry: geometry,
743
+ material: material,
744
+ mesh: null
745
+ });
746
+ };
747
+
748
+ Mesh.prototype.onComplete = function(callback) {
749
+ this.onCompleteCallbacks.push(callback);
750
+ this.checkComplete();
751
+ };
752
+
753
+ Mesh.prototype.checkComplete = function() {
754
+ var self = this;
755
+ if(this.onCompleteCallbacks.length && this.primitives.length == this.loadedGeometry) {
756
+ this.onCompleteCallbacks.forEach(function(callback) {
757
+ callback(self);
758
+ });
759
+ this.onCompleteCallbacks = [];
760
+ }
761
+ };
762
+
763
+ Mesh.prototype.attachToNode = function(threeNode) {
764
+ // Assumes that the geometry is complete
765
+ this.primitives.forEach(function(primitive) {
766
+ /*if(!primitive.mesh) {
767
+ primitive.mesh = new THREE.Mesh(primitive.geometry, primitive.material);
768
+ }*/
769
+ var material = primitive.material;
770
+ if (!(material instanceof THREE.Material)) {
771
+ material = theLoader.createShaderMaterial(material);
772
+ }
773
+
774
+ var threeMesh = new THREE.Mesh(primitive.geometry.geometry, material);
775
+ threeMesh.castShadow = true;
776
+ threeNode.add(threeMesh);
777
+ });
778
+ };
779
+
780
+ // Delayed-loaded material
781
+ var Material = function(params) {
782
+ this.params = params;
783
+ };
784
+
785
+ // Delegate for processing animation parameter buffers
786
+ var AnimationParameterDelegate = function() {};
787
+
788
+ AnimationParameterDelegate.prototype.handleError = function(errorCode, info) {
789
+ // FIXME: report error
790
+ console.log("ERROR(AnimationParameterDelegate):"+errorCode+":"+info);
791
+ };
792
+
793
+ AnimationParameterDelegate.prototype.convert = function(resource, ctx) {
794
+ var parameter = ctx.parameter;
795
+
796
+ var glResource = null;
797
+ switch (parameter.type) {
798
+ case WebGLRenderingContext.FLOAT :
799
+ case WebGLRenderingContext.FLOAT_VEC2 :
800
+ case WebGLRenderingContext.FLOAT_VEC3 :
801
+ case WebGLRenderingContext.FLOAT_VEC4 :
802
+ glResource = new Float32Array(resource, 0, parameter.count * componentsPerElementForGLType(parameter.type));
803
+ break;
804
+ default:
805
+ break;
806
+ }
807
+
808
+ return glResource;
809
+ };
810
+
811
+ AnimationParameterDelegate.prototype.resourceAvailable = function(glResource, ctx) {
812
+ var animation = ctx.animation;
813
+ var parameter = ctx.parameter;
814
+ parameter.data = glResource;
815
+ animation.handleParameterLoaded(parameter);
816
+ return true;
817
+ };
818
+
819
+ var animationParameterDelegate = new AnimationParameterDelegate();
820
+
821
+ var AnimationParameterContext = function(parameter, animation) {
822
+ this.parameter = parameter;
823
+ this.animation = animation;
824
+ };
825
+
826
+ // Animations
827
+ var Animation = function() {
828
+
829
+ // create Three.js keyframe here
830
+ this.totalParameters = 0;
831
+ this.loadedParameters = 0;
832
+ this.parameters = {};
833
+ this.finishedLoading = false;
834
+ this.onload = null;
835
+
836
+ };
837
+
838
+ Animation.prototype.constructor = Animation;
839
+
840
+ Animation.prototype.handleParameterLoaded = function(parameter) {
841
+ this.parameters[parameter.name] = parameter;
842
+ this.loadedParameters++;
843
+ this.checkFinished();
844
+ };
845
+
846
+ Animation.prototype.checkFinished = function() {
847
+ if(this.loadedParameters === this.totalParameters) {
848
+ // Build animation
849
+ this.finishedLoading = true;
850
+
851
+ if (this.onload) {
852
+ this.onload();
853
+ }
854
+ }
855
+ };
856
+
857
+ // Delegate for processing inverse bind matrices buffer
858
+ var InverseBindMatricesDelegate = function() {};
859
+
860
+ InverseBindMatricesDelegate.prototype.handleError = function(errorCode, info) {
861
+ // FIXME: report error
862
+ console.log("ERROR(InverseBindMatricesDelegate):"+errorCode+":"+info);
863
+ };
864
+
865
+ InverseBindMatricesDelegate.prototype.convert = function(resource, ctx) {
866
+ var parameter = ctx.parameter;
867
+
868
+ var glResource = null;
869
+ switch (parameter.type) {
870
+ case WebGLRenderingContext.FLOAT_MAT4 :
871
+ glResource = new Float32Array(resource, 0, parameter.count * componentsPerElementForGLType(parameter.type));
872
+ break;
873
+ default:
874
+ break;
875
+ }
876
+
877
+ return glResource;
878
+ };
879
+
880
+ InverseBindMatricesDelegate.prototype.resourceAvailable = function(glResource, ctx) {
881
+ var skin = ctx.skin;
882
+ skin.inverseBindMatrices = glResource;
883
+ return true;
884
+ };
885
+
886
+ var inverseBindMatricesDelegate = new InverseBindMatricesDelegate();
887
+
888
+ var InverseBindMatricesContext = function(param, skin) {
889
+ this.parameter = param;
890
+ this.skin = skin;
891
+ };
892
+
893
+ // Delegate for processing shaders from external files
894
+ var ShaderDelegate = function() {};
895
+
896
+ ShaderDelegate.prototype.handleError = function(errorCode, info) {
897
+ // FIXME: report error
898
+ console.log("ERROR(ShaderDelegate):"+errorCode+":"+info);
899
+ };
900
+
901
+ ShaderDelegate.prototype.convert = function(resource, ctx) {
902
+ return resource;
903
+ }
904
+
905
+ ShaderDelegate.prototype.resourceAvailable = function(data, ctx) {
906
+ theLoader.shadersLoaded++;
907
+ theLoader.shaders[ctx.id] = data;
908
+ return true;
909
+ };
910
+
911
+ var shaderDelegate = new ShaderDelegate();
912
+
913
+ var ShaderContext = function(id, path) {
914
+ this.id = id;
915
+ this.path = path;
916
+ };
917
+
918
+ // Resource management
919
+
920
+ var ResourceEntry = function(entryID, object, description) {
921
+ this.entryID = entryID;
922
+ this.object = object;
923
+ this.description = description;
924
+ };
925
+
926
+ var Resources = function() {
927
+ this._entries = {};
928
+ };
929
+
930
+ Resources.prototype.setEntry = function(entryID, object, description) {
931
+ if (!entryID) {
932
+ console.error("No EntryID provided, cannot store", description);
933
+ return;
934
+ }
935
+
936
+ if (this._entries[entryID]) {
937
+ console.warn("entry["+entryID+"] is being overwritten");
938
+ }
939
+
940
+ this._entries[entryID] = new ResourceEntry(entryID, object, description );
941
+ };
942
+
943
+ Resources.prototype.getEntry = function(entryID) {
944
+ return this._entries[entryID];
945
+ };
946
+
947
+ Resources.prototype.clearEntries = function() {
948
+ this._entries = {};
949
+ };
950
+
951
+ LoadDelegate = function() {
952
+ }
953
+
954
+ LoadDelegate.prototype.loadCompleted = function(callback, obj) {
955
+ callback.call(Window, obj);
956
+ }
957
+
958
+ // Loader
959
+
960
+ var ThreeGLTFLoader = Object.create(glTFParser, {
961
+
962
+ load: {
963
+ enumerable: true,
964
+ value: function(userInfo, options) {
965
+ this.resources = new Resources();
966
+ this.cameras = [];
967
+ this.lights = [];
968
+ this.animations = [];
969
+ this.joints = {};
970
+ this.skeltons = {};
971
+ THREE.GLTFLoaderUtils.init();
972
+ glTFParser.load.call(this, userInfo, options);
973
+ }
974
+ },
975
+
976
+ cameras: {
977
+ enumerable: true,
978
+ writable: true,
979
+ value : []
980
+ },
981
+
982
+ lights: {
983
+ enumerable: true,
984
+ writable: true,
985
+ value : []
986
+ },
987
+
988
+ animations: {
989
+ enumerable: true,
990
+ writable: true,
991
+ value : []
992
+ },
993
+
994
+ // Implement WebGLTFLoader handlers
995
+
996
+ handleBuffer: {
997
+ value: function(entryID, description, userInfo) {
998
+ this.resources.setEntry(entryID, null, description);
999
+ description.type = "ArrayBuffer";
1000
+ return true;
1001
+ }
1002
+ },
1003
+
1004
+ handleBufferView: {
1005
+ value: function(entryID, description, userInfo) {
1006
+ this.resources.setEntry(entryID, null, description);
1007
+
1008
+ var buffer = this.resources.getEntry(description.buffer);
1009
+ description.type = "ArrayBufferView";
1010
+
1011
+ var bufferViewEntry = this.resources.getEntry(entryID);
1012
+ bufferViewEntry.buffer = buffer;
1013
+ return true;
1014
+ }
1015
+ },
1016
+
1017
+ handleShader: {
1018
+ value: function(entryID, description, userInfo) {
1019
+ this.resources.setEntry(entryID, null, description);
1020
+ var shaderRequest = {
1021
+ id : entryID,
1022
+ path : description.path,
1023
+ };
1024
+
1025
+ var shaderContext = new ShaderContext(entryID, description.path);
1026
+
1027
+ theLoader.shadersRequested++;
1028
+ THREE.GLTFLoaderUtils.getFile(shaderRequest, shaderDelegate, shaderContext);
1029
+
1030
+ return true;
1031
+ }
1032
+ },
1033
+
1034
+ handleProgram: {
1035
+ value: function(entryID, description, userInfo) {
1036
+ this.resources.setEntry(entryID, null, description);
1037
+ return true;
1038
+ }
1039
+ },
1040
+
1041
+ handleTechnique: {
1042
+ value: function(entryID, description, userInfo) {
1043
+ this.resources.setEntry(entryID, null, description);
1044
+ return true;
1045
+ }
1046
+ },
1047
+
1048
+ createShaderMaterial : {
1049
+ value: function(material) {
1050
+
1051
+ var fragmentShader = theLoader.shaders[material.params.fragmentShader];
1052
+ if (!fragmentShader) {
1053
+ console.log("ERROR: Missing fragment shader definition:", material.params.fragmentShader);
1054
+ return new THREE.MeshPhongMaterial;
1055
+ }
1056
+
1057
+ var vertexShader = theLoader.shaders[material.params.vertexShader];
1058
+ if (!fragmentShader) {
1059
+ console.log("ERROR: Missing vertex shader definition:", material.params.vertexShader);
1060
+ return new THREE.MeshPhongMaterial;
1061
+ }
1062
+
1063
+ var uniforms = {};
1064
+ var shaderMaterial = new THREE.ShaderMaterial( {
1065
+
1066
+ fragmentShader: fragmentShader,
1067
+ vertexShader: vertexShader,
1068
+ uniforms: uniforms,
1069
+
1070
+ } );
1071
+
1072
+ return new THREE.MeshPhongMaterial(material.params);
1073
+ }
1074
+ },
1075
+
1076
+ createShaderParams : {
1077
+ value: function(materialId, values, params, instanceProgram) {
1078
+ var program = this.resources.getEntry(instanceProgram.program);
1079
+
1080
+ if (program) {
1081
+ params.fragmentShader = program.description.fragmentShader;
1082
+ params.vertexShader = program.description.vertexShader;
1083
+ params.attributes = instanceProgram.attributes;
1084
+ params.uniforms = instanceProgram.uniforms;
1085
+ }
1086
+ }
1087
+ },
1088
+
1089
+ threeJSMaterialType : {
1090
+ value: function(materialId, technique, values, params) {
1091
+
1092
+ var materialType = THREE.MeshPhongMaterial;
1093
+ var defaultPass = null;
1094
+ if (technique && technique.description && technique.description.passes)
1095
+ defaultPass = technique.description.passes.defaultPass;
1096
+
1097
+ if (defaultPass) {
1098
+ if (defaultPass.details && defaultPass.details.commonProfile) {
1099
+ var profile = technique.description.passes.defaultPass.details.commonProfile;
1100
+ if (profile)
1101
+ {
1102
+ switch (profile.lightingModel)
1103
+ {
1104
+ case 'Blinn' :
1105
+ case 'Phong' :
1106
+ materialType = THREE.MeshPhongMaterial;
1107
+ break;
1108
+
1109
+ case 'Lambert' :
1110
+ materialType = THREE.MeshLambertMaterial;
1111
+ break;
1112
+
1113
+ default :
1114
+ materialType = THREE.MeshBasicMaterial;
1115
+ break;
1116
+ }
1117
+
1118
+ if (profile.extras && profile.extras.doubleSided)
1119
+ {
1120
+ params.side = THREE.DoubleSide;
1121
+ }
1122
+ }
1123
+ }
1124
+ else if (defaultPass.instanceProgram) {
1125
+
1126
+ var instanceProgram = defaultPass.instanceProgram;
1127
+
1128
+ this.createShaderParams(materialId, values, params, instanceProgram);
1129
+
1130
+ var loadshaders = true;
1131
+
1132
+ if (loadshaders) {
1133
+ materialType = Material;
1134
+ }
1135
+ }
1136
+ }
1137
+
1138
+ var texturePath = null;
1139
+ var textureParams = null;
1140
+ var diffuse = values.diffuse;
1141
+ if (diffuse)
1142
+ {
1143
+ var texture = diffuse;
1144
+ if (texture) {
1145
+ var textureEntry = this.resources.getEntry(texture);
1146
+ if (textureEntry) {
1147
+ {
1148
+ var imageEntry = this.resources.getEntry(textureEntry.description.source);
1149
+ if (imageEntry) {
1150
+ texturePath = imageEntry.description.path;
1151
+ }
1152
+
1153
+ var samplerEntry = this.resources.getEntry(textureEntry.description.sampler);
1154
+ if (samplerEntry) {
1155
+ textureParams = samplerEntry.description;
1156
+ }
1157
+ }
1158
+ }
1159
+ }
1160
+ }
1161
+
1162
+ var texture = LoadTexture(texturePath);
1163
+ if (texture && textureParams) {
1164
+
1165
+ if (textureParams.wrapS == WebGLRenderingContext.REPEAT)
1166
+ texture.wrapS = THREE.RepeatWrapping;
1167
+
1168
+ if (textureParams.wrapT == WebGLRenderingContext.REPEAT)
1169
+ texture.wrapT = THREE.RepeatWrapping;
1170
+
1171
+ if (textureParams.magFilter == WebGLRenderingContext.LINEAR)
1172
+ texture.magFilter = THREE.LinearFilter;
1173
+
1174
+ // if (textureParams.minFilter == "LINEAR")
1175
+ // texture.minFilter = THREE.LinearFilter;
1176
+
1177
+ params.map = texture;
1178
+ }
1179
+
1180
+ var envMapPath = null;
1181
+ var envMapParams = null;
1182
+ var reflective = values.reflective;
1183
+ if (reflective)
1184
+ {
1185
+ var texture = reflective;
1186
+ if (texture) {
1187
+ var textureEntry = this.resources.getEntry(texture);
1188
+ if (textureEntry) {
1189
+ {
1190
+ var imageEntry = this.resources.getEntry(textureEntry.description.source);
1191
+ if (imageEntry) {
1192
+ envMapPath = imageEntry.description.path;
1193
+ }
1194
+
1195
+ var samplerEntry = this.resources.getEntry(textureEntry.description.sampler);
1196
+ if (samplerEntry) {
1197
+ envMapParams = samplerEntry.description;
1198
+ }
1199
+ }
1200
+ }
1201
+ }
1202
+ }
1203
+
1204
+ var texture = LoadTexture(envMapPath);
1205
+ if (texture && envMapParams) {
1206
+
1207
+ if (envMapParams.wrapS == WebGLRenderingContext.REPEAT)
1208
+ texture.wrapS = THREE.RepeatWrapping;
1209
+
1210
+ if (envMapParams.wrapT == WebGLRenderingContext.REPEAT)
1211
+ texture.wrapT = THREE.RepeatWrapping;
1212
+
1213
+ if (envMapParams.magFilter == WebGLRenderingContext.LINEAR)
1214
+ texture.magFilter = THREE.LinearFilter;
1215
+
1216
+ // if (envMapParams.minFilter == WebGLRenderingContext.LINEAR)
1217
+ // texture.minFilter = THREE.LinearFilter;
1218
+
1219
+ params.envMap = texture;
1220
+ }
1221
+
1222
+ var shininess = values.shininesss || values.shininess; // N.B.: typo in converter!
1223
+ if (shininess)
1224
+ {
1225
+ shininess = shininess;
1226
+ }
1227
+
1228
+ var diffuseColor = !texturePath ? diffuse : null;
1229
+ var opacity = 1.0;
1230
+ if (values.hasOwnProperty("transparency"))
1231
+ {
1232
+ var USE_A_ONE = true; // for now, hack because file format isn't telling us
1233
+ opacity = USE_A_ONE ? values.transparency : (1.0 - values.transparency);
1234
+ }
1235
+
1236
+ // if (diffuseColor) diffuseColor = [0, 1, 0];
1237
+
1238
+ params.color = RgbArraytoHex(diffuseColor);
1239
+ params.opacity = opacity;
1240
+ params.transparent = opacity < 1.0;
1241
+ // hack hack hack
1242
+ if (texturePath && texturePath.toLowerCase().indexOf(".png") != -1)
1243
+ params.transparent = true;
1244
+
1245
+ if (!(shininess === undefined))
1246
+ {
1247
+ params.shininess = shininess;
1248
+ }
1249
+
1250
+ if (!(values.ambient === undefined) && !(typeof(values.ambient) == 'string'))
1251
+ {
1252
+ params.ambient = RgbArraytoHex(values.ambient);
1253
+ }
1254
+
1255
+ if (!(values.emission === undefined))
1256
+ {
1257
+ params.emissive = RgbArraytoHex(values.emission);
1258
+ }
1259
+
1260
+ if (!(values.specular === undefined))
1261
+ {
1262
+ params.specular = RgbArraytoHex(values.specular);
1263
+ }
1264
+
1265
+ return materialType;
1266
+
1267
+ }
1268
+ },
1269
+
1270
+ handleMaterial: {
1271
+ value: function(entryID, description, userInfo) {
1272
+ //this should be rewritten using the meta datas that actually create the shader.
1273
+ //here we will infer what needs to be pass to Three.js by looking inside the technique parameters.
1274
+ var technique = this.resources.getEntry(description.instanceTechnique.technique);
1275
+ var materialParams = {};
1276
+ var values = description.instanceTechnique.values;
1277
+
1278
+ var materialType = this.threeJSMaterialType(entryID, technique, values, materialParams);
1279
+
1280
+ var material = new materialType(materialParams);
1281
+
1282
+ this.resources.setEntry(entryID, material, description);
1283
+
1284
+ return true;
1285
+ }
1286
+ },
1287
+
1288
+ handleMesh: {
1289
+ value: function(entryID, description, userInfo) {
1290
+ var mesh = new Mesh();
1291
+ this.resources.setEntry(entryID, mesh, description);
1292
+ var primitivesDescription = description.primitives;
1293
+ if (!primitivesDescription) {
1294
+ //FIXME: not implemented in delegate
1295
+ console.log("MISSING_PRIMITIVES for mesh:"+ entryID);
1296
+ return false;
1297
+ }
1298
+
1299
+ for (var i = 0 ; i < primitivesDescription.length ; i++) {
1300
+ var primitiveDescription = primitivesDescription[i];
1301
+
1302
+ if (primitiveDescription.primitive === WebGLRenderingContext.TRIANGLES) {
1303
+
1304
+ var geometry = new ClassicGeometry();
1305
+ var materialEntry = this.resources.getEntry(primitiveDescription.material);
1306
+
1307
+ mesh.addPrimitive(geometry, materialEntry.object);
1308
+
1309
+ var indices = this.resources.getEntry(primitiveDescription.indices);
1310
+ var bufferEntry = this.resources.getEntry(indices.description.bufferView);
1311
+ var indicesObject = {
1312
+ bufferView : bufferEntry,
1313
+ byteOffset : indices.description.byteOffset,
1314
+ count : indices.description.count,
1315
+ id : indices.entryID,
1316
+ type : indices.description.type
1317
+ };
1318
+
1319
+ var indicesContext = new IndicesContext(indicesObject, geometry);
1320
+ var alreadyProcessedIndices = THREE.GLTFLoaderUtils.getBuffer(indicesObject, indicesDelegate, indicesContext);
1321
+ /*if(alreadyProcessedIndices) {
1322
+ indicesDelegate.resourceAvailable(alreadyProcessedIndices, indicesContext);
1323
+ }*/
1324
+
1325
+ // Load Vertex Attributes
1326
+ var allAttributes = Object.keys(primitiveDescription.attributes);
1327
+ allAttributes.forEach( function(semantic) {
1328
+ geometry.totalAttributes++;
1329
+
1330
+ var attribute;
1331
+ var attributeID = primitiveDescription.attributes[semantic];
1332
+ var attributeEntry = this.resources.getEntry(attributeID);
1333
+ if (!attributeEntry) {
1334
+ //let's just use an anonymous object for the attribute
1335
+ attribute = description.attributes[attributeID];
1336
+ attribute.id = attributeID;
1337
+ this.resources.setEntry(attributeID, attribute, attribute);
1338
+
1339
+ var bufferEntry = this.resources.getEntry(attribute.bufferView);
1340
+ attributeEntry = this.resources.getEntry(attributeID);
1341
+
1342
+ } else {
1343
+ attribute = attributeEntry.object;
1344
+ attribute.id = attributeID;
1345
+ var bufferEntry = this.resources.getEntry(attribute.bufferView);
1346
+ }
1347
+
1348
+ var attributeObject = {
1349
+ bufferView : bufferEntry,
1350
+ byteOffset : attribute.byteOffset,
1351
+ byteStride : attribute.byteStride,
1352
+ count : attribute.count,
1353
+ max : attribute.max,
1354
+ min : attribute.min,
1355
+ type : attribute.type,
1356
+ id : attributeID
1357
+ };
1358
+
1359
+ var attribContext = new VertexAttributeContext(attributeObject, semantic, geometry);
1360
+
1361
+ var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer(attributeObject, vertexAttributeDelegate, attribContext);
1362
+ /*if(alreadyProcessedAttribute) {
1363
+ vertexAttributeDelegate.resourceAvailable(alreadyProcessedAttribute, attribContext);
1364
+ }*/
1365
+ }, this);
1366
+ }
1367
+ }
1368
+ return true;
1369
+ }
1370
+ },
1371
+
1372
+ handleCamera: {
1373
+ value: function(entryID, description, userInfo) {
1374
+ var camera;
1375
+ if (description.type == "perspective")
1376
+ {
1377
+ var znear = description.perspective.znear;
1378
+ var zfar = description.perspective.zfar;
1379
+ var yfov = description.perspective.yfov;
1380
+ var xfov = description.perspective.xfov;
1381
+ var aspect_ratio = description.perspective.aspect_ratio;
1382
+
1383
+ if (!aspect_ratio)
1384
+ aspect_ratio = 1;
1385
+
1386
+ if (yfov === undefined)
1387
+ {
1388
+ if (xfov)
1389
+ {
1390
+ // According to COLLADA spec...
1391
+ // aspect_ratio = xfov / yfov
1392
+ yfov = xfov / aspect_ratio;
1393
+ }
1394
+
1395
+ }
1396
+
1397
+ if (yfov)
1398
+ {
1399
+ camera = new THREE.PerspectiveCamera(yfov, aspect_ratio, znear, zfar);
1400
+ }
1401
+ }
1402
+ else
1403
+ {
1404
+ camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, znear, zfar );
1405
+ }
1406
+
1407
+ if (camera)
1408
+ {
1409
+ this.resources.setEntry(entryID, camera, description);
1410
+ }
1411
+
1412
+ return true;
1413
+ }
1414
+ },
1415
+
1416
+ handleLight: {
1417
+ value: function(entryID, description, userInfo) {
1418
+
1419
+ var light = null;
1420
+ var type = description.type;
1421
+ console.log('HANDLELIGHT', type, description[type]);
1422
+ if (type && description[type])
1423
+ {
1424
+ var lparams = description[type];
1425
+ var color = RgbArraytoHex(lparams.color);
1426
+
1427
+ switch (type) {
1428
+ case "directional" :
1429
+ light = new THREE.DirectionalLight(color);
1430
+ light.position.set(0, 0, 1);
1431
+ break;
1432
+
1433
+ case "point" :
1434
+ light = new THREE.PointLight(color);
1435
+ break;
1436
+
1437
+ case "spot" :
1438
+ light = new THREE.SpotLight(color);
1439
+ light.position.set(0, 0, 1);
1440
+ light.castShadow = true;
1441
+ light.shadowCameraVisible = true;
1442
+ light.shadowCameraNear = .5;
1443
+ light.shadowCameraFar = 100;
1444
+ light.shadowCameraFov = 120;
1445
+ light.shadowCameraWidth = 2048;
1446
+ light.shadowCameraHeight = 2048;
1447
+ break;
1448
+
1449
+ case "ambient" :
1450
+ light = new THREE.AmbientLight(color);
1451
+ break;
1452
+ }
1453
+ }
1454
+
1455
+ console.log('do light!', light);
1456
+ if (light)
1457
+ {
1458
+ this.resources.setEntry(entryID, light, description);
1459
+ }
1460
+
1461
+ return true;
1462
+ }
1463
+ },
1464
+
1465
+ addPendingMesh: {
1466
+ value: function(mesh, threeNode) {
1467
+ theLoader.pendingMeshes.push({
1468
+ mesh: mesh,
1469
+ node: threeNode
1470
+ });
1471
+ }
1472
+ },
1473
+
1474
+ handleNode: {
1475
+ value: function(entryID, description, userInfo) {
1476
+
1477
+ var threeNode = null;
1478
+ if (description.jointId) {
1479
+ threeNode = new THREE.Bone();
1480
+ threeNode.jointId = description.jointId;
1481
+ this.joints[description.jointId] = entryID;
1482
+ }
1483
+ else {
1484
+ threeNode = new THREE.Object3D();
1485
+ }
1486
+
1487
+ threeNode.name = description.name;
1488
+
1489
+ this.resources.setEntry(entryID, threeNode, description);
1490
+
1491
+ var m = description.matrix;
1492
+ if(m) {
1493
+ threeNode.applyMatrix(new THREE.Matrix4(
1494
+ m[0], m[4], m[8], m[12],
1495
+ m[1], m[5], m[9], m[13],
1496
+ m[2], m[6], m[10], m[14],
1497
+ m[3], m[7], m[11], m[15]
1498
+ ));
1499
+ threeNode.matrixAutoUpdate = false;
1500
+ threeNode.matrixWorldNeedsUpdate = true;
1501
+ }
1502
+ else {
1503
+ var t = description.translation;
1504
+ var r = description.rotation;
1505
+ var s = description.scale;
1506
+
1507
+ var position = t ? new THREE.Vector3(t[0], t[1], t[2]) :
1508
+ new THREE.Vector3;
1509
+ if (r) {
1510
+ convertAxisAngleToQuaternion(r, 1);
1511
+ }
1512
+ var rotation = r ? new THREE.Quaternion(r[0], r[1], r[2], r[3]) :
1513
+ new THREE.Quaternion;
1514
+ var scale = s ? new THREE.Vector3(s[0], s[1], s[2]) :
1515
+ new THREE.Vector3;
1516
+
1517
+ var matrix = new THREE.Matrix4;
1518
+ matrix.compose(position, rotation, scale);
1519
+ threeNode.matrixAutoUpdate = false;
1520
+ threeNode.matrixWorldNeedsUpdate = true;
1521
+ threeNode.applyMatrix(matrix);
1522
+ }
1523
+
1524
+ var self = this;
1525
+
1526
+ // Iterate through all node meshes and attach the appropriate objects
1527
+ //FIXME: decision needs to be made between these 2 ways, probably meshes will be discarded.
1528
+ var meshEntry;
1529
+ if (description.mesh) {
1530
+ meshEntry = this.resources.getEntry(description.mesh);
1531
+ theLoader.meshesRequested++;
1532
+ meshEntry.object.onComplete(function(mesh) {
1533
+ self.addPendingMesh(mesh, threeNode);
1534
+ theLoader.meshesLoaded++;
1535
+ theLoader.checkComplete();
1536
+ });
1537
+ }
1538
+
1539
+ if (description.meshes) {
1540
+ description.meshes.forEach( function(meshID) {
1541
+ meshEntry = this.resources.getEntry(meshID);
1542
+ theLoader.meshesRequested++;
1543
+ meshEntry.object.onComplete(function(mesh) {
1544
+ self.addPendingMesh(mesh, threeNode);
1545
+ theLoader.meshesLoaded++;
1546
+ theLoader.checkComplete();
1547
+ });
1548
+ }, this);
1549
+ }
1550
+
1551
+ if (description.instanceSkin) {
1552
+
1553
+ var skinEntry = this.resources.getEntry(description.instanceSkin.skin);
1554
+
1555
+ if (skinEntry) {
1556
+
1557
+ var skin = skinEntry.object;
1558
+ description.instanceSkin.skin = skin;
1559
+ threeNode.instanceSkin = description.instanceSkin;
1560
+
1561
+ var sources = description.instanceSkin.sources;
1562
+ skin.meshes = [];
1563
+ sources.forEach( function(meshID) {
1564
+ meshEntry = this.resources.getEntry(meshID);
1565
+ theLoader.meshesRequested++;
1566
+ meshEntry.object.onComplete(function(mesh) {
1567
+
1568
+ skin.meshes.push(mesh);
1569
+ theLoader.meshesLoaded++;
1570
+ theLoader.checkComplete();
1571
+ });
1572
+ }, this);
1573
+
1574
+ }
1575
+ }
1576
+
1577
+ if (description.camera) {
1578
+ var cameraEntry = this.resources.getEntry(description.camera);
1579
+ if (cameraEntry) {
1580
+ threeNode.add(cameraEntry.object);
1581
+ this.cameras.push(cameraEntry.object);
1582
+ }
1583
+ }
1584
+
1585
+ if (description.light) {
1586
+ var lightEntry = this.resources.getEntry(description.light);
1587
+ if (lightEntry) {
1588
+ threeNode.add(lightEntry.object);
1589
+ this.lights.push(lightEntry.object);
1590
+ }
1591
+ }
1592
+
1593
+ return true;
1594
+ }
1595
+ },
1596
+
1597
+ buildNodeHirerachy: {
1598
+ value: function(nodeEntryId, parentThreeNode) {
1599
+ var nodeEntry = this.resources.getEntry(nodeEntryId);
1600
+ var threeNode = nodeEntry.object;
1601
+ parentThreeNode.add(threeNode);
1602
+
1603
+ var children = nodeEntry.description.children;
1604
+ if (children) {
1605
+ children.forEach( function(childID) {
1606
+ this.buildNodeHirerachy(childID, threeNode);
1607
+ }, this);
1608
+ }
1609
+
1610
+ return threeNode;
1611
+ }
1612
+ },
1613
+
1614
+ buildSkin: {
1615
+ value: function(node) {
1616
+
1617
+ var skin = node.instanceSkin.skin;
1618
+ if (skin) {
1619
+ node.instanceSkin.skeletons.forEach(function(skeleton) {
1620
+ var nodeEntry = this.resources.getEntry(skeleton);
1621
+ if (nodeEntry) {
1622
+
1623
+ var rootSkeleton = nodeEntry.object;
1624
+
1625
+ var dobones = true;
1626
+
1627
+ var i, len = skin.meshes.length;
1628
+ for (i = 0; i < len; i++) {
1629
+ var mesh = skin.meshes[i];
1630
+ var threeMesh = null;
1631
+ mesh.primitives.forEach(function(primitive) {
1632
+
1633
+ var material = primitive.material;
1634
+ if (!(material instanceof THREE.Material)) {
1635
+ material = this.createShaderMaterial(material);
1636
+ }
1637
+
1638
+ threeMesh = new THREE.SkinnedMesh(primitive.geometry.geometry, material, false);
1639
+ threeMesh.add(rootSkeleton);
1640
+
1641
+ var geometry = primitive.geometry.geometry;
1642
+ var j;
1643
+ if (geometry.vertices) {
1644
+ for ( j = 0; j < geometry.vertices.length; j ++ ) {
1645
+ geometry.vertices[j].applyMatrix4( skin.bindShapeMatrix );
1646
+ }
1647
+ }
1648
+ else if (geometry.attributes.position) {
1649
+ var a = geometry.attributes.position.array;
1650
+ var v = new THREE.Vector3;
1651
+ for ( j = 0; j < a.length / 3; j++ ) {
1652
+ v.set(a[j * 3], a[j * 3 + 1], a[j * 3 + 2]);
1653
+ v.applyMatrix4( skin.bindShapeMatrix );
1654
+ a[j * 3] = v.x;
1655
+ a[j * 3 + 1] = v.y;
1656
+ a[j * 3 + 2] = v.z;
1657
+ }
1658
+ }
1659
+
1660
+ if (threeMesh && dobones) {
1661
+
1662
+ material.skinning = true;
1663
+
1664
+ threeMesh.boneInverses = [];
1665
+ var jointsIds = skin.jointsIds;
1666
+ var joints = [];
1667
+ var i, len = jointsIds.length;
1668
+ for (i = 0; i < len; i++) {
1669
+ var jointId = jointsIds[i];
1670
+ var nodeForJoint = this.joints[jointId];
1671
+ var joint = this.resources.getEntry(nodeForJoint).object;
1672
+ if (joint) {
1673
+
1674
+ joint.skin = threeMesh;
1675
+ joints.push(joint);
1676
+ threeMesh.bones.push(joint);
1677
+
1678
+ var m = skin.inverseBindMatrices;
1679
+ var mat = new THREE.Matrix4(
1680
+ m[i * 16 + 0], m[i * 16 + 4], m[i * 16 + 8], m[i * 16 + 12],
1681
+ m[i * 16 + 1], m[i * 16 + 5], m[i * 16 + 9], m[i * 16 + 13],
1682
+ m[i * 16 + 2], m[i * 16 + 6], m[i * 16 + 10], m[i * 16 + 14],
1683
+ m[i * 16 + 3], m[i * 16 + 7], m[i * 16 + 11], m[i * 16 + 15]
1684
+ );
1685
+ threeMesh.boneInverses.push(mat);
1686
+ threeMesh.pose();
1687
+
1688
+ } else {
1689
+ console.log("WARNING: jointId:"+jointId+" cannot be found in skeleton:"+skeleton);
1690
+ }
1691
+ }
1692
+ }
1693
+
1694
+ if (threeMesh) {
1695
+ threeMesh.castShadow = true;
1696
+ node.add(threeMesh);
1697
+ }
1698
+
1699
+ }, this);
1700
+ }
1701
+
1702
+ }
1703
+
1704
+
1705
+ }, this);
1706
+
1707
+ }
1708
+ }
1709
+ },
1710
+
1711
+ buildSkins: {
1712
+ value: function(node) {
1713
+
1714
+ if (node.instanceSkin)
1715
+ this.buildSkin(node);
1716
+
1717
+ var children = node.children;
1718
+ if (children) {
1719
+ children.forEach( function(child) {
1720
+ this.buildSkins(child);
1721
+ }, this);
1722
+ }
1723
+ }
1724
+ },
1725
+
1726
+ createMeshAnimations : {
1727
+ value : function(root) {
1728
+ this.buildSkins(root);
1729
+ }
1730
+ },
1731
+
1732
+ handleScene: {
1733
+ value: function(entryID, description, userInfo) {
1734
+
1735
+ if (!description.nodes) {
1736
+ console.log("ERROR: invalid file required nodes property is missing from scene");
1737
+ return false;
1738
+ }
1739
+
1740
+ description.nodes.forEach( function(nodeUID) {
1741
+ this.buildNodeHirerachy(nodeUID, userInfo.rootObj);
1742
+ }, this);
1743
+
1744
+ if (this.delegate) {
1745
+ this.delegate.loadCompleted(userInfo.callback, userInfo.rootObj);
1746
+ }
1747
+
1748
+ return true;
1749
+ }
1750
+ },
1751
+
1752
+ handleImage: {
1753
+ value: function(entryID, description, userInfo) {
1754
+ this.resources.setEntry(entryID, null, description);
1755
+ return true;
1756
+ }
1757
+ },
1758
+
1759
+ addNodeAnimationChannel : {
1760
+ value : function(name, channel, interp) {
1761
+ if (!this.nodeAnimationChannels)
1762
+ this.nodeAnimationChannels = {};
1763
+
1764
+ if (!this.nodeAnimationChannels[name]) {
1765
+ this.nodeAnimationChannels[name] = [];
1766
+ }
1767
+
1768
+ this.nodeAnimationChannels[name].push(interp);
1769
+ },
1770
+ },
1771
+
1772
+ createAnimations : {
1773
+ value : function() {
1774
+ for (var name in this.nodeAnimationChannels) {
1775
+ var nodeAnimationChannels = this.nodeAnimationChannels[name];
1776
+ var i, len = nodeAnimationChannels.length;
1777
+ //console.log(" animation channels for node " + name);
1778
+ //for (i = 0; i < len; i++) {
1779
+ // console.log(nodeAnimationChannels[i]);
1780
+ //}
1781
+ var anim = new THREE.glTFAnimation(nodeAnimationChannels);
1782
+ anim.name = "animation_" + name;
1783
+ this.animations.push(anim);
1784
+ }
1785
+ }
1786
+ },
1787
+
1788
+ buildAnimation: {
1789
+ value : function(animation) {
1790
+
1791
+ var interps = [];
1792
+ var i, len = animation.channels.length;
1793
+ for (i = 0; i < len; i++) {
1794
+
1795
+ var channel = animation.channels[i];
1796
+ var sampler = animation.samplers[channel.sampler];
1797
+ if (sampler) {
1798
+
1799
+ var input = animation.parameters[sampler.input];
1800
+ if (input && input.data) {
1801
+
1802
+ var output = animation.parameters[sampler.output];
1803
+ if (output && output.data) {
1804
+
1805
+ var target = channel.target;
1806
+ var node = this.resources.getEntry(target.id);
1807
+ if (node) {
1808
+
1809
+ var path = target.path;
1810
+
1811
+ if (path == "rotation")
1812
+ {
1813
+ convertAxisAngleToQuaternion(output.data, output.count);
1814
+ }
1815
+
1816
+ var interp = {
1817
+ keys : input.data,
1818
+ values : output.data,
1819
+ count : input.count,
1820
+ target : node.object,
1821
+ path : path,
1822
+ type : sampler.interpolation
1823
+ };
1824
+
1825
+ this.addNodeAnimationChannel(target.id, channel, interp);
1826
+ interps.push(interp);
1827
+ }
1828
+ }
1829
+ }
1830
+ }
1831
+ }
1832
+ }
1833
+ },
1834
+
1835
+ handleAnimation: {
1836
+ value: function(entryID, description, userInfo) {
1837
+
1838
+ var self = this;
1839
+ theLoader.animationsRequested++;
1840
+ var animation = new Animation();
1841
+ animation.name = entryID;
1842
+ animation.onload = function() {
1843
+ // self.buildAnimation(animation);
1844
+ theLoader.animationsLoaded++;
1845
+ theLoader.animations.push(animation);
1846
+ theLoader.checkComplete();
1847
+ };
1848
+
1849
+ animation.channels = description.channels;
1850
+ animation.samplers = description.samplers;
1851
+ this.resources.setEntry(entryID, animation, description);
1852
+ var parameters = description.parameters;
1853
+ if (!parameters) {
1854
+ //FIXME: not implemented in delegate
1855
+ console.log("MISSING_PARAMETERS for animation:"+ entryID);
1856
+ return false;
1857
+ }
1858
+
1859
+ // Load parameter buffers
1860
+ var params = Object.keys(parameters);
1861
+ params.forEach( function(param) {
1862
+
1863
+ animation.totalParameters++;
1864
+ var parameter = parameters[param];
1865
+ var accessor = this.resources.getEntry(parameter);
1866
+ if (!accessor)
1867
+ debugger;
1868
+ accessor = accessor.object;
1869
+ var bufferView = this.resources.getEntry(accessor.bufferView);
1870
+ var paramObject = {
1871
+ bufferView : bufferView,
1872
+ byteOffset : accessor.byteOffset,
1873
+ count : accessor.count,
1874
+ type : accessor.type,
1875
+ id : accessor.bufferView,
1876
+ name : param
1877
+ };
1878
+
1879
+ var paramContext = new AnimationParameterContext(paramObject, animation);
1880
+
1881
+ var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer(paramObject, animationParameterDelegate, paramContext);
1882
+ /*if(alreadyProcessedAttribute) {
1883
+ vertexAttributeDelegate.resourceAvailable(alreadyProcessedAttribute, attribContext);
1884
+ }*/
1885
+ }, this);
1886
+
1887
+ return true;
1888
+ }
1889
+ },
1890
+
1891
+ handleAccessor: {
1892
+ value: function(entryID, description, userInfo) {
1893
+ // Save attribute entry
1894
+ this.resources.setEntry(entryID, description, description);
1895
+ return true;
1896
+ }
1897
+ },
1898
+
1899
+ handleSkin: {
1900
+ value: function(entryID, description, userInfo) {
1901
+ // Save skin entry
1902
+
1903
+ var skin = {
1904
+ };
1905
+
1906
+ var m = description.bindShapeMatrix;
1907
+ skin.bindShapeMatrix = new THREE.Matrix4(
1908
+ m[0], m[4], m[8], m[12],
1909
+ m[1], m[5], m[9], m[13],
1910
+ m[2], m[6], m[10], m[14],
1911
+ m[3], m[7], m[11], m[15]
1912
+ );
1913
+
1914
+ skin.jointsIds = description.joints;
1915
+ var inverseBindMatricesDescription = description.inverseBindMatrices;
1916
+ skin.inverseBindMatricesDescription = inverseBindMatricesDescription;
1917
+ skin.inverseBindMatricesDescription.id = entryID + "_inverseBindMatrices";
1918
+
1919
+ var bufferEntry = this.resources.getEntry(inverseBindMatricesDescription.bufferView);
1920
+
1921
+ var paramObject = {
1922
+ bufferView : bufferEntry,
1923
+ byteOffset : inverseBindMatricesDescription.byteOffset,
1924
+ count : inverseBindMatricesDescription.count,
1925
+ type : inverseBindMatricesDescription.type,
1926
+ id : inverseBindMatricesDescription.bufferView,
1927
+ name : skin.inverseBindMatricesDescription.id
1928
+ };
1929
+
1930
+ var context = new InverseBindMatricesContext(paramObject, skin);
1931
+
1932
+ var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer(paramObject, inverseBindMatricesDelegate, context);
1933
+
1934
+ var bufferView = this.resources.getEntry(skin.inverseBindMatricesDescription.bufferView);
1935
+ skin.inverseBindMatricesDescription.bufferView =
1936
+ bufferView.object;
1937
+ this.resources.setEntry(entryID, skin, description);
1938
+ return true;
1939
+ }
1940
+ },
1941
+
1942
+ handleSampler: {
1943
+ value: function(entryID, description, userInfo) {
1944
+ // Save attribute entry
1945
+ this.resources.setEntry(entryID, description, description);
1946
+ return true;
1947
+ }
1948
+ },
1949
+
1950
+ handleTexture: {
1951
+ value: function(entryID, description, userInfo) {
1952
+ // Save attribute entry
1953
+ this.resources.setEntry(entryID, null, description);
1954
+ return true;
1955
+ }
1956
+ },
1957
+
1958
+ handleError: {
1959
+ value: function(msg) {
1960
+
1961
+ throw new Error(msg);
1962
+ return true;
1963
+ }
1964
+ },
1965
+
1966
+ _delegate: {
1967
+ value: new LoadDelegate,
1968
+ writable: true
1969
+ },
1970
+
1971
+ delegate: {
1972
+ enumerable: true,
1973
+ get: function() {
1974
+ return this._delegate;
1975
+ },
1976
+ set: function(value) {
1977
+ this._delegate = value;
1978
+ }
1979
+ }
1980
+ });
1981
+
1982
+
1983
+ // Loader
1984
+
1985
+ var Context = function(rootObj, callback) {
1986
+ this.rootObj = rootObj;
1987
+ this.callback = callback;
1988
+ };
1989
+
1990
+ var rootObj = new THREE.Object3D();
1991
+
1992
+ var self = this;
1993
+
1994
+ var loader = Object.create(ThreeGLTFLoader);
1995
+ loader.initWithPath(url);
1996
+ loader.load(new Context(rootObj,
1997
+ function(obj) {
1998
+ }),
1999
+ null);
2000
+
2001
+ this.loader = loader;
2002
+ this.callback = callback;
2003
+ this.rootObj = rootObj;
2004
+ return rootObj;
2005
+ }
2006
+
2007
+ THREE.glTFLoader.prototype.callLoadedCallback = function() {
2008
+ var result = {
2009
+ scene : this.rootObj,
2010
+ cameras : this.loader.cameras,
2011
+ animations : this.loader.animations,
2012
+ };
2013
+
2014
+ this.callback(result);
2015
+ }
2016
+
2017
+ THREE.glTFLoader.prototype.checkComplete = function() {
2018
+ if (this.meshesLoaded == this.meshesRequested
2019
+ && this.shadersLoaded == this.shadersRequested
2020
+ && this.animationsLoaded == this.animationsRequested)
2021
+ {
2022
+
2023
+ for (var i = 0; i < this.pendingMeshes.length; i++) {
2024
+ var pending = this.pendingMeshes[i];
2025
+ pending.mesh.attachToNode(pending.node);
2026
+ }
2027
+
2028
+ for (var i = 0; i < this.animationsLoaded; i++) {
2029
+ var animation = this.animations[i];
2030
+ this.loader.buildAnimation(animation);
2031
+ }
2032
+
2033
+ this.loader.createAnimations();
2034
+ this.loader.createMeshAnimations(this.rootObj);
2035
+
2036
+ this.callLoadedCallback();
2037
+ }
2038
+ }
2039
+
2040
+
2041
+
2042
+ /**
2043
+ * @author Tony Parisi / http://www.tonyparisi.com/
2044
+ */
2045
+
2046
+ THREE.GLTFLoaderUtils = Object.create(Object, {
2047
+
2048
+ // errors
2049
+ MISSING_DESCRIPTION: { value: "MISSING_DESCRIPTION" },
2050
+ INVALID_PATH: { value: "INVALID_PATH" },
2051
+ INVALID_TYPE: { value: "INVALID_TYPE" },
2052
+ XMLHTTPREQUEST_STATUS_ERROR: { value: "XMLHTTPREQUEST_STATUS_ERROR" },
2053
+ NOT_FOUND: { value: "NOT_FOUND" },
2054
+ // misc constants
2055
+ ARRAY_BUFFER: { value: "ArrayBuffer" },
2056
+
2057
+ _streams : { value:{}, writable: true },
2058
+
2059
+ _streamsStatus: { value: {}, writable: true },
2060
+
2061
+ _resources: { value: {}, writable: true },
2062
+
2063
+ _resourcesStatus: { value: {}, writable: true },
2064
+
2065
+ // initialization
2066
+ init: {
2067
+ value: function() {
2068
+ this._streams = {};
2069
+ this._streamsStatus = {};
2070
+ this._resources = {};
2071
+ this._resourcesStatus = {};
2072
+ }
2073
+ },
2074
+
2075
+ //manage entries
2076
+ _containsResource: {
2077
+ enumerable: false,
2078
+ value: function(resourceID) {
2079
+ return this._resources[resourceID] ? true : false;
2080
+ }
2081
+ },
2082
+
2083
+ _storeResource: {
2084
+ enumerable: false,
2085
+ value: function(resourceID, resource) {
2086
+ if (!resourceID) {
2087
+ console.log("ERROR: entry does not contain id, cannot store");
2088
+ return;
2089
+ }
2090
+
2091
+ if (this._containsResource[resourceID]) {
2092
+ console.log("WARNING: resource:"+resourceID+" is already stored, overriding");
2093
+ }
2094
+
2095
+ this._resources[resourceID] = resource;
2096
+ }
2097
+ },
2098
+
2099
+ _getResource: {
2100
+ enumerable: false,
2101
+ value: function(resourceID) {
2102
+ return this._resources[resourceID];
2103
+ }
2104
+ },
2105
+
2106
+ _loadStream: {
2107
+ value: function(path, type, delegate) {
2108
+ var self = this;
2109
+
2110
+ if (!type) {
2111
+ delegate.handleError(THREE.GLTFLoaderUtils.INVALID_TYPE, null);
2112
+ return;
2113
+ }
2114
+
2115
+ if (!path) {
2116
+ delegate.handleError(THREE.GLTFLoaderUtils.INVALID_PATH);
2117
+ return;
2118
+ }
2119
+
2120
+ var xhr = new XMLHttpRequest();
2121
+ xhr.open('GET', path, true);
2122
+ xhr.responseType = (type === this.ARRAY_BUFFER) ? "arraybuffer" : "text";
2123
+
2124
+ //if this is not specified, 1 "big blob" scenes fails to load.
2125
+ xhr.setRequestHeader("If-Modified-Since", "Sat, 01 Jan 1970 00:00:00 GMT");
2126
+ xhr.addEventListener( 'load', function ( event ) {
2127
+ delegate.streamAvailable(path, xhr.response);
2128
+ }, false );
2129
+ xhr.addEventListener( 'error', function ( event ) {
2130
+ delegate.handleError(THREE.GLTFLoaderUtils.XMLHTTPREQUEST_STATUS_ERROR, xhr.status);
2131
+ }, false );
2132
+ xhr.send(null);
2133
+ return xhr;
2134
+ }
2135
+ },
2136
+
2137
+ send: { value: 0, writable: true },
2138
+ requested: { value: 0, writable: true },
2139
+
2140
+ _handleRequest: {
2141
+ value: function(request) {
2142
+ var resourceStatus = this._resourcesStatus[request.id];
2143
+ if (resourceStatus)
2144
+ {
2145
+ this._resourcesStatus[request.id]++;
2146
+ }
2147
+ else
2148
+ {
2149
+ this._resourcesStatus[request.id] = 1;
2150
+ }
2151
+
2152
+ var streamStatus = this._streamsStatus[request.path];
2153
+ if (streamStatus && streamStatus.status === "loading" )
2154
+ {
2155
+ streamStatus.requests.push(request);
2156
+ return;
2157
+ }
2158
+
2159
+ this._streamsStatus[request.path] = { status : "loading", requests : [request] };
2160
+
2161
+ var self = this;
2162
+ var processResourceDelegate = {};
2163
+
2164
+ processResourceDelegate.streamAvailable = function(path, res_) {
2165
+ var streamStatus = self._streamsStatus[path];
2166
+ var requests = streamStatus.requests;
2167
+ requests.forEach( function(req_) {
2168
+ var subArray = res_.slice(req_.range[0], req_.range[1]);
2169
+ var convertedResource = req_.delegate.convert(subArray, req_.ctx);
2170
+ self._storeResource(req_.id, convertedResource);
2171
+ req_.delegate.resourceAvailable(convertedResource, req_.ctx);
2172
+ --self._resourcesStatus[req_.id];
2173
+
2174
+ }, this);
2175
+
2176
+ delete self._streamsStatus[path];
2177
+
2178
+ };
2179
+
2180
+ processResourceDelegate.handleError = function(errorCode, info) {
2181
+ request.delegate.handleError(errorCode, info);
2182
+ }
2183
+
2184
+ return this._loadStream(request.path, request.type, processResourceDelegate);
2185
+ }
2186
+ },
2187
+
2188
+
2189
+ _elementSizeForGLType: {
2190
+ value: function(glType) {
2191
+ switch (glType) {
2192
+ case WebGLRenderingContext.FLOAT :
2193
+ return Float32Array.BYTES_PER_ELEMENT;
2194
+ case WebGLRenderingContext.UNSIGNED_BYTE :
2195
+ return Uint8Array.BYTES_PER_ELEMENT;
2196
+ case WebGLRenderingContext.UNSIGNED_SHORT :
2197
+ return Uint16Array.BYTES_PER_ELEMENT;
2198
+ case WebGLRenderingContext.FLOAT_VEC2 :
2199
+ return Float32Array.BYTES_PER_ELEMENT * 2;
2200
+ case WebGLRenderingContext.FLOAT_VEC3 :
2201
+ return Float32Array.BYTES_PER_ELEMENT * 3;
2202
+ case WebGLRenderingContext.FLOAT_VEC4 :
2203
+ return Float32Array.BYTES_PER_ELEMENT * 4;
2204
+ case WebGLRenderingContext.FLOAT_MAT3 :
2205
+ return Float32Array.BYTES_PER_ELEMENT * 9;
2206
+ case WebGLRenderingContext.FLOAT_MAT4 :
2207
+ return Float32Array.BYTES_PER_ELEMENT * 16;
2208
+ default:
2209
+ return null;
2210
+ }
2211
+ }
2212
+ },
2213
+
2214
+ _handleWrappedBufferViewResourceLoading: {
2215
+ value: function(wrappedBufferView, delegate, ctx) {
2216
+ var bufferView = wrappedBufferView.bufferView;
2217
+ var buffer = bufferView.buffer;
2218
+ var byteOffset = wrappedBufferView.byteOffset + bufferView.description.byteOffset;
2219
+ var range = [byteOffset , (this._elementSizeForGLType(wrappedBufferView.type) * wrappedBufferView.count) + byteOffset];
2220
+
2221
+ return this._handleRequest({ "id" : wrappedBufferView.id,
2222
+ "range" : range,
2223
+ "type" : buffer.description.type,
2224
+ "path" : buffer.description.path,
2225
+ "delegate" : delegate,
2226
+ "ctx" : ctx }, null);
2227
+ }
2228
+ },
2229
+
2230
+ getBuffer: {
2231
+
2232
+ value: function(wrappedBufferView, delegate, ctx) {
2233
+
2234
+ var savedBuffer = this._getResource(wrappedBufferView.id);
2235
+ if (savedBuffer) {
2236
+ return savedBuffer;
2237
+ } else {
2238
+ this._handleWrappedBufferViewResourceLoading(wrappedBufferView, delegate, ctx);
2239
+ }
2240
+
2241
+ return null;
2242
+ }
2243
+ },
2244
+
2245
+ getFile: {
2246
+
2247
+ value: function(request, delegate, ctx) {
2248
+
2249
+ request.delegate = delegate;
2250
+ request.ctx = ctx;
2251
+
2252
+ return this._handleRequest({ "id" : request.id,
2253
+ "path" : request.path,
2254
+ "range" : [0],
2255
+ "type" : "text",
2256
+ "delegate" : delegate,
2257
+ "ctx" : ctx }, null);
2258
+
2259
+ return null;
2260
+ }
2261
+ },
2262
+ });
2263
+ /**
2264
+ * @author Tony Parisi / http://www.tonyparisi.com/
2265
+ */
2266
+
2267
+ THREE.glTFAnimator = ( function () {
2268
+
2269
+ var animators = [];
2270
+
2271
+ return {
2272
+ add : function(animator)
2273
+ {
2274
+ animators.push(animator);
2275
+ },
2276
+
2277
+ remove: function(animator)
2278
+ {
2279
+
2280
+ var i = animators.indexOf(animator);
2281
+
2282
+ if ( i !== -1 ) {
2283
+ animators.splice( i, 1 );
2284
+ }
2285
+ },
2286
+
2287
+ update : function()
2288
+ {
2289
+ for (i = 0; i < animators.length; i++)
2290
+ {
2291
+ animators[i].update();
2292
+ }
2293
+ },
2294
+ };
2295
+ })();
2296
+
2297
+ // Construction/initialization
2298
+ THREE.glTFAnimation = function(interps)
2299
+ {
2300
+ this.running = false;
2301
+ this.loop = false;
2302
+ this.duration = 0;
2303
+ this.startTime = 0;
2304
+ this.interps = [];
2305
+
2306
+ if (interps)
2307
+ {
2308
+ this.createInterpolators(interps);
2309
+ }
2310
+ }
2311
+
2312
+ THREE.glTFAnimation.prototype.createInterpolators = function(interps)
2313
+ {
2314
+ var i, len = interps.length;
2315
+ for (i = 0; i < len; i++)
2316
+ {
2317
+ var interp = new THREE.glTFInterpolator(interps[i]);
2318
+ this.interps.push(interp);
2319
+ this.duration = Math.max(this.duration, interp.duration);
2320
+ }
2321
+ }
2322
+
2323
+ // Start/stop
2324
+ THREE.glTFAnimation.prototype.play = function()
2325
+ {
2326
+ if (this.running)
2327
+ return;
2328
+
2329
+ this.startTime = Date.now();
2330
+ this.running = true;
2331
+ THREE.glTFAnimator.add(this);
2332
+ }
2333
+
2334
+ THREE.glTFAnimation.prototype.stop = function()
2335
+ {
2336
+ this.running = false;
2337
+ THREE.glTFAnimator.remove(this);
2338
+ }
2339
+
2340
+ // Update - drive key frame evaluation
2341
+ THREE.glTFAnimation.prototype.update = function()
2342
+ {
2343
+ if (!this.running)
2344
+ return;
2345
+
2346
+ var now = Date.now();
2347
+ var deltat = (now - this.startTime) / 1000;
2348
+ var t = deltat % this.duration;
2349
+ var nCycles = Math.floor(deltat / this.duration);
2350
+
2351
+ if (nCycles >= 1 && !this.loop)
2352
+ {
2353
+ this.running = false;
2354
+ var i, len = this.interps.length;
2355
+ for (i = 0; i < len; i++)
2356
+ {
2357
+ this.interps[i].interp(this.duration);
2358
+ }
2359
+ this.stop();
2360
+ return;
2361
+ }
2362
+ else
2363
+ {
2364
+ var i, len = this.interps.length;
2365
+ for (i = 0; i < len; i++)
2366
+ {
2367
+ this.interps[i].interp(t);
2368
+ }
2369
+ }
2370
+ }
2371
+
2372
+ //Interpolator class
2373
+ //Construction/initialization
2374
+ THREE.glTFInterpolator = function(param)
2375
+ {
2376
+ this.keys = param.keys;
2377
+ this.values = param.values;
2378
+ this.count = param.count;
2379
+ this.type = param.type;
2380
+ this.path = param.path;
2381
+ this.isRot = false;
2382
+
2383
+ var node = param.target;
2384
+ node.updateMatrix();
2385
+ node.matrixAutoUpdate = true;
2386
+ this.targetNode = node;
2387
+
2388
+ switch (param.path) {
2389
+ case "translation" :
2390
+ this.target = node.position;
2391
+ this.originalValue = node.position.clone();
2392
+ break;
2393
+ case "rotation" :
2394
+ this.target = node.quaternion;
2395
+ this.originalValue = node.quaternion.clone();
2396
+ this.isRot = true;
2397
+ break;
2398
+ case "scale" :
2399
+ this.target = node.scale;
2400
+ this.originalValue = node.scale.clone();
2401
+ break;
2402
+ }
2403
+
2404
+ this.duration = this.keys[this.count - 1];
2405
+
2406
+ this.vec1 = new THREE.Vector3;
2407
+ this.vec2 = new THREE.Vector3;
2408
+ this.vec3 = new THREE.Vector3;
2409
+ this.quat1 = new THREE.Quaternion;
2410
+ this.quat2 = new THREE.Quaternion;
2411
+ this.quat3 = new THREE.Quaternion;
2412
+ }
2413
+
2414
+ //Interpolation and tweening methods
2415
+ THREE.glTFInterpolator.prototype.interp = function(t)
2416
+ {
2417
+ var i, j;
2418
+ if (t == this.keys[0])
2419
+ {
2420
+ if (this.isRot) {
2421
+ this.quat3.set(this.values[0], this.values[1], this.values[2], this.values[3]);
2422
+ }
2423
+ else {
2424
+ this.vec3.set(this.values[0], this.values[1], this.values[2]);
2425
+ }
2426
+ }
2427
+ else if (t < this.keys[0])
2428
+ {
2429
+ if (this.isRot) {
2430
+ this.quat1.set(this.originalValue.x,
2431
+ this.originalValue.y,
2432
+ this.originalValue.z,
2433
+ this.originalValue.w);
2434
+ this.quat2.set(this.values[0],
2435
+ this.values[1],
2436
+ this.values[2],
2437
+ this.values[3]);
2438
+ THREE.Quaternion.slerp(this.quat1, this.quat2, this.quat3, t / this.keys[0]);
2439
+ }
2440
+ else {
2441
+ this.vec3.set(this.originalValue.x,
2442
+ this.originalValue.y,
2443
+ this.originalValue.z);
2444
+ this.vec2.set(this.values[0],
2445
+ this.values[1],
2446
+ this.values[2]);
2447
+
2448
+ this.vec3.lerp(this.vec2, t / this.keys[0]);
2449
+ }
2450
+ }
2451
+ else if (t >= this.keys[this.count - 1])
2452
+ {
2453
+ if (this.isRot) {
2454
+ this.quat3.set(this.values[(this.count - 1) * 4],
2455
+ this.values[(this.count - 1) * 4 + 1],
2456
+ this.values[(this.count - 1) * 4 + 2],
2457
+ this.values[(this.count - 1) * 4 + 3]);
2458
+ }
2459
+ else {
2460
+ this.vec3.set(this.values[(this.count - 1) * 3],
2461
+ this.values[(this.count - 1) * 3 + 1],
2462
+ this.values[(this.count - 1) * 3 + 2]);
2463
+ }
2464
+ }
2465
+ else
2466
+ {
2467
+ for (i = 0; i < this.count - 1; i++)
2468
+ {
2469
+ var key1 = this.keys[i];
2470
+ var key2 = this.keys[i + 1];
2471
+
2472
+ if (t >= key1 && t <= key2)
2473
+ {
2474
+ if (this.isRot) {
2475
+ this.quat1.set(this.values[i * 4],
2476
+ this.values[i * 4 + 1],
2477
+ this.values[i * 4 + 2],
2478
+ this.values[i * 4 + 3]);
2479
+ this.quat2.set(this.values[(i + 1) * 4],
2480
+ this.values[(i + 1) * 4 + 1],
2481
+ this.values[(i + 1) * 4 + 2],
2482
+ this.values[(i + 1) * 4 + 3]);
2483
+ THREE.Quaternion.slerp(this.quat1, this.quat2, this.quat3, (t - key1) / (key2 - key1));
2484
+ }
2485
+ else {
2486
+ this.vec3.set(this.values[i * 3],
2487
+ this.values[i * 3 + 1],
2488
+ this.values[i * 3 + 2]);
2489
+ this.vec2.set(this.values[(i + 1) * 3],
2490
+ this.values[(i + 1) * 3 + 1],
2491
+ this.values[(i + 1) * 3 + 2]);
2492
+
2493
+ this.vec3.lerp(this.vec2, (t - key1) / (key2 - key1));
2494
+ }
2495
+ }
2496
+ }
2497
+ }
2498
+
2499
+ if (this.target)
2500
+ {
2501
+ this.copyValue(this.target);
2502
+ }
2503
+ }
2504
+
2505
+ THREE.glTFInterpolator.prototype.copyValue = function(target) {
2506
+
2507
+ if (this.isRot) {
2508
+ target.copy(this.quat3);
2509
+ }
2510
+ else {
2511
+ target.copy(this.vec3);
2512
+ }
2513
+ }