glTFLoader.js 43 KB

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