glTFLoader.js 58 KB

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