glTFLoader.js 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554
  1. /**
  2. * @author Tony Parisi / http://www.tonyparisi.com/
  3. */
  4. THREE.glTFLoader = function () {
  5. this.meshesRequested = 0;
  6. this.meshesLoaded = 0;
  7. this.pendingMeshes = [];
  8. this.animationsRequested = 0;
  9. this.animationsLoaded = 0;
  10. this.animations = [];
  11. this.shadersRequested = 0;
  12. this.shadersLoaded = 0;
  13. this.shaders = {};
  14. THREE.Loader.call( this );
  15. };
  16. THREE.glTFLoader.prototype = Object.create( THREE.Loader.prototype );
  17. THREE.glTFLoader.prototype.constructor = THREE.glTFLoader;
  18. THREE.glTFLoader.prototype.load = function( url, callback ) {
  19. var theLoader = this;
  20. // Utilities
  21. function RgbArraytoHex(colorArray) {
  22. if (!colorArray) return 0xFFFFFFFF;
  23. var r = Math.floor(colorArray[0] * 255),
  24. g = Math.floor(colorArray[1] * 255),
  25. b = Math.floor(colorArray[2] * 255),
  26. a = 255;
  27. var color = (a << 24) + (r << 16) + (g << 8) + b;
  28. return color;
  29. }
  30. function convertAxisAngleToQuaternion(rotations, count)
  31. {
  32. var q = new THREE.Quaternion;
  33. var axis = new THREE.Vector3;
  34. var euler = new THREE.Vector3;
  35. var i;
  36. for (i = 0; i < count; i ++) {
  37. axis.set(rotations[i * 4], rotations[i * 4 + 1],
  38. rotations[i * 4 + 2]).normalize();
  39. var angle = rotations[i * 4 + 3];
  40. q.setFromAxisAngle(axis, angle);
  41. rotations[i * 4] = q.x;
  42. rotations[i * 4 + 1] = q.y;
  43. rotations[i * 4 + 2] = q.z;
  44. rotations[i * 4 + 3] = q.w;
  45. }
  46. }
  47. function componentsPerElementForGLType(glType) {
  48. switch (glType) {
  49. case WebGLRenderingContext.FLOAT :
  50. case WebGLRenderingContext.UNSIGNED_BYTE :
  51. case WebGLRenderingContext.UNSIGNED_SHORT :
  52. return 1;
  53. case WebGLRenderingContext.FLOAT_VEC2 :
  54. return 2;
  55. case WebGLRenderingContext.FLOAT_VEC3 :
  56. return 3;
  57. case WebGLRenderingContext.FLOAT_VEC4 :
  58. return 4;
  59. case WebGLRenderingContext.FLOAT_MAT4 :
  60. return 16;
  61. default:
  62. return null;
  63. }
  64. }
  65. function LoadTexture(src) {
  66. if (!src) { return null; }
  67. return THREE.ImageUtils.loadTexture(src);
  68. }
  69. // Geometry processing
  70. var ClassicGeometry = function() {
  71. this.geometry = new THREE.BufferGeometry();
  72. this.totalAttributes = 0;
  73. this.loadedAttributes = 0;
  74. this.indicesLoaded = false;
  75. this.finished = false;
  76. this.onload = null;
  77. this.uvs = null;
  78. this.indexArray = null;
  79. };
  80. ClassicGeometry.prototype.constructor = ClassicGeometry;
  81. ClassicGeometry.prototype.buildBufferGeometry = function() {
  82. // Build indexed mesh
  83. var geometry = this.geometry;
  84. geometry.addAttribute( 'index', new THREE.BufferAttribute( this.indexArray, 1 ) );
  85. geometry.addDrawCall( 0, this.indexArray.length );
  86. geometry.computeBoundingSphere();
  87. };
  88. ClassicGeometry.prototype.checkFinished = function() {
  89. if (this.indexArray && this.loadedAttributes === this.totalAttributes) {
  90. this.buildBufferGeometry();
  91. this.finished = true;
  92. if (this.onload) {
  93. this.onload();
  94. }
  95. }
  96. };
  97. // Delegate for processing index buffers
  98. var IndicesDelegate = function() {};
  99. IndicesDelegate.prototype.handleError = function(errorCode, info) {
  100. // FIXME: report error
  101. console.log("ERROR(IndicesDelegate):" + errorCode + ":" + info);
  102. };
  103. IndicesDelegate.prototype.convert = function(resource, ctx) {
  104. return new Uint16Array(resource, 0, ctx.indices.count);
  105. };
  106. IndicesDelegate.prototype.resourceAvailable = function(glResource, ctx) {
  107. var geometry = ctx.geometry;
  108. geometry.indexArray = glResource;
  109. geometry.checkFinished();
  110. return true;
  111. };
  112. var indicesDelegate = new IndicesDelegate();
  113. var IndicesContext = function(indices, geometry) {
  114. this.indices = indices;
  115. this.geometry = geometry;
  116. };
  117. // Delegate for processing vertex attribute buffers
  118. var VertexAttributeDelegate = function() {};
  119. VertexAttributeDelegate.prototype.handleError = function(errorCode, info) {
  120. // FIXME: report error
  121. console.log("ERROR(VertexAttributeDelegate):" + errorCode + ":" + info);
  122. };
  123. VertexAttributeDelegate.prototype.convert = function(resource, ctx) {
  124. return resource;
  125. };
  126. VertexAttributeDelegate.prototype.arrayResourceAvailable = function(glResource, ctx) {
  127. var geom = ctx.geometry;
  128. var attribute = ctx.attribute;
  129. var semantic = ctx.semantic;
  130. var floatArray;
  131. var i, l;
  132. //FIXME: Float32 is assumed here, but should be checked.
  133. if (semantic == "POSITION") {
  134. // TODO: Should be easy to take strides into account here
  135. floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
  136. for (i = 0, l = floatArray.length; i < l; i += 3) {
  137. geom.geometry.vertices.push( new THREE.Vector3( floatArray[i], floatArray[i + 1], floatArray[i + 2] ) );
  138. }
  139. } else if (semantic == "NORMAL") {
  140. geom.geometry.normals = [];
  141. floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
  142. for (i = 0, l = floatArray.length; i < l; i += 3) {
  143. geom.geometry.normals.push( new THREE.Vector3( floatArray[i], floatArray[i + 1], floatArray[i + 2] ) );
  144. }
  145. } else if ((semantic == "TEXCOORD_0") || (semantic == "TEXCOORD" )) {
  146. geom.uvs = [];
  147. floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
  148. for (i = 0, l = floatArray.length; i < l; i += 2) {
  149. geom.uvs.push( new THREE.Vector2( floatArray[i], 1.0 - floatArray[i + 1] ) );
  150. }
  151. }
  152. else if (semantic == "WEIGHT") {
  153. nComponents = componentsPerElementForGLType(attribute.type);
  154. floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
  155. for (i = 0, l = floatArray.length; i < l; i += 4) {
  156. geom.geometry.skinWeights.push( new THREE.Vector4( floatArray[i], floatArray[i + 1], floatArray[i + 2], floatArray[i + 3] ) );
  157. }
  158. }
  159. else if (semantic == "JOINT") {
  160. nComponents = componentsPerElementForGLType(attribute.type);
  161. floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
  162. for (i = 0, l = floatArray.length; i < l; i += 4) {
  163. geom.geometry.skinIndices.push( new THREE.Vector4( floatArray[i], floatArray[i + 1], floatArray[i + 2], floatArray[i + 3] ) );
  164. }
  165. }
  166. };
  167. VertexAttributeDelegate.prototype.bufferResourceAvailable = function(glResource, ctx) {
  168. var geom = ctx.geometry;
  169. var attribute = ctx.attribute;
  170. var semantic = ctx.semantic;
  171. var floatArray;
  172. var i, l;
  173. var nComponents;
  174. //FIXME: Float32 is assumed here, but should be checked.
  175. if (semantic == "POSITION") {
  176. // TODO: Should be easy to take strides into account here
  177. floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
  178. geom.geometry.addAttribute( 'position', new THREE.BufferAttribute( floatArray, 3 ) );
  179. } else if (semantic == "NORMAL") {
  180. floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
  181. geom.geometry.addAttribute( 'normal', new THREE.BufferAttribute( floatArray, 3 ) );
  182. } else if ((semantic == "TEXCOORD_0") || (semantic == "TEXCOORD" )) {
  183. nComponents = componentsPerElementForGLType(attribute.type);
  184. floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
  185. // N.B.: flip Y value... should we just set texture.flipY everywhere?
  186. for (i = 0; i < floatArray.length / 2; i ++) {
  187. floatArray[i * 2 + 1] = 1.0 - floatArray[i * 2 + 1];
  188. }
  189. geom.geometry.addAttribute( 'uv', new THREE.BufferAttribute( floatArray, nComponents ) );
  190. }
  191. else if (semantic == "WEIGHT") {
  192. nComponents = componentsPerElementForGLType(attribute.type);
  193. floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
  194. geom.geometry.addAttribute( 'skinWeight', new THREE.BufferAttribute( floatArray, nComponents ) );
  195. }
  196. else if (semantic == "JOINT") {
  197. nComponents = componentsPerElementForGLType(attribute.type);
  198. floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
  199. geom.geometry.addAttribute( 'skinIndex', new THREE.BufferAttribute( floatArray, nComponents ) );
  200. }
  201. };
  202. VertexAttributeDelegate.prototype.resourceAvailable = function(glResource, ctx) {
  203. this.bufferResourceAvailable(glResource, ctx);
  204. var geom = ctx.geometry;
  205. geom.loadedAttributes ++;
  206. geom.checkFinished();
  207. return true;
  208. };
  209. var vertexAttributeDelegate = new VertexAttributeDelegate();
  210. var VertexAttributeContext = function(attribute, semantic, geometry) {
  211. this.attribute = attribute;
  212. this.semantic = semantic;
  213. this.geometry = geometry;
  214. };
  215. var Mesh = function() {
  216. this.primitives = [];
  217. this.materialsPending = [];
  218. this.loadedGeometry = 0;
  219. this.onCompleteCallbacks = [];
  220. };
  221. Mesh.prototype.addPrimitive = function(geometry, material) {
  222. var self = this;
  223. geometry.onload = function() {
  224. self.loadedGeometry ++;
  225. self.checkComplete();
  226. };
  227. this.primitives.push({
  228. geometry: geometry,
  229. material: material,
  230. mesh: null
  231. });
  232. };
  233. Mesh.prototype.onComplete = function(callback) {
  234. this.onCompleteCallbacks.push(callback);
  235. this.checkComplete();
  236. };
  237. Mesh.prototype.checkComplete = function() {
  238. var self = this;
  239. if (this.onCompleteCallbacks.length && this.primitives.length == this.loadedGeometry) {
  240. this.onCompleteCallbacks.forEach(function(callback) {
  241. callback(self);
  242. });
  243. this.onCompleteCallbacks = [];
  244. }
  245. };
  246. Mesh.prototype.attachToNode = function(threeNode) {
  247. // Assumes that the geometry is complete
  248. this.primitives.forEach(function(primitive) {
  249. /*if(!primitive.mesh) {
  250. primitive.mesh = new THREE.Mesh(primitive.geometry, primitive.material);
  251. }*/
  252. var material = primitive.material;
  253. if (!(material instanceof THREE.Material)) {
  254. material = theLoader.createShaderMaterial(material);
  255. }
  256. var threeMesh = new THREE.Mesh(primitive.geometry.geometry, material);
  257. threeMesh.castShadow = true;
  258. threeNode.add(threeMesh);
  259. });
  260. };
  261. // Delayed-loaded material
  262. var Material = function(params) {
  263. this.params = params;
  264. };
  265. // Delegate for processing animation parameter buffers
  266. var AnimationParameterDelegate = function() {};
  267. AnimationParameterDelegate.prototype.handleError = function(errorCode, info) {
  268. // FIXME: report error
  269. console.log("ERROR(AnimationParameterDelegate):" + errorCode + ":" + info);
  270. };
  271. AnimationParameterDelegate.prototype.convert = function(resource, ctx) {
  272. var parameter = ctx.parameter;
  273. var glResource = null;
  274. switch (parameter.type) {
  275. case WebGLRenderingContext.FLOAT :
  276. case WebGLRenderingContext.FLOAT_VEC2 :
  277. case WebGLRenderingContext.FLOAT_VEC3 :
  278. case WebGLRenderingContext.FLOAT_VEC4 :
  279. glResource = new Float32Array(resource, 0, parameter.count * componentsPerElementForGLType(parameter.type));
  280. break;
  281. default:
  282. break;
  283. }
  284. return glResource;
  285. };
  286. AnimationParameterDelegate.prototype.resourceAvailable = function(glResource, ctx) {
  287. var animation = ctx.animation;
  288. var parameter = ctx.parameter;
  289. parameter.data = glResource;
  290. animation.handleParameterLoaded(parameter);
  291. return true;
  292. };
  293. var animationParameterDelegate = new AnimationParameterDelegate();
  294. var AnimationParameterContext = function(parameter, animation) {
  295. this.parameter = parameter;
  296. this.animation = animation;
  297. };
  298. // Animations
  299. var Animation = function() {
  300. // create Three.js keyframe here
  301. this.totalParameters = 0;
  302. this.loadedParameters = 0;
  303. this.parameters = {};
  304. this.finishedLoading = false;
  305. this.onload = null;
  306. };
  307. Animation.prototype.constructor = Animation;
  308. Animation.prototype.handleParameterLoaded = function(parameter) {
  309. this.parameters[parameter.name] = parameter;
  310. this.loadedParameters ++;
  311. this.checkFinished();
  312. };
  313. Animation.prototype.checkFinished = function() {
  314. if (this.loadedParameters === this.totalParameters) {
  315. // Build animation
  316. this.finishedLoading = true;
  317. if (this.onload) {
  318. this.onload();
  319. }
  320. }
  321. };
  322. // Delegate for processing inverse bind matrices buffer
  323. var InverseBindMatricesDelegate = function() {};
  324. InverseBindMatricesDelegate.prototype.handleError = function(errorCode, info) {
  325. // FIXME: report error
  326. console.log("ERROR(InverseBindMatricesDelegate):" + errorCode + ":" + info);
  327. };
  328. InverseBindMatricesDelegate.prototype.convert = function(resource, ctx) {
  329. var parameter = ctx.parameter;
  330. var glResource = null;
  331. switch (parameter.type) {
  332. case WebGLRenderingContext.FLOAT_MAT4 :
  333. glResource = new Float32Array(resource, 0, parameter.count * componentsPerElementForGLType(parameter.type));
  334. break;
  335. default:
  336. break;
  337. }
  338. return glResource;
  339. };
  340. InverseBindMatricesDelegate.prototype.resourceAvailable = function(glResource, ctx) {
  341. var skin = ctx.skin;
  342. skin.inverseBindMatrices = glResource;
  343. return true;
  344. };
  345. var inverseBindMatricesDelegate = new InverseBindMatricesDelegate();
  346. var InverseBindMatricesContext = function(param, skin) {
  347. this.parameter = param;
  348. this.skin = skin;
  349. };
  350. // Delegate for processing shaders from external files
  351. var ShaderDelegate = function() {};
  352. ShaderDelegate.prototype.handleError = function(errorCode, info) {
  353. // FIXME: report error
  354. console.log("ERROR(ShaderDelegate):" + errorCode + ":" + info);
  355. };
  356. ShaderDelegate.prototype.convert = function(resource, ctx) {
  357. return resource;
  358. };
  359. ShaderDelegate.prototype.resourceAvailable = function(data, ctx) {
  360. theLoader.shadersLoaded ++;
  361. theLoader.shaders[ctx.id] = data;
  362. theLoader.checkComplete();
  363. return true;
  364. };
  365. var shaderDelegate = new ShaderDelegate();
  366. var ShaderContext = function(id, path) {
  367. this.id = id;
  368. this.path = path;
  369. };
  370. // Resource management
  371. var ResourceEntry = function(entryID, object, description) {
  372. this.entryID = entryID;
  373. this.object = object;
  374. this.description = description;
  375. };
  376. var Resources = function() {
  377. this._entries = {};
  378. };
  379. Resources.prototype.setEntry = function(entryID, object, description) {
  380. if (!entryID) {
  381. console.error("No EntryID provided, cannot store", description);
  382. return;
  383. }
  384. if (this._entries[entryID]) {
  385. console.warn("entry[" + entryID + "] is being overwritten");
  386. }
  387. this._entries[entryID] = new ResourceEntry(entryID, object, description );
  388. };
  389. Resources.prototype.getEntry = function(entryID) {
  390. return this._entries[entryID];
  391. };
  392. Resources.prototype.clearEntries = function() {
  393. this._entries = {};
  394. };
  395. LoadDelegate = function() {
  396. };
  397. LoadDelegate.prototype.loadCompleted = function(callback, obj) {
  398. callback.call(Window, obj);
  399. };
  400. // Loader
  401. var ThreeGLTFLoader = Object.create(glTFParser, {
  402. load: {
  403. enumerable: true,
  404. value: function(userInfo, options) {
  405. this.resources = new Resources();
  406. this.cameras = [];
  407. this.lights = [];
  408. this.animations = [];
  409. this.joints = {};
  410. this.skeltons = {};
  411. THREE.GLTFLoaderUtils.init();
  412. glTFParser.load.call(this, userInfo, options);
  413. }
  414. },
  415. cameras: {
  416. enumerable: true,
  417. writable: true,
  418. value : []
  419. },
  420. lights: {
  421. enumerable: true,
  422. writable: true,
  423. value : []
  424. },
  425. animations: {
  426. enumerable: true,
  427. writable: true,
  428. value : []
  429. },
  430. // Implement WebGLTFLoader handlers
  431. handleBuffer: {
  432. value: function(entryID, description, userInfo) {
  433. this.resources.setEntry(entryID, null, description);
  434. description.type = "ArrayBuffer";
  435. return true;
  436. }
  437. },
  438. handleBufferView: {
  439. value: function(entryID, description, userInfo) {
  440. this.resources.setEntry(entryID, null, description);
  441. var buffer = this.resources.getEntry(description.buffer);
  442. description.type = "ArrayBufferView";
  443. var bufferViewEntry = this.resources.getEntry(entryID);
  444. bufferViewEntry.buffer = buffer;
  445. return true;
  446. }
  447. },
  448. handleShader: {
  449. value: function(entryID, description, userInfo) {
  450. this.resources.setEntry(entryID, null, description);
  451. var shaderRequest = {
  452. id : entryID,
  453. path : description.path,
  454. };
  455. var shaderContext = new ShaderContext(entryID, description.path);
  456. theLoader.shadersRequested ++;
  457. THREE.GLTFLoaderUtils.getFile(shaderRequest, shaderDelegate, shaderContext);
  458. return true;
  459. }
  460. },
  461. handleProgram: {
  462. value: function(entryID, description, userInfo) {
  463. this.resources.setEntry(entryID, null, description);
  464. return true;
  465. }
  466. },
  467. handleTechnique: {
  468. value: function(entryID, description, userInfo) {
  469. this.resources.setEntry(entryID, null, description);
  470. return true;
  471. }
  472. },
  473. createShaderMaterial : {
  474. value: function(material) {
  475. var fragmentShader = theLoader.shaders[material.params.fragmentShader];
  476. if (!fragmentShader) {
  477. console.log("ERROR: Missing fragment shader definition:", material.params.fragmentShader);
  478. return new THREE.MeshPhongMaterial;
  479. }
  480. var vertexShader = theLoader.shaders[material.params.vertexShader];
  481. if (!fragmentShader) {
  482. console.log("ERROR: Missing vertex shader definition:", material.params.vertexShader);
  483. return new THREE.MeshPhongMaterial;
  484. }
  485. var uniforms = {};
  486. var shaderMaterial = new THREE.ShaderMaterial( {
  487. fragmentShader: fragmentShader,
  488. vertexShader: vertexShader,
  489. uniforms: uniforms,
  490. } );
  491. return new THREE.MeshPhongMaterial(material.params);
  492. }
  493. },
  494. createShaderParams : {
  495. value: function(materialId, values, params, instanceProgram) {
  496. var program = this.resources.getEntry(instanceProgram.program);
  497. if (program) {
  498. params.fragmentShader = program.description.fragmentShader;
  499. params.vertexShader = program.description.vertexShader;
  500. params.attributes = instanceProgram.attributes;
  501. params.uniforms = instanceProgram.uniforms;
  502. }
  503. }
  504. },
  505. threeJSMaterialType : {
  506. value: function(materialId, technique, values, params) {
  507. var materialType = THREE.MeshPhongMaterial;
  508. var defaultPass = null;
  509. if (technique && technique.description && technique.description.passes)
  510. defaultPass = technique.description.passes.defaultPass;
  511. if (defaultPass) {
  512. if (defaultPass.details && defaultPass.details.commonProfile) {
  513. var profile = technique.description.passes.defaultPass.details.commonProfile;
  514. if (profile)
  515. {
  516. switch (profile.lightingModel)
  517. {
  518. case 'Blinn' :
  519. case 'Phong' :
  520. materialType = THREE.MeshPhongMaterial;
  521. break;
  522. case 'Lambert' :
  523. materialType = THREE.MeshLambertMaterial;
  524. break;
  525. default :
  526. materialType = THREE.MeshBasicMaterial;
  527. break;
  528. }
  529. if (profile.extras && profile.extras.doubleSided)
  530. {
  531. params.side = THREE.DoubleSide;
  532. }
  533. }
  534. }
  535. else if (defaultPass.instanceProgram) {
  536. var instanceProgram = defaultPass.instanceProgram;
  537. this.createShaderParams(materialId, values, params, instanceProgram);
  538. var loadshaders = true;
  539. if (loadshaders) {
  540. materialType = Material;
  541. }
  542. }
  543. }
  544. var texturePath = null;
  545. var textureParams = null;
  546. var diffuse = values.diffuse;
  547. if (diffuse)
  548. {
  549. var texture = diffuse;
  550. if (texture) {
  551. var textureEntry = this.resources.getEntry(texture);
  552. if (textureEntry) {
  553. {
  554. var imageEntry = this.resources.getEntry(textureEntry.description.source);
  555. if (imageEntry) {
  556. texturePath = imageEntry.description.path;
  557. }
  558. var samplerEntry = this.resources.getEntry(textureEntry.description.sampler);
  559. if (samplerEntry) {
  560. textureParams = samplerEntry.description;
  561. }
  562. }
  563. }
  564. }
  565. }
  566. var texture = LoadTexture(texturePath);
  567. if (texture && textureParams) {
  568. if (textureParams.wrapS == WebGLRenderingContext.REPEAT)
  569. texture.wrapS = THREE.RepeatWrapping;
  570. if (textureParams.wrapT == WebGLRenderingContext.REPEAT)
  571. texture.wrapT = THREE.RepeatWrapping;
  572. if (textureParams.magFilter == WebGLRenderingContext.LINEAR)
  573. texture.magFilter = THREE.LinearFilter;
  574. // if (textureParams.minFilter == "LINEAR")
  575. // texture.minFilter = THREE.LinearFilter;
  576. params.map = texture;
  577. }
  578. var envMapPath = null;
  579. var envMapParams = null;
  580. var reflective = values.reflective;
  581. if (reflective)
  582. {
  583. var texture = reflective;
  584. if (texture) {
  585. var textureEntry = this.resources.getEntry(texture);
  586. if (textureEntry) {
  587. {
  588. var imageEntry = this.resources.getEntry(textureEntry.description.source);
  589. if (imageEntry) {
  590. envMapPath = imageEntry.description.path;
  591. }
  592. var samplerEntry = this.resources.getEntry(textureEntry.description.sampler);
  593. if (samplerEntry) {
  594. envMapParams = samplerEntry.description;
  595. }
  596. }
  597. }
  598. }
  599. }
  600. var texture = LoadTexture(envMapPath);
  601. if (texture && envMapParams) {
  602. if (envMapParams.wrapS == WebGLRenderingContext.REPEAT)
  603. texture.wrapS = THREE.RepeatWrapping;
  604. if (envMapParams.wrapT == WebGLRenderingContext.REPEAT)
  605. texture.wrapT = THREE.RepeatWrapping;
  606. if (envMapParams.magFilter == WebGLRenderingContext.LINEAR)
  607. texture.magFilter = THREE.LinearFilter;
  608. // if (envMapParams.minFilter == WebGLRenderingContext.LINEAR)
  609. // texture.minFilter = THREE.LinearFilter;
  610. params.envMap = texture;
  611. }
  612. var shininess = values.shininesss || values.shininess; // N.B.: typo in converter!
  613. if (shininess)
  614. {
  615. shininess = shininess;
  616. }
  617. var diffuseColor = !texturePath ? diffuse : null;
  618. var opacity = 1.0;
  619. if (values.hasOwnProperty("transparency"))
  620. {
  621. var USE_A_ONE = true; // for now, hack because file format isn't telling us
  622. opacity = USE_A_ONE ? values.transparency : (1.0 - values.transparency);
  623. }
  624. // if (diffuseColor) diffuseColor = [0, 1, 0];
  625. params.color = RgbArraytoHex(diffuseColor);
  626. params.opacity = opacity;
  627. params.transparent = opacity < 1.0;
  628. // hack hack hack
  629. if (texturePath && texturePath.toLowerCase().indexOf(".png") != -1)
  630. params.transparent = true;
  631. if (!(shininess === undefined))
  632. {
  633. params.shininess = shininess;
  634. }
  635. if (!(values.emission === undefined))
  636. {
  637. params.emissive = RgbArraytoHex(values.emission);
  638. }
  639. if (!(values.specular === undefined))
  640. {
  641. params.specular = RgbArraytoHex(values.specular);
  642. }
  643. return materialType;
  644. }
  645. },
  646. handleMaterial: {
  647. value: function(entryID, description, userInfo) {
  648. //this should be rewritten using the meta datas that actually create the shader.
  649. //here we will infer what needs to be pass to Three.js by looking inside the technique parameters.
  650. var technique = this.resources.getEntry(description.instanceTechnique.technique);
  651. var materialParams = {};
  652. var values = description.instanceTechnique.values;
  653. var materialType = this.threeJSMaterialType(entryID, technique, values, materialParams);
  654. var material = new materialType(materialParams);
  655. this.resources.setEntry(entryID, material, description);
  656. return true;
  657. }
  658. },
  659. handleMesh: {
  660. value: function(entryID, description, userInfo) {
  661. var mesh = new Mesh();
  662. this.resources.setEntry(entryID, mesh, description);
  663. var primitivesDescription = description.primitives;
  664. if (!primitivesDescription) {
  665. //FIXME: not implemented in delegate
  666. console.log("MISSING_PRIMITIVES for mesh:" + entryID);
  667. return false;
  668. }
  669. for (var i = 0 ; i < primitivesDescription.length ; i ++) {
  670. var primitiveDescription = primitivesDescription[i];
  671. if (primitiveDescription.primitive === WebGLRenderingContext.TRIANGLES) {
  672. var geometry = new ClassicGeometry();
  673. var materialEntry = this.resources.getEntry(primitiveDescription.material);
  674. mesh.addPrimitive(geometry, materialEntry.object);
  675. var indices = this.resources.getEntry(primitiveDescription.indices);
  676. var bufferEntry = this.resources.getEntry(indices.description.bufferView);
  677. var indicesObject = {
  678. bufferView : bufferEntry,
  679. byteOffset : indices.description.byteOffset,
  680. count : indices.description.count,
  681. id : indices.entryID,
  682. type : indices.description.type
  683. };
  684. var indicesContext = new IndicesContext(indicesObject, geometry);
  685. var alreadyProcessedIndices = THREE.GLTFLoaderUtils.getBuffer(indicesObject, indicesDelegate, indicesContext);
  686. /*if(alreadyProcessedIndices) {
  687. indicesDelegate.resourceAvailable(alreadyProcessedIndices, indicesContext);
  688. }*/
  689. // Load Vertex Attributes
  690. var allAttributes = Object.keys(primitiveDescription.attributes);
  691. allAttributes.forEach( function(semantic) {
  692. geometry.totalAttributes ++;
  693. var attribute;
  694. var attributeID = primitiveDescription.attributes[semantic];
  695. var attributeEntry = this.resources.getEntry(attributeID);
  696. if (!attributeEntry) {
  697. //let's just use an anonymous object for the attribute
  698. attribute = description.attributes[attributeID];
  699. attribute.id = attributeID;
  700. this.resources.setEntry(attributeID, attribute, attribute);
  701. var bufferEntry = this.resources.getEntry(attribute.bufferView);
  702. attributeEntry = this.resources.getEntry(attributeID);
  703. } else {
  704. attribute = attributeEntry.object;
  705. attribute.id = attributeID;
  706. var bufferEntry = this.resources.getEntry(attribute.bufferView);
  707. }
  708. var attributeObject = {
  709. bufferView : bufferEntry,
  710. byteOffset : attribute.byteOffset,
  711. byteStride : attribute.byteStride,
  712. count : attribute.count,
  713. max : attribute.max,
  714. min : attribute.min,
  715. type : attribute.type,
  716. id : attributeID
  717. };
  718. var attribContext = new VertexAttributeContext(attributeObject, semantic, geometry);
  719. var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer(attributeObject, vertexAttributeDelegate, attribContext);
  720. /*if(alreadyProcessedAttribute) {
  721. vertexAttributeDelegate.resourceAvailable(alreadyProcessedAttribute, attribContext);
  722. }*/
  723. }, this);
  724. }
  725. }
  726. return true;
  727. }
  728. },
  729. handleCamera: {
  730. value: function(entryID, description, userInfo) {
  731. var camera;
  732. if (description.type == "perspective")
  733. {
  734. var znear = description.perspective.znear;
  735. var zfar = description.perspective.zfar;
  736. var yfov = description.perspective.yfov;
  737. var xfov = description.perspective.xfov;
  738. var aspect_ratio = description.perspective.aspect_ratio;
  739. if (!aspect_ratio)
  740. aspect_ratio = 1;
  741. if (yfov === undefined)
  742. {
  743. if (xfov)
  744. {
  745. // According to COLLADA spec...
  746. // aspect_ratio = xfov / yfov
  747. yfov = xfov / aspect_ratio;
  748. }
  749. }
  750. if (yfov)
  751. {
  752. camera = new THREE.PerspectiveCamera(yfov, aspect_ratio, znear, zfar);
  753. }
  754. }
  755. else
  756. {
  757. camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, znear, zfar );
  758. }
  759. if (camera)
  760. {
  761. this.resources.setEntry(entryID, camera, description);
  762. }
  763. return true;
  764. }
  765. },
  766. handleLight: {
  767. value: function(entryID, description, userInfo) {
  768. var light = null;
  769. var type = description.type;
  770. if (type && description[type])
  771. {
  772. var lparams = description[type];
  773. var color = RgbArraytoHex(lparams.color);
  774. switch (type) {
  775. case "directional" :
  776. light = new THREE.DirectionalLight(color);
  777. light.position.set(0, 0, 1);
  778. break;
  779. case "point" :
  780. light = new THREE.PointLight(color);
  781. break;
  782. case "spot " :
  783. light = new THREE.SpotLight(color);
  784. light.position.set(0, 0, 1);
  785. break;
  786. case "ambient" :
  787. light = new THREE.AmbientLight(color);
  788. break;
  789. }
  790. }
  791. if (light)
  792. {
  793. this.resources.setEntry(entryID, light, description);
  794. }
  795. return true;
  796. }
  797. },
  798. addPendingMesh: {
  799. value: function(mesh, threeNode) {
  800. theLoader.pendingMeshes.push({
  801. mesh: mesh,
  802. node: threeNode
  803. });
  804. }
  805. },
  806. handleNode: {
  807. value: function(entryID, description, userInfo) {
  808. var threeNode = null;
  809. if (description.jointId) {
  810. threeNode = new THREE.Bone();
  811. threeNode.jointId = description.jointId;
  812. this.joints[description.jointId] = entryID;
  813. }
  814. else {
  815. threeNode = new THREE.Object3D();
  816. }
  817. threeNode.name = description.name;
  818. this.resources.setEntry(entryID, threeNode, description);
  819. var m = description.matrix;
  820. if (m) {
  821. threeNode.applyMatrix(new THREE.Matrix4().fromArray( m ));
  822. threeNode.matrixAutoUpdate = false;
  823. threeNode.matrixWorldNeedsUpdate = true;
  824. }
  825. else {
  826. var t = description.translation;
  827. var r = description.rotation;
  828. var s = description.scale;
  829. var position = t ? new THREE.Vector3(t[0], t[1], t[2]) :
  830. new THREE.Vector3;
  831. if (r) {
  832. convertAxisAngleToQuaternion(r, 1);
  833. }
  834. var rotation = r ? new THREE.Quaternion(r[0], r[1], r[2], r[3]) :
  835. new THREE.Quaternion;
  836. var scale = s ? new THREE.Vector3(s[0], s[1], s[2]) :
  837. new THREE.Vector3;
  838. var matrix = new THREE.Matrix4;
  839. matrix.compose(position, rotation, scale);
  840. threeNode.matrixAutoUpdate = false;
  841. threeNode.matrixWorldNeedsUpdate = true;
  842. threeNode.applyMatrix(matrix);
  843. }
  844. var self = this;
  845. // Iterate through all node meshes and attach the appropriate objects
  846. //FIXME: decision needs to be made between these 2 ways, probably meshes will be discarded.
  847. var meshEntry;
  848. if (description.mesh) {
  849. meshEntry = this.resources.getEntry(description.mesh);
  850. theLoader.meshesRequested ++;
  851. meshEntry.object.onComplete(function(mesh) {
  852. self.addPendingMesh(mesh, threeNode);
  853. theLoader.meshesLoaded ++;
  854. theLoader.checkComplete();
  855. });
  856. }
  857. if (description.meshes) {
  858. description.meshes.forEach( function(meshID) {
  859. meshEntry = this.resources.getEntry(meshID);
  860. theLoader.meshesRequested ++;
  861. meshEntry.object.onComplete(function(mesh) {
  862. self.addPendingMesh(mesh, threeNode);
  863. theLoader.meshesLoaded ++;
  864. theLoader.checkComplete();
  865. });
  866. }, this);
  867. }
  868. if (description.instanceSkin) {
  869. var skinEntry = this.resources.getEntry(description.instanceSkin.skin);
  870. if (skinEntry) {
  871. var skin = skinEntry.object;
  872. description.instanceSkin.skin = skin;
  873. threeNode.instanceSkin = description.instanceSkin;
  874. var sources = description.instanceSkin.sources;
  875. skin.meshes = [];
  876. sources.forEach( function(meshID) {
  877. meshEntry = this.resources.getEntry(meshID);
  878. theLoader.meshesRequested ++;
  879. meshEntry.object.onComplete(function(mesh) {
  880. skin.meshes.push(mesh);
  881. theLoader.meshesLoaded ++;
  882. theLoader.checkComplete();
  883. });
  884. }, this);
  885. }
  886. }
  887. if (description.camera) {
  888. var cameraEntry = this.resources.getEntry(description.camera);
  889. if (cameraEntry) {
  890. threeNode.add(cameraEntry.object);
  891. this.cameras.push(cameraEntry.object);
  892. }
  893. }
  894. if (description.light) {
  895. var lightEntry = this.resources.getEntry(description.light);
  896. if (lightEntry) {
  897. threeNode.add(lightEntry.object);
  898. this.lights.push(lightEntry.object);
  899. }
  900. }
  901. return true;
  902. }
  903. },
  904. buildNodeHirerachy: {
  905. value: function(nodeEntryId, parentThreeNode) {
  906. var nodeEntry = this.resources.getEntry(nodeEntryId);
  907. var threeNode = nodeEntry.object;
  908. parentThreeNode.add(threeNode);
  909. var children = nodeEntry.description.children;
  910. if (children) {
  911. children.forEach( function(childID) {
  912. this.buildNodeHirerachy(childID, threeNode);
  913. }, this);
  914. }
  915. return threeNode;
  916. }
  917. },
  918. buildSkin: {
  919. value: function(node) {
  920. var skin = node.instanceSkin.skin;
  921. if (skin) {
  922. node.instanceSkin.skeletons.forEach(function(skeleton) {
  923. var nodeEntry = this.resources.getEntry(skeleton);
  924. if (nodeEntry) {
  925. var rootSkeleton = nodeEntry.object;
  926. var dobones = true;
  927. var i, len = skin.meshes.length;
  928. for (i = 0; i < len; i ++) {
  929. var mesh = skin.meshes[i];
  930. var threeMesh = null;
  931. mesh.primitives.forEach(function(primitive) {
  932. var material = primitive.material;
  933. if (!(material instanceof THREE.Material)) {
  934. material = this.createShaderMaterial(material);
  935. }
  936. threeMesh = new THREE.SkinnedMesh(primitive.geometry.geometry, material, false);
  937. threeMesh.add(rootSkeleton);
  938. var geometry = primitive.geometry.geometry;
  939. var j;
  940. if (geometry.vertices) {
  941. for ( j = 0; j < geometry.vertices.length; j ++ ) {
  942. geometry.vertices[j].applyMatrix4( skin.bindShapeMatrix );
  943. }
  944. }
  945. else if (geometry.attributes.position) {
  946. var a = geometry.attributes.position.array;
  947. var v = new THREE.Vector3;
  948. for ( j = 0; j < a.length / 3; j ++ ) {
  949. v.set(a[j * 3], a[j * 3 + 1], a[j * 3 + 2]);
  950. v.applyMatrix4( skin.bindShapeMatrix );
  951. a[j * 3] = v.x;
  952. a[j * 3 + 1] = v.y;
  953. a[j * 3 + 2] = v.z;
  954. }
  955. }
  956. if (threeMesh && dobones) {
  957. material.skinning = true;
  958. threeMesh.boneInverses = [];
  959. var jointsIds = skin.jointsIds;
  960. var bones = [];
  961. var boneInverses = [];
  962. var i, len = jointsIds.length;
  963. for (i = 0; i < len; i ++) {
  964. var jointId = jointsIds[i];
  965. var nodeForJoint = this.joints[jointId];
  966. var joint = this.resources.getEntry(nodeForJoint).object;
  967. if (joint) {
  968. joint.skin = threeMesh;
  969. bones.push(joint);
  970. var m = skin.inverseBindMatrices;
  971. var mat = new THREE.Matrix4().set(
  972. m[i * 16 + 0], m[i * 16 + 4], m[i * 16 + 8], m[i * 16 + 12],
  973. m[i * 16 + 1], m[i * 16 + 5], m[i * 16 + 9], m[i * 16 + 13],
  974. m[i * 16 + 2], m[i * 16 + 6], m[i * 16 + 10], m[i * 16 + 14],
  975. m[i * 16 + 3], m[i * 16 + 7], m[i * 16 + 11], m[i * 16 + 15]
  976. );
  977. boneInverses.push(mat);
  978. } else {
  979. console.log("WARNING: jointId:" + jointId + " cannot be found in skeleton:" + skeleton);
  980. }
  981. }
  982. threeMesh.bind( new THREE.Skeleton( bones, boneInverses, false ), threeMesh.matrixWorld );
  983. }
  984. if (threeMesh) {
  985. threeMesh.castShadow = true;
  986. node.add(threeMesh);
  987. }
  988. }, this);
  989. }
  990. }
  991. }, this);
  992. }
  993. }
  994. },
  995. buildSkins: {
  996. value: function(node) {
  997. if (node.instanceSkin)
  998. this.buildSkin(node);
  999. var children = node.children;
  1000. if (children) {
  1001. children.forEach( function(child) {
  1002. this.buildSkins(child);
  1003. }, this);
  1004. }
  1005. }
  1006. },
  1007. createMeshAnimations : {
  1008. value : function(root) {
  1009. this.buildSkins(root);
  1010. }
  1011. },
  1012. handleScene: {
  1013. value: function(entryID, description, userInfo) {
  1014. if (!description.nodes) {
  1015. console.log("ERROR: invalid file required nodes property is missing from scene");
  1016. return false;
  1017. }
  1018. description.nodes.forEach( function(nodeUID) {
  1019. this.buildNodeHirerachy(nodeUID, userInfo.rootObj);
  1020. }, this);
  1021. if (this.delegate) {
  1022. this.delegate.loadCompleted(userInfo.callback, userInfo.rootObj);
  1023. }
  1024. return true;
  1025. }
  1026. },
  1027. handleImage: {
  1028. value: function(entryID, description, userInfo) {
  1029. this.resources.setEntry(entryID, null, description);
  1030. return true;
  1031. }
  1032. },
  1033. addNodeAnimationChannel : {
  1034. value : function(name, channel, interp) {
  1035. if (!this.nodeAnimationChannels)
  1036. this.nodeAnimationChannels = {};
  1037. if (!this.nodeAnimationChannels[name]) {
  1038. this.nodeAnimationChannels[name] = [];
  1039. }
  1040. this.nodeAnimationChannels[name].push(interp);
  1041. },
  1042. },
  1043. createAnimations : {
  1044. value : function() {
  1045. for (var name in this.nodeAnimationChannels) {
  1046. var nodeAnimationChannels = this.nodeAnimationChannels[name];
  1047. var i, len = nodeAnimationChannels.length;
  1048. //console.log(" animation channels for node " + name);
  1049. //for (i = 0; i < len; i++) {
  1050. // console.log(nodeAnimationChannels[i]);
  1051. //}
  1052. var anim = new THREE.glTFAnimation(nodeAnimationChannels);
  1053. anim.name = "animation_" + name;
  1054. this.animations.push(anim);
  1055. }
  1056. }
  1057. },
  1058. buildAnimation: {
  1059. value : function(animation) {
  1060. var interps = [];
  1061. var i, len = animation.channels.length;
  1062. for (i = 0; i < len; i ++) {
  1063. var channel = animation.channels[i];
  1064. var sampler = animation.samplers[channel.sampler];
  1065. if (sampler) {
  1066. var input = animation.parameters[sampler.input];
  1067. if (input && input.data) {
  1068. var output = animation.parameters[sampler.output];
  1069. if (output && output.data) {
  1070. var target = channel.target;
  1071. var node = this.resources.getEntry(target.id);
  1072. if (node) {
  1073. var path = target.path;
  1074. if (path == "rotation")
  1075. {
  1076. convertAxisAngleToQuaternion(output.data, output.count);
  1077. }
  1078. var interp = {
  1079. keys : input.data,
  1080. values : output.data,
  1081. count : input.count,
  1082. target : node.object,
  1083. path : path,
  1084. type : sampler.interpolation
  1085. };
  1086. this.addNodeAnimationChannel(target.id, channel, interp);
  1087. interps.push(interp);
  1088. }
  1089. }
  1090. }
  1091. }
  1092. }
  1093. }
  1094. },
  1095. handleAnimation: {
  1096. value: function(entryID, description, userInfo) {
  1097. var self = this;
  1098. theLoader.animationsRequested ++;
  1099. var animation = new Animation();
  1100. animation.name = entryID;
  1101. animation.onload = function() {
  1102. // self.buildAnimation(animation);
  1103. theLoader.animationsLoaded ++;
  1104. theLoader.animations.push(animation);
  1105. theLoader.checkComplete();
  1106. };
  1107. animation.channels = description.channels;
  1108. animation.samplers = description.samplers;
  1109. this.resources.setEntry(entryID, animation, description);
  1110. var parameters = description.parameters;
  1111. if (!parameters) {
  1112. //FIXME: not implemented in delegate
  1113. console.log("MISSING_PARAMETERS for animation:" + entryID);
  1114. return false;
  1115. }
  1116. // Load parameter buffers
  1117. var params = Object.keys(parameters);
  1118. params.forEach( function(param) {
  1119. animation.totalParameters ++;
  1120. var parameter = parameters[param];
  1121. var accessor = this.resources.getEntry(parameter);
  1122. if (!accessor)
  1123. debugger;
  1124. accessor = accessor.object;
  1125. var bufferView = this.resources.getEntry(accessor.bufferView);
  1126. var paramObject = {
  1127. bufferView : bufferView,
  1128. byteOffset : accessor.byteOffset,
  1129. count : accessor.count,
  1130. type : accessor.type,
  1131. id : accessor.bufferView,
  1132. name : param
  1133. };
  1134. var paramContext = new AnimationParameterContext(paramObject, animation);
  1135. var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer(paramObject, animationParameterDelegate, paramContext);
  1136. /*if(alreadyProcessedAttribute) {
  1137. vertexAttributeDelegate.resourceAvailable(alreadyProcessedAttribute, attribContext);
  1138. }*/
  1139. }, this);
  1140. return true;
  1141. }
  1142. },
  1143. handleAccessor: {
  1144. value: function(entryID, description, userInfo) {
  1145. // Save attribute entry
  1146. this.resources.setEntry(entryID, description, description);
  1147. return true;
  1148. }
  1149. },
  1150. handleSkin: {
  1151. value: function(entryID, description, userInfo) {
  1152. // Save skin entry
  1153. var skin = {
  1154. };
  1155. var m = description.bindShapeMatrix;
  1156. skin.bindShapeMatrix = new THREE.Matrix4().fromArray( m );
  1157. skin.jointsIds = description.joints;
  1158. var inverseBindMatricesDescription = description.inverseBindMatrices;
  1159. skin.inverseBindMatricesDescription = inverseBindMatricesDescription;
  1160. skin.inverseBindMatricesDescription.id = entryID + "_inverseBindMatrices";
  1161. var bufferEntry = this.resources.getEntry(inverseBindMatricesDescription.bufferView);
  1162. var paramObject = {
  1163. bufferView : bufferEntry,
  1164. byteOffset : inverseBindMatricesDescription.byteOffset,
  1165. count : inverseBindMatricesDescription.count,
  1166. type : inverseBindMatricesDescription.type,
  1167. id : inverseBindMatricesDescription.bufferView,
  1168. name : skin.inverseBindMatricesDescription.id
  1169. };
  1170. var context = new InverseBindMatricesContext(paramObject, skin);
  1171. var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer(paramObject, inverseBindMatricesDelegate, context);
  1172. var bufferView = this.resources.getEntry(skin.inverseBindMatricesDescription.bufferView);
  1173. skin.inverseBindMatricesDescription.bufferView =
  1174. bufferView.object;
  1175. this.resources.setEntry(entryID, skin, description);
  1176. return true;
  1177. }
  1178. },
  1179. handleSampler: {
  1180. value: function(entryID, description, userInfo) {
  1181. // Save attribute entry
  1182. this.resources.setEntry(entryID, description, description);
  1183. return true;
  1184. }
  1185. },
  1186. handleTexture: {
  1187. value: function(entryID, description, userInfo) {
  1188. // Save attribute entry
  1189. this.resources.setEntry(entryID, null, description);
  1190. return true;
  1191. }
  1192. },
  1193. handleError: {
  1194. value: function(msg) {
  1195. throw new Error(msg);
  1196. return true;
  1197. }
  1198. },
  1199. _delegate: {
  1200. value: new LoadDelegate,
  1201. writable: true
  1202. },
  1203. delegate: {
  1204. enumerable: true,
  1205. get: function() {
  1206. return this._delegate;
  1207. },
  1208. set: function(value) {
  1209. this._delegate = value;
  1210. }
  1211. }
  1212. });
  1213. // Loader
  1214. var Context = function(rootObj, callback) {
  1215. this.rootObj = rootObj;
  1216. this.callback = callback;
  1217. };
  1218. var rootObj = new THREE.Object3D();
  1219. var self = this;
  1220. var loader = Object.create(ThreeGLTFLoader);
  1221. loader.initWithPath(url);
  1222. loader.load(new Context(rootObj,
  1223. function(obj) {
  1224. }),
  1225. null);
  1226. this.loader = loader;
  1227. this.callback = callback;
  1228. this.rootObj = rootObj;
  1229. return rootObj;
  1230. };
  1231. THREE.glTFLoader.prototype.callLoadedCallback = function() {
  1232. var result = {
  1233. scene : this.rootObj,
  1234. cameras : this.loader.cameras,
  1235. animations : this.loader.animations,
  1236. };
  1237. this.callback(result);
  1238. };
  1239. THREE.glTFLoader.prototype.checkComplete = function() {
  1240. if (this.meshesLoaded == this.meshesRequested
  1241. && this.shadersLoaded == this.shadersRequested
  1242. && this.animationsLoaded == this.animationsRequested)
  1243. {
  1244. for (var i = 0; i < this.pendingMeshes.length; i ++) {
  1245. var pending = this.pendingMeshes[i];
  1246. pending.mesh.attachToNode(pending.node);
  1247. }
  1248. for (var i = 0; i < this.animationsLoaded; i ++) {
  1249. var animation = this.animations[i];
  1250. this.loader.buildAnimation(animation);
  1251. }
  1252. this.loader.createAnimations();
  1253. this.loader.createMeshAnimations(this.rootObj);
  1254. this.callLoadedCallback();
  1255. }
  1256. };