glTFLoader.js 58 KB

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