glTFLoader.js 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962
  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. this.loadRequests = [];
  15. THREE.glTFShaders.removeAll();
  16. THREE.Loader.call( this );
  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 componentsPerElementForGLType(type) {
  33. switch(type) {
  34. case "SCALAR" :
  35. nElements = 1;
  36. break;
  37. case "VEC2" :
  38. nElements = 2;
  39. break;
  40. case "VEC3" :
  41. nElements = 3;
  42. break;
  43. case "VEC4" :
  44. nElements = 4;
  45. break;
  46. case "MAT2" :
  47. nElements = 4;
  48. break;
  49. case "MAT3" :
  50. nElements = 9;
  51. break;
  52. case "MAT4" :
  53. nElements = 16;
  54. break;
  55. default :
  56. debugger;
  57. break;
  58. }
  59. return nElements;
  60. }
  61. function replaceShaderDefinitions(shader, material) {
  62. // Three.js seems too dependent on attribute names so globally
  63. // replace those in the shader code
  64. var program = material.params.program;
  65. var shaderParams = material.params.technique.parameters;
  66. var shaderAttributes = material.params.technique.attributes;
  67. var params = {};
  68. for (var attribute in material.params.attributes) {
  69. var pname = shaderAttributes[attribute];
  70. var shaderParam = shaderParams[pname];
  71. var semantic = shaderParam.semantic;
  72. if (semantic) {
  73. params[attribute] = shaderParam;
  74. }
  75. }
  76. var s = shader;
  77. var r = "";
  78. for (var pname in params) {
  79. var param = params[pname];
  80. var semantic = param.semantic;
  81. r = eval("/" + pname + "/g");
  82. switch (semantic) {
  83. case "POSITION" :
  84. s = s.replace(r, 'position');
  85. break;
  86. case "NORMAL" :
  87. s = s.replace(r, 'normal');
  88. break;
  89. case "TEXCOORD_0" :
  90. s = s.replace(r, 'uv');
  91. break;
  92. case "WEIGHT" :
  93. s = s.replace(r, 'skinWeight');
  94. break;
  95. case "JOINT" :
  96. s = s.replace(r, 'skinIndex');
  97. break;
  98. default :
  99. break;
  100. }
  101. }
  102. return s;
  103. }
  104. function replaceShaderSemantics(material) {
  105. var vertexShader = theLoader.shaders[material.params.vertexShader];
  106. if (vertexShader) {
  107. vertexShader = replaceShaderDefinitions(vertexShader, material);
  108. theLoader.shaders[material.params.vertexShader] = vertexShader;
  109. }
  110. }
  111. function createShaderMaterial(material) {
  112. // replace named attributes and uniforms with Three.js built-ins
  113. replaceShaderSemantics(material);
  114. var fragmentShader = theLoader.shaders[material.params.fragmentShader];
  115. if (!fragmentShader) {
  116. console.log("ERROR: Missing fragment shader definition:", material.params.fragmentShader);
  117. return new THREE.MeshPhongMaterial;
  118. }
  119. var vertexShader = theLoader.shaders[material.params.vertexShader];
  120. if (!vertexShader) {
  121. console.log("ERROR: Missing vertex shader definition:", material.params.vertexShader);
  122. return new THREE.MeshPhongMaterial;
  123. }
  124. // clone most uniforms but then clobber textures, we want them to
  125. // be reused
  126. var uniforms = THREE.UniformsUtils.clone(material.params.uniforms);
  127. for (uniform in material.params.uniforms) {
  128. var src = material.params.uniforms[uniform];
  129. var dst = uniforms[uniform];
  130. if (dst.type == "t") {
  131. dst.value = src.value;
  132. }
  133. }
  134. var shaderMaterial = new THREE.RawShaderMaterial( {
  135. fragmentShader: fragmentShader,
  136. vertexShader: vertexShader,
  137. uniforms: uniforms,
  138. transparent: material.params.transparent,
  139. } );
  140. // console.log("New shader material")
  141. return shaderMaterial;
  142. }
  143. function LoadTexture(src) {
  144. if(!src) { return null; }
  145. var isDataUriRegex = /^data:/;
  146. var loadImage = function(url, success, error) {
  147. var image = new Image();
  148. image.onload = function() {
  149. success(image);
  150. };
  151. if (typeof error !== 'undefined') {
  152. image.onerror = error;
  153. }
  154. image.src = url;
  155. };
  156. function loadImageFromTypedArray(uint8Array, format) {
  157. //>>includeStart('debug', pragmas.debug);
  158. if (!defined(uint8Array)) {
  159. throw new DeveloperError('uint8Array is required.');
  160. }
  161. if (!defined(format)) {
  162. throw new DeveloperError('format is required.');
  163. }
  164. //>>includeEnd('debug');
  165. var blob = new Blob([uint8Array], {
  166. type : format
  167. });
  168. };
  169. function decodeDataUriText(isBase64, data) {
  170. var result = decodeURIComponent(data);
  171. if (isBase64) {
  172. return atob(result);
  173. }
  174. return result;
  175. }
  176. function decodeDataUriArrayBuffer(isBase64, data) {
  177. var byteString = decodeDataUriText(isBase64, data);
  178. var buffer = new ArrayBuffer(byteString.length);
  179. var view = new Uint8Array(buffer);
  180. for (var i = 0; i < byteString.length; i++) {
  181. view[i] = byteString.charCodeAt(i);
  182. }
  183. return buffer;
  184. }
  185. function decodeDataUri(dataUriRegexResult, responseType) {
  186. responseType = typeof responseType !== 'undefined' ? responseType : '';
  187. var mimeType = dataUriRegexResult[1];
  188. var isBase64 = !!dataUriRegexResult[2];
  189. var data = dataUriRegexResult[3];
  190. switch (responseType) {
  191. case '':
  192. case 'text':
  193. return decodeDataUriText(isBase64, data);
  194. case 'ArrayBuffer':
  195. return decodeDataUriArrayBuffer(isBase64, data);
  196. case 'blob':
  197. var buffer = decodeDataUriArrayBuffer(isBase64, data);
  198. return new Blob([buffer], {
  199. type : mimeType
  200. });
  201. case 'document':
  202. var parser = new DOMParser();
  203. return parser.parseFromString(decodeDataUriText(isBase64, data), mimeType);
  204. case 'json':
  205. return JSON.parse(decodeDataUriText(isBase64, data));
  206. default:
  207. throw 'Unhandled responseType: ' + responseType;
  208. }
  209. }
  210. var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
  211. var dataUriRegexResult = dataUriRegex.exec(src);
  212. if (dataUriRegexResult !== null) {
  213. var texture = new THREE.Texture;
  214. var blob = decodeDataUri(dataUriRegexResult, 'blob');
  215. var blobUrl = window.URL.createObjectURL(blob);
  216. loadImage(blobUrl, function(img) {
  217. texture.image = img;
  218. texture.needsUpdate = true;
  219. });
  220. return texture;
  221. }
  222. var textureLoader = THREE.Loader.Handlers.get(src);
  223. if ( textureLoader === null ) {
  224. textureLoader = new THREE.TextureLoader();
  225. }
  226. textureLoader.crossOrigin = true;
  227. return textureLoader.load(src);
  228. }
  229. function CreateTexture(resources, resource) {
  230. var texturePath = null;
  231. var textureParams = null;
  232. if (resource)
  233. {
  234. var texture = resource;
  235. if (texture) {
  236. var textureEntry = resources.getEntry(texture);
  237. if (textureEntry) {
  238. {
  239. var imageEntry = resources.getEntry(textureEntry.description.source);
  240. if (imageEntry) {
  241. texturePath = imageEntry.description.uri;
  242. }
  243. var samplerEntry = resources.getEntry(textureEntry.description.sampler);
  244. if (samplerEntry) {
  245. textureParams = samplerEntry.description;
  246. }
  247. }
  248. }
  249. }
  250. }
  251. var texture = LoadTexture(texturePath);
  252. if (texture && textureParams) {
  253. if (textureParams.wrapS == THREE.GLTFLoaderUtils.WEBGL_CONSTANTS.REPEAT)
  254. texture.wrapS = THREE.RepeatWrapping;
  255. if (textureParams.wrapT == THREE.GLTFLoaderUtils.WEBGL_CONSTANTS.REPEAT)
  256. texture.wrapT = THREE.RepeatWrapping;
  257. if (textureParams.magFilter == THREE.GLTFLoaderUtils.WEBGL_CONSTANTS.LINEAR)
  258. texture.magFilter = THREE.LinearFilter;
  259. // if (textureParams.minFilter == "LINEAR")
  260. // texture.minFilter = THREE.LinearFilter;
  261. }
  262. return texture;
  263. }
  264. // Geometry processing
  265. var ClassicGeometry = function() {
  266. this.geometry = new THREE.BufferGeometry;
  267. this.totalAttributes = 0;
  268. this.loadedAttributes = 0;
  269. this.indicesLoaded = false;
  270. this.finished = false;
  271. this.onload = null;
  272. this.uvs = null;
  273. this.indexArray = null;
  274. };
  275. ClassicGeometry.prototype.constructor = ClassicGeometry;
  276. ClassicGeometry.prototype.buildBufferGeometry = function() {
  277. // Build indexed mesh
  278. var geometry = this.geometry;
  279. geometry.setIndex(new THREE.BufferAttribute( this.indexArray, 1 ) );
  280. var offset = {
  281. start: 0,
  282. index: 0,
  283. count: this.indexArray.length
  284. };
  285. geometry.groups.push( offset );
  286. geometry.computeBoundingSphere();
  287. }
  288. ClassicGeometry.prototype.checkFinished = function() {
  289. if(this.indexArray && this.loadedAttributes === this.totalAttributes) {
  290. this.buildBufferGeometry();
  291. this.finished = true;
  292. if(this.onload) {
  293. this.onload();
  294. }
  295. }
  296. };
  297. // Delegate for processing index buffers
  298. var IndicesDelegate = function() {};
  299. IndicesDelegate.prototype.handleError = function(errorCode, info) {
  300. // FIXME: report error
  301. console.log("ERROR(IndicesDelegate):"+errorCode+":"+info);
  302. };
  303. IndicesDelegate.prototype.convert = function(resource, ctx) {
  304. return new Uint16Array(resource, 0, ctx.indices.count);
  305. };
  306. IndicesDelegate.prototype.resourceAvailable = function(glResource, ctx) {
  307. var geometry = ctx.geometry;
  308. geometry.indexArray = glResource;
  309. geometry.checkFinished();
  310. return true;
  311. };
  312. var indicesDelegate = new IndicesDelegate();
  313. var IndicesContext = function(indices, geometry) {
  314. this.indices = indices;
  315. this.geometry = geometry;
  316. };
  317. // Delegate for processing vertex attribute buffers
  318. var VertexAttributeDelegate = function() {};
  319. VertexAttributeDelegate.prototype.handleError = function(errorCode, info) {
  320. // FIXME: report error
  321. console.log("ERROR(VertexAttributeDelegate):"+errorCode+":"+info);
  322. };
  323. VertexAttributeDelegate.prototype.convert = function(resource, ctx) {
  324. return resource;
  325. };
  326. VertexAttributeDelegate.prototype.bufferResourceAvailable = function(glResource, ctx) {
  327. var geom = ctx.geometry;
  328. var attribute = ctx.attribute;
  329. var semantic = ctx.semantic;
  330. var floatArray;
  331. var i, l;
  332. var nComponents;
  333. //FIXME: Float32 is assumed here, but should be checked.
  334. if (semantic == "POSITION") {
  335. // TODO: Should be easy to take strides into account here
  336. floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
  337. geom.geometry.addAttribute( 'position', new THREE.BufferAttribute( floatArray, 3 ) );
  338. } else if (semantic == "NORMAL") {
  339. nComponents = componentsPerElementForGLType(attribute.type);
  340. floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
  341. geom.geometry.addAttribute( 'normal', new THREE.BufferAttribute( floatArray, 3 ) );
  342. } else if ((semantic == "TEXCOORD_0") || (semantic == "TEXCOORD" )) {
  343. nComponents = componentsPerElementForGLType(attribute.type);
  344. floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
  345. // N.B.: flip Y value... should we just set texture.flipY everywhere?
  346. for (i = 0; i < floatArray.length / 2; i++) {
  347. floatArray[i*2+1] = 1.0 - floatArray[i*2+1];
  348. }
  349. geom.geometry.addAttribute( 'uv', new THREE.BufferAttribute( floatArray, nComponents ) );
  350. }
  351. else if (semantic == "WEIGHT") {
  352. nComponents = componentsPerElementForGLType(attribute.type);
  353. floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
  354. geom.geometry.addAttribute( 'skinWeight', new THREE.BufferAttribute( floatArray, nComponents ) );
  355. }
  356. else if (semantic == "JOINT") {
  357. nComponents = componentsPerElementForGLType(attribute.type);
  358. floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
  359. geom.geometry.addAttribute( 'skinIndex', new THREE.BufferAttribute( floatArray, nComponents ) );
  360. }
  361. }
  362. VertexAttributeDelegate.prototype.resourceAvailable = function(glResource, ctx) {
  363. this.bufferResourceAvailable(glResource, ctx);
  364. var geom = ctx.geometry;
  365. geom.loadedAttributes++;
  366. geom.checkFinished();
  367. return true;
  368. };
  369. var vertexAttributeDelegate = new VertexAttributeDelegate();
  370. var VertexAttributeContext = function(attribute, semantic, geometry) {
  371. this.attribute = attribute;
  372. this.semantic = semantic;
  373. this.geometry = geometry;
  374. };
  375. var Mesh = function() {
  376. this.primitives = [];
  377. this.materialsPending = [];
  378. this.loadedGeometry = 0;
  379. this.onCompleteCallbacks = [];
  380. };
  381. Mesh.prototype.addPrimitive = function(geometry, material) {
  382. var self = this;
  383. geometry.onload = function() {
  384. self.loadedGeometry++;
  385. self.checkComplete();
  386. };
  387. this.primitives.push({
  388. geometry: geometry,
  389. material: material,
  390. mesh: null
  391. });
  392. };
  393. Mesh.prototype.onComplete = function(callback) {
  394. this.onCompleteCallbacks.push(callback);
  395. //this.checkComplete();
  396. };
  397. Mesh.prototype.checkComplete = function() {
  398. var self = this;
  399. if(this.onCompleteCallbacks.length && this.primitives.length == this.loadedGeometry) {
  400. this.onCompleteCallbacks.forEach(function(callback) {
  401. callback(self);
  402. });
  403. this.onCompleteCallbacks = [];
  404. }
  405. };
  406. Mesh.prototype.attachToNode = function(threeNode) {
  407. // Assumes that the geometry is complete
  408. var that = this;
  409. this.primitives.forEach(function(primitive) {
  410. /*if(!primitive.mesh) {
  411. primitive.mesh = new THREE.Mesh(primitive.geometry, primitive.material);
  412. }*/
  413. var material = primitive.material;
  414. var materialParams = material.params;
  415. if (!(material instanceof THREE.Material)) {
  416. material = createShaderMaterial(material);
  417. }
  418. if (!that.skin) {
  419. // console.log ("New mesh")
  420. var threeMesh = new THREE.Mesh(primitive.geometry.geometry, material);
  421. threeMesh.castShadow = true;
  422. threeNode.add(threeMesh);
  423. if (material instanceof THREE.ShaderMaterial) {
  424. var glTFShader = new THREE.glTFShader(material, materialParams, threeMesh, theLoader.rootObj);
  425. THREE.glTFShaders.add(glTFShader);
  426. }
  427. }
  428. });
  429. };
  430. // Delayed-loaded material
  431. var Material = function(params) {
  432. this.params = params;
  433. };
  434. // Delegate for processing animation parameter buffers
  435. var AnimationParameterDelegate = function() {};
  436. AnimationParameterDelegate.prototype.handleError = function(errorCode, info) {
  437. // FIXME: report error
  438. console.log("ERROR(AnimationParameterDelegate):"+errorCode+":"+info);
  439. };
  440. AnimationParameterDelegate.prototype.convert = function(resource, ctx) {
  441. var parameter = ctx.parameter;
  442. var glResource = null;
  443. switch (parameter.type) {
  444. case "SCALAR" :
  445. case "VEC2" :
  446. case "VEC3" :
  447. case "VEC4" :
  448. glResource = new Float32Array(resource, 0, parameter.count * componentsPerElementForGLType(parameter.type));
  449. break;
  450. default:
  451. break;
  452. }
  453. return glResource;
  454. };
  455. AnimationParameterDelegate.prototype.resourceAvailable = function(glResource, ctx) {
  456. var animation = ctx.animation;
  457. var parameter = ctx.parameter;
  458. parameter.data = glResource;
  459. animation.handleParameterLoaded(parameter);
  460. return true;
  461. };
  462. var animationParameterDelegate = new AnimationParameterDelegate();
  463. var AnimationParameterContext = function(parameter, animation) {
  464. this.parameter = parameter;
  465. this.animation = animation;
  466. };
  467. // Animations
  468. var Animation = function() {
  469. // create Three.js keyframe here
  470. this.totalParameters = 0;
  471. this.loadedParameters = 0;
  472. this.parameters = {};
  473. this.finishedLoading = false;
  474. this.onload = null;
  475. };
  476. Animation.prototype.constructor = Animation;
  477. Animation.prototype.handleParameterLoaded = function(parameter) {
  478. this.parameters[parameter.name] = parameter;
  479. this.loadedParameters++;
  480. this.checkFinished();
  481. };
  482. Animation.prototype.checkFinished = function() {
  483. if(this.loadedParameters === this.totalParameters) {
  484. // Build animation
  485. this.finishedLoading = true;
  486. if (this.onload) {
  487. this.onload();
  488. }
  489. }
  490. };
  491. // Delegate for processing inverse bind matrices buffer
  492. var InverseBindMatricesDelegate = function() {};
  493. InverseBindMatricesDelegate.prototype.handleError = function(errorCode, info) {
  494. // FIXME: report error
  495. console.log("ERROR(InverseBindMatricesDelegate):"+errorCode+":"+info);
  496. };
  497. InverseBindMatricesDelegate.prototype.convert = function(resource, ctx) {
  498. var parameter = ctx.parameter;
  499. var glResource = null;
  500. switch (parameter.type) {
  501. case "MAT4" :
  502. glResource = new Float32Array(resource, 0, parameter.count * componentsPerElementForGLType(parameter.type));
  503. break;
  504. default:
  505. break;
  506. }
  507. return glResource;
  508. };
  509. InverseBindMatricesDelegate.prototype.resourceAvailable = function(glResource, ctx) {
  510. var skin = ctx.skin;
  511. skin.inverseBindMatrices = glResource;
  512. return true;
  513. };
  514. var inverseBindMatricesDelegate = new InverseBindMatricesDelegate();
  515. var InverseBindMatricesContext = function(param, skin) {
  516. this.parameter = param;
  517. this.skin = skin;
  518. };
  519. // Delegate for processing shaders from external files
  520. var ShaderDelegate = function() {};
  521. ShaderDelegate.prototype.handleError = function(errorCode, info) {
  522. // FIXME: report error
  523. console.log("ERROR(ShaderDelegate):"+errorCode+":"+info);
  524. };
  525. ShaderDelegate.prototype.convert = function(resource, ctx) {
  526. return resource;
  527. }
  528. ShaderDelegate.prototype.resourceAvailable = function(data, ctx) {
  529. theLoader.shadersLoaded++;
  530. theLoader.shaders[ctx.id] = data;
  531. return true;
  532. };
  533. var shaderDelegate = new ShaderDelegate();
  534. var ShaderContext = function(id, path) {
  535. this.id = id;
  536. this.uri = path;
  537. };
  538. // Resource management
  539. var ResourceEntry = function(entryID, object, description) {
  540. this.entryID = entryID;
  541. this.object = object;
  542. this.description = description;
  543. };
  544. var Resources = function() {
  545. this._entries = {};
  546. };
  547. Resources.prototype.setEntry = function(entryID, object, description) {
  548. if (!entryID) {
  549. console.error("No EntryID provided, cannot store", description);
  550. return;
  551. }
  552. if (this._entries[entryID]) {
  553. console.warn("entry["+entryID+"] is being overwritten");
  554. }
  555. this._entries[entryID] = new ResourceEntry(entryID, object, description );
  556. };
  557. Resources.prototype.getEntry = function(entryID) {
  558. return this._entries[entryID];
  559. };
  560. Resources.prototype.clearEntries = function() {
  561. this._entries = {};
  562. };
  563. LoadDelegate = function() {
  564. }
  565. LoadDelegate.prototype.loadCompleted = function(callback, obj) {
  566. callback.call(Window, obj);
  567. }
  568. // Loader
  569. var ThreeGLTFLoader = Object.create(glTFParser, {
  570. load: {
  571. enumerable: true,
  572. value: function(userInfo, options) {
  573. this.resources = new Resources();
  574. this.cameras = [];
  575. this.lights = [];
  576. this.animations = [];
  577. this.joints = {};
  578. THREE.GLTFLoaderUtils.init();
  579. glTFParser.load.call(this, userInfo, options);
  580. }
  581. },
  582. cameras: {
  583. enumerable: true,
  584. writable: true,
  585. value : []
  586. },
  587. lights: {
  588. enumerable: true,
  589. writable: true,
  590. value : []
  591. },
  592. animations: {
  593. enumerable: true,
  594. writable: true,
  595. value : []
  596. },
  597. // Implement WebGLTFLoader handlers
  598. handleBuffer: {
  599. value: function(entryID, description, userInfo) {
  600. this.resources.setEntry(entryID, null, description);
  601. description.type = "ArrayBuffer";
  602. return true;
  603. }
  604. },
  605. handleBufferView: {
  606. value: function(entryID, description, userInfo) {
  607. this.resources.setEntry(entryID, null, description);
  608. var buffer = this.resources.getEntry(description.buffer);
  609. description.type = "ArrayBufferView";
  610. var bufferViewEntry = this.resources.getEntry(entryID);
  611. bufferViewEntry.buffer = buffer;
  612. return true;
  613. }
  614. },
  615. handleShader: {
  616. value: function(entryID, description, userInfo) {
  617. this.resources.setEntry(entryID, null, description);
  618. var shaderRequest = {
  619. id : entryID,
  620. uri : description.uri,
  621. };
  622. var shaderContext = new ShaderContext(entryID, description.uri);
  623. theLoader.shadersRequested++;
  624. THREE.GLTFLoaderUtils.getFile(shaderRequest, shaderDelegate, shaderContext);
  625. return true;
  626. }
  627. },
  628. handleProgram: {
  629. value: function(entryID, description, userInfo) {
  630. this.resources.setEntry(entryID, null, description);
  631. return true;
  632. }
  633. },
  634. handleTechnique: {
  635. value: function(entryID, description, userInfo) {
  636. description.refCount = 0;
  637. this.resources.setEntry(entryID, null, description);
  638. return true;
  639. }
  640. },
  641. createShaderParams : {
  642. value: function(materialId, values, params, programID, technique) {
  643. var program = this.resources.getEntry(programID);
  644. params.uniforms = {};
  645. params.attributes = {};
  646. params.program = program;
  647. params.technique = technique;
  648. if (program) {
  649. params.fragmentShader = program.description.fragmentShader;
  650. params.vertexShader = program.description.vertexShader;
  651. for (var uniform in technique.uniforms) {
  652. var pname = technique.uniforms[uniform];
  653. var shaderParam = technique.parameters[pname];
  654. var ptype = shaderParam.type;
  655. var pcount = shaderParam.count;
  656. var value = values[pname];
  657. var utype = "";
  658. var uvalue;
  659. var ulength;
  660. // THIS: for (n in WebGLRenderingContext) { z = WebGLRenderingContext[n]; idx[z] = n; }
  661. //console.log("shader uniform param type: ", ptype, "-", theLoader.idx[ptype])
  662. switch (ptype) {
  663. case THREE.GLTFLoaderUtils.WEBGL_CONSTANTS.FLOAT :
  664. utype = "f";
  665. uvalue = shaderParam.value;
  666. if (pname == "transparency") {
  667. var USE_A_ONE = true; // for now, hack because file format isn't telling us
  668. var opacity = USE_A_ONE ? value : (1.0 - value);
  669. uvalue = opacity;
  670. params.transparent = true;
  671. }
  672. break;
  673. case THREE.GLTFLoaderUtils.WEBGL_CONSTANTS.FLOAT_VEC2 :
  674. utype = "v2";
  675. uvalue = new THREE.Vector2;
  676. if (shaderParam && shaderParam.value) {
  677. var v2 = shaderParam.value;
  678. uvalue.fromArray(v2);
  679. }
  680. if (value) {
  681. uvalue.fromArray(value);
  682. }
  683. break;
  684. case THREE.GLTFLoaderUtils.WEBGL_CONSTANTS.FLOAT_VEC3 :
  685. utype = "v3";
  686. uvalue = new THREE.Vector3;
  687. if (shaderParam && shaderParam.value) {
  688. var v3 = shaderParam.value;
  689. uvalue.fromArray(v3);
  690. }
  691. if (value) {
  692. uvalue.fromArray(value);
  693. }
  694. break;
  695. case THREE.GLTFLoaderUtils.WEBGL_CONSTANTS.FLOAT_VEC4 :
  696. utype = "v4";
  697. uvalue = new THREE.Vector4;
  698. if (shaderParam && shaderParam.value) {
  699. var v4 = shaderParam.value;
  700. uvalue.fromArray(v4);
  701. }
  702. if (value) {
  703. uvalue.fromArray(value);
  704. }
  705. break;
  706. case THREE.GLTFLoaderUtils.WEBGL_CONSTANTS.FLOAT_MAT2 :
  707. // what to do?
  708. console.log("Warning: FLOAT_MAT2");
  709. break;
  710. case THREE.GLTFLoaderUtils.WEBGL_CONSTANTS.FLOAT_MAT3 :
  711. utype = "m3";
  712. uvalue = new THREE.Matrix3;
  713. if (shaderParam && shaderParam.value) {
  714. var m3 = shaderParam.value;
  715. uvalue.fromArray(m3);
  716. }
  717. if (value) {
  718. uvalue.fromArray(value);
  719. }
  720. break;
  721. case THREE.GLTFLoaderUtils.WEBGL_CONSTANTS.FLOAT_MAT4 :
  722. if (pcount !== undefined) {
  723. utype = "m4v";
  724. uvalue = new Array(pcount);
  725. for (var mi = 0; mi < pcount; mi++) {
  726. uvalue[mi] = new THREE.Matrix4;
  727. }
  728. ulength = pcount;
  729. if (shaderParam && shaderParam.value) {
  730. var m4v = shaderParam.value;
  731. uvalue.fromArray(m4v);
  732. }
  733. if (value) {
  734. uvalue.fromArray(value);
  735. }
  736. }
  737. else {
  738. utype = "m4";
  739. uvalue = new THREE.Matrix4;
  740. if (shaderParam && shaderParam.value) {
  741. var m4 = shaderParam.value;
  742. uvalue.fromArray(m4);
  743. }
  744. if (value) {
  745. uvalue.fromArray(value);
  746. }
  747. }
  748. break;
  749. case THREE.GLTFLoaderUtils.WEBGL_CONSTANTS.SAMPLER_2D :
  750. utype = "t";
  751. uvalue = value ? CreateTexture(this.resources, value) : null;
  752. break;
  753. default :
  754. throw new Error("Unknown shader uniform param type: " + ptype + " - " + theLoader.idx[ptype]);
  755. break;
  756. }
  757. var udecl = { type : utype, value : uvalue, length : ulength };
  758. params.uniforms[uniform] = udecl;
  759. }
  760. for (var attribute in technique.attributes) {
  761. var pname = technique.attributes[attribute];
  762. var param = technique.parameters[pname];
  763. var atype = param.type;
  764. var semantic = param.semantic;
  765. var adecl = { type : atype, semantic : semantic };
  766. params.attributes[attribute] = adecl;
  767. }
  768. }
  769. }
  770. },
  771. threeJSMaterialType : {
  772. value: function(materialId, material, params) {
  773. var extensions = material.extensions;
  774. var khr_material = extensions ? extensions.KHR_materials_common : null;
  775. var materialType = null;
  776. var values;
  777. if (khr_material) {
  778. switch (khr_material.technique)
  779. {
  780. case 'BLINN' :
  781. case 'PHONG' :
  782. materialType = THREE.MeshPhongMaterial;
  783. break;
  784. case 'LAMBERT' :
  785. materialType = THREE.MeshLambertMaterial;
  786. break;
  787. case 'CONSTANT' :
  788. default :
  789. materialType = THREE.MeshBasicMaterial;
  790. break;
  791. }
  792. if (khr_material.doubleSided)
  793. {
  794. params.side = THREE.DoubleSide;
  795. }
  796. if (khr_material.transparent)
  797. {
  798. params.transparent = true;
  799. }
  800. values = {};
  801. for (prop in khr_material.values) {
  802. values[prop] = khr_material.values[prop];
  803. }
  804. }
  805. else if (material.technique === undefined) {
  806. materialType = THREE.MeshPhongMaterial;
  807. if (material.doubleSided)
  808. {
  809. params.side = THREE.DoubleSide;
  810. }
  811. if (material.transparent)
  812. {
  813. params.transparent = true;
  814. }
  815. values = {};
  816. for (var prop in material.values) {
  817. values[prop] = material.values[prop];
  818. }
  819. }
  820. else {
  821. var technique = this.resources.getEntry(material.technique);
  822. values = {};
  823. for (var prop in material.values) {
  824. values[prop] = material.values[prop];
  825. }
  826. var description = technique.description;
  827. if (++description.refCount > 1) {
  828. //console.log("refcount", description.refCount);
  829. }
  830. var programID = description.program;
  831. this.createShaderParams(materialId, values, params, programID, description);
  832. var loadshaders = true;
  833. if (loadshaders) {
  834. materialType = Material;
  835. }
  836. }
  837. if (values.diffuse && typeof(values.diffuse) == 'string') {
  838. params.map = CreateTexture(this.resources, values.diffuse);
  839. }
  840. if (values.reflective && typeof(values.reflective) == 'string') {
  841. params.envMap = CreateTexture(this.resources, values.reflective);
  842. }
  843. var shininess = values.shininesss || values.shininess; // N.B.: typo in converter!
  844. if (shininess)
  845. {
  846. shininess = shininess;
  847. }
  848. var diffuseColor = null;
  849. if (!params.map) {
  850. diffuseColor = values.diffuse;
  851. }
  852. var opacity = 1.0;
  853. if (values.hasOwnProperty("transparency"))
  854. {
  855. var USE_A_ONE = true; // for now, hack because file format isn't telling us
  856. opacity = USE_A_ONE ? values.transparency : (1.0 - values.transparency);
  857. }
  858. // if (diffuseColor) diffuseColor = [0, 1, 0];
  859. params.color = RgbArraytoHex(diffuseColor);
  860. params.opacity = opacity;
  861. params.transparent = opacity < 1.0;
  862. // hack hack hack
  863. if (params.map && params.map.sourceFile.toLowerCase().indexOf(".png") != -1)
  864. params.transparent = true;
  865. if (!(shininess === undefined))
  866. {
  867. params.shininess = Math.max( shininess, 1e-4 );
  868. }
  869. delete params.ambient;
  870. if (!(values.ambient === undefined) && !(typeof(values.ambient) == 'string'))
  871. {
  872. //params.ambient = RgbArraytoHex(values.ambient);
  873. }
  874. if (!(values.emission === undefined))
  875. {
  876. params.emissive = RgbArraytoHex(values.emission);
  877. }
  878. if (!(values.specular === undefined))
  879. {
  880. params.specular = RgbArraytoHex(values.specular);
  881. }
  882. return materialType;
  883. }
  884. },
  885. handleMaterial: {
  886. value: function(entryID, description, userInfo) {
  887. var params = {};
  888. var materialType = this.threeJSMaterialType(entryID, description, params);
  889. var material = new materialType(params);
  890. this.resources.setEntry(entryID, material, description);
  891. return true;
  892. }
  893. },
  894. handleMesh: {
  895. value: function(entryID, description, userInfo) {
  896. var mesh = new Mesh();
  897. this.resources.setEntry(entryID, mesh, description);
  898. var primitivesDescription = description.primitives;
  899. if (!primitivesDescription) {
  900. //FIXME: not implemented in delegate
  901. console.log("MISSING_PRIMITIVES for mesh:"+ entryID);
  902. return false;
  903. }
  904. for (var i = 0 ; i < primitivesDescription.length ; i++) {
  905. var primitiveDescription = primitivesDescription[i];
  906. if (primitiveDescription.mode === THREE.GLTFLoaderUtils.WEBGL_CONSTANTS.TRIANGLES) {
  907. var geometry = new ClassicGeometry();
  908. var materialEntry = this.resources.getEntry(primitiveDescription.material);
  909. mesh.addPrimitive(geometry, materialEntry.object);
  910. var allAttributes = Object.keys(primitiveDescription.attributes);
  911. // count them first, async issues otherwise
  912. allAttributes.forEach( function(semantic) {
  913. geometry.totalAttributes++;
  914. }, this);
  915. var indices = this.resources.getEntry(primitiveDescription.indices);
  916. var bufferEntry = this.resources.getEntry(indices.description.bufferView);
  917. var indicesObject = {
  918. bufferView : bufferEntry,
  919. byteOffset : indices.description.byteOffset,
  920. count : indices.description.count,
  921. id : indices.entryID,
  922. componentType : indices.description.componentType,
  923. type : indices.description.type
  924. };
  925. var indicesContext = new IndicesContext(indicesObject, geometry);
  926. var loaddata = {
  927. indicesObject : indicesObject,
  928. indicesDelegate : indicesDelegate,
  929. indicesContext : indicesContext
  930. };
  931. theLoader.scheduleLoad(function(data) {
  932. var alreadyProcessedIndices =
  933. THREE.GLTFLoaderUtils.getBuffer(data.indicesObject,
  934. data.indicesDelegate, data.indicesContext);
  935. if (alreadyProcessedIndices) {
  936. data.indicesDelegate.resourceAvailable(
  937. alreadyProcessedIndices, data.indicesContext);
  938. }
  939. }, loaddata);
  940. // Load Vertex Attributes
  941. allAttributes.forEach( function(semantic) {
  942. var attribute;
  943. var attributeID = primitiveDescription.attributes[semantic];
  944. var attributeEntry = this.resources.getEntry(attributeID);
  945. if (!attributeEntry) {
  946. //let's just use an anonymous object for the attribute
  947. attribute = description.attributes[attributeID];
  948. attribute.id = attributeID;
  949. this.resources.setEntry(attributeID, attribute, attribute);
  950. var bufferEntry = this.resources.getEntry(attribute.bufferView);
  951. attributeEntry = this.resources.getEntry(attributeID);
  952. } else {
  953. attribute = attributeEntry.object;
  954. attribute.id = attributeID;
  955. var bufferEntry = this.resources.getEntry(attribute.bufferView);
  956. }
  957. var attributeObject = {
  958. bufferView : bufferEntry,
  959. byteOffset : attribute.byteOffset,
  960. byteStride : attribute.byteStride,
  961. count : attribute.count,
  962. max : attribute.max,
  963. min : attribute.min,
  964. componentType : attribute.componentType,
  965. type : attribute.type,
  966. id : attributeID
  967. };
  968. var attribContext = new VertexAttributeContext(attributeObject, semantic, geometry);
  969. var loaddata = {
  970. attributeObject : attributeObject,
  971. vertexAttributeDelegate : vertexAttributeDelegate,
  972. attribContext : attribContext
  973. };
  974. theLoader.scheduleLoad(function(data) {
  975. var alreadyProcessedAttribute =
  976. THREE.GLTFLoaderUtils.getBuffer(data.attributeObject,
  977. data.vertexAttributeDelegate, data.attribContext);
  978. if (alreadyProcessedAttribute) {
  979. data.vertexAttributeDelegate.resourceAvailable(
  980. alreadyProcessedAttribute, data.attribContext);
  981. }
  982. }, loaddata);
  983. }, this);
  984. }
  985. }
  986. return true;
  987. }
  988. },
  989. handleCamera: {
  990. value: function(entryID, description, userInfo) {
  991. var camera;
  992. if (description.type == "perspective")
  993. {
  994. var znear = description.perspective.znear;
  995. var zfar = description.perspective.zfar;
  996. var yfov = description.perspective.yfov;
  997. var xfov = description.perspective.xfov;
  998. var aspect_ratio = description.perspective.aspect_ratio;
  999. if (!aspect_ratio)
  1000. aspect_ratio = 1;
  1001. if (xfov === undefined) {
  1002. if (yfov)
  1003. {
  1004. // According to COLLADA spec...
  1005. // aspect_ratio = xfov / yfov
  1006. xfov = yfov * aspect_ratio;
  1007. }
  1008. }
  1009. if (yfov === undefined)
  1010. {
  1011. if (xfov)
  1012. {
  1013. // According to COLLADA spec...
  1014. // aspect_ratio = xfov / yfov
  1015. yfov = xfov / aspect_ratio;
  1016. }
  1017. }
  1018. if (xfov)
  1019. {
  1020. xfov = THREE.Math.radToDeg(xfov);
  1021. camera = new THREE.PerspectiveCamera(xfov, aspect_ratio, znear, zfar);
  1022. }
  1023. }
  1024. else
  1025. {
  1026. camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, znear, zfar );
  1027. }
  1028. if (camera)
  1029. {
  1030. this.resources.setEntry(entryID, camera, description);
  1031. }
  1032. return true;
  1033. }
  1034. },
  1035. handleLight: {
  1036. value: function(entryID, description, userInfo) {
  1037. var light = null;
  1038. var type = description.type;
  1039. if (type && description[type])
  1040. {
  1041. var lparams = description[type];
  1042. var color = RgbArraytoHex(lparams.color);
  1043. switch (type) {
  1044. case "directional" :
  1045. light = new THREE.DirectionalLight(color);
  1046. light.position.set(0, 0, 1);
  1047. break;
  1048. case "point" :
  1049. light = new THREE.PointLight(color);
  1050. break;
  1051. case "spot " :
  1052. light = new THREE.SpotLight(color);
  1053. light.position.set(0, 0, 1);
  1054. break;
  1055. case "ambient" :
  1056. light = new THREE.AmbientLight(color);
  1057. break;
  1058. }
  1059. }
  1060. if (light)
  1061. {
  1062. this.resources.setEntry(entryID, light, description);
  1063. }
  1064. return true;
  1065. }
  1066. },
  1067. addPendingMesh: {
  1068. value: function(mesh, threeNode) {
  1069. theLoader.pendingMeshes.push({
  1070. mesh: mesh,
  1071. node: threeNode
  1072. });
  1073. }
  1074. },
  1075. handleNode: {
  1076. value: function(entryID, description, userInfo) {
  1077. var threeNode = null;
  1078. if (description.jointName) {
  1079. threeNode = new THREE.Bone();
  1080. threeNode.jointName = description.jointName;
  1081. this.joints[description.jointName] = entryID;
  1082. }
  1083. else {
  1084. threeNode = new THREE.Object3D();
  1085. }
  1086. threeNode.name = description.name;
  1087. threeNode.glTFID = entryID;
  1088. threeNode.glTF = description;
  1089. this.resources.setEntry(entryID, threeNode, description);
  1090. var m = description.matrix;
  1091. if(m) {
  1092. threeNode.matrixAutoUpdate = false;
  1093. threeNode.applyMatrix(new THREE.Matrix4().set(
  1094. m[0], m[4], m[8], m[12],
  1095. m[1], m[5], m[9], m[13],
  1096. m[2], m[6], m[10], m[14],
  1097. m[3], m[7], m[11], m[15]
  1098. ));
  1099. }
  1100. else {
  1101. var t = description.translation;
  1102. var r = description.rotation;
  1103. var s = description.scale;
  1104. var position = t ? new THREE.Vector3(t[0], t[1], t[2]) :
  1105. new THREE.Vector3;
  1106. var rotation = r ? new THREE.Quaternion(r[0], r[1], r[2], r[3]) :
  1107. new THREE.Quaternion;
  1108. var scale = s ? new THREE.Vector3(s[0], s[1], s[2]) :
  1109. new THREE.Vector3(1, 1, 1);
  1110. var matrix = new THREE.Matrix4;
  1111. matrix.compose(position, rotation, scale);
  1112. threeNode.matrixAutoUpdate = false;
  1113. threeNode.applyMatrix(matrix);
  1114. }
  1115. var self = this;
  1116. if (description.meshes) {
  1117. description.meshInstances = {};
  1118. var skinEntry;
  1119. if (description.skin) {
  1120. skinEntry = this.resources.getEntry(description.skin);
  1121. }
  1122. description.meshes.forEach( function(meshID) {
  1123. meshEntry = this.resources.getEntry(meshID);
  1124. theLoader.meshesRequested++;
  1125. meshEntry.object.onComplete(function(mesh) {
  1126. self.addPendingMesh(mesh, threeNode);
  1127. description.meshInstances[meshID] = meshEntry.object;
  1128. if (skinEntry) {
  1129. mesh.skin = skinEntry;
  1130. description.instanceSkin = skinEntry.object;
  1131. }
  1132. theLoader.meshesLoaded++;
  1133. theLoader.checkComplete();
  1134. });
  1135. }, this);
  1136. }
  1137. if (description.camera) {
  1138. var cameraEntry = this.resources.getEntry(description.camera);
  1139. if (cameraEntry) {
  1140. threeNode.add(cameraEntry.object);
  1141. this.cameras.push(cameraEntry.object);
  1142. }
  1143. }
  1144. if (description.extensions && description.extensions.KHR_materials_common
  1145. && description.extensions.KHR_materials_common.light) {
  1146. var lightID = description.extensions.KHR_materials_common.light;
  1147. var lightEntry = this.resources.getEntry(lightID);
  1148. if (lightEntry) {
  1149. threeNode.add(lightEntry.object);
  1150. this.lights.push(lightEntry.object);
  1151. }
  1152. }
  1153. return true;
  1154. }
  1155. },
  1156. handleExtension: {
  1157. value: function(entryID, description, userInfo) {
  1158. // console.log("Extension", entryID, description);
  1159. switch (entryID) {
  1160. case 'KHR_materials_common' :
  1161. var lights = description.lights;
  1162. for (lightID in lights) {
  1163. var light = lights[lightID];
  1164. this.handleLight(lightID, light);
  1165. }
  1166. break;
  1167. }
  1168. return true;
  1169. }
  1170. },
  1171. buildNodeHirerachy: {
  1172. value: function(nodeEntryId, parentThreeNode) {
  1173. var nodeEntry = this.resources.getEntry(nodeEntryId);
  1174. var threeNode = nodeEntry.object;
  1175. parentThreeNode.add(threeNode);
  1176. var children = nodeEntry.description.children;
  1177. if (children) {
  1178. children.forEach( function(childID) {
  1179. this.buildNodeHirerachy(childID, threeNode);
  1180. }, this);
  1181. }
  1182. return threeNode;
  1183. }
  1184. },
  1185. buildSkin: {
  1186. value: function(node) {
  1187. var glTF = node.glTF;
  1188. var skin = glTF.instanceSkin;
  1189. var skeletons = glTF.skeletons;
  1190. if (skin) {
  1191. skeletons.forEach(function(skeleton) {
  1192. var nodeEntry = this.resources.getEntry(skeleton);
  1193. if (nodeEntry) {
  1194. var rootSkeleton = nodeEntry.object;
  1195. node.add(rootSkeleton);
  1196. var dobones = true;
  1197. for (meshID in glTF.meshInstances) {
  1198. var mesh = glTF.meshInstances[meshID];
  1199. var threeMesh = null;
  1200. mesh.primitives.forEach(function(primitive) {
  1201. var material = primitive.material;
  1202. var materialParams = material.params;
  1203. if (!(material instanceof THREE.Material)) {
  1204. material = createShaderMaterial(material);
  1205. }
  1206. threeMesh = new THREE.SkinnedMesh(primitive.geometry.geometry, material, false);
  1207. var geometry = primitive.geometry.geometry;
  1208. var j;
  1209. /* if (geometry.vertices) {
  1210. for ( j = 0; j < geometry.vertices.length; j ++ ) {
  1211. geometry.vertices[j].applyMatrix4( skin.bindShapeMatrix );
  1212. }
  1213. }
  1214. else if (geometry.attributes.position) {
  1215. var a = geometry.attributes.position.array;
  1216. var v = new THREE.Vector3;
  1217. for ( j = 0; j < a.length / 3; j++ ) {
  1218. v.set(a[j * 3], a[j * 3 + 1], a[j * 3 + 2]);
  1219. v.applyMatrix4( skin.bindShapeMatrix );
  1220. a[j * 3] = v.x;
  1221. a[j * 3 + 1] = v.y;
  1222. a[j * 3 + 2] = v.z;
  1223. }
  1224. }*/
  1225. if (threeMesh && dobones) {
  1226. material.skinning = true;
  1227. var jointNames = skin.jointNames;
  1228. var joints = [];
  1229. var bones = [];
  1230. var boneInverses = [];
  1231. var i, len = jointNames.length;
  1232. for (i = 0; i < len; i++) {
  1233. var jointName = jointNames[i];
  1234. var nodeForJoint = this.joints[jointName];
  1235. var joint = this.resources.getEntry(nodeForJoint).object;
  1236. if (joint) {
  1237. joint.skin = threeMesh;
  1238. joints.push(joint);
  1239. bones.push(joint);
  1240. var m = skin.inverseBindMatrices;
  1241. var mat = new THREE.Matrix4().set(
  1242. m[i * 16 + 0], m[i * 16 + 4], m[i * 16 + 8], m[i * 16 + 12],
  1243. m[i * 16 + 1], m[i * 16 + 5], m[i * 16 + 9], m[i * 16 + 13],
  1244. m[i * 16 + 2], m[i * 16 + 6], m[i * 16 + 10], m[i * 16 + 14],
  1245. m[i * 16 + 3], m[i * 16 + 7], m[i * 16 + 11], m[i * 16 + 15]
  1246. );
  1247. boneInverses.push(mat);
  1248. } else {
  1249. console.log("WARNING: jointName:"+jointName+" cannot be found in skeleton:"+skeleton);
  1250. }
  1251. }
  1252. threeMesh.bind( new THREE.Skeleton( bones,
  1253. boneInverses, false ), skin.bindShapeMatrix );
  1254. //threeMesh.bindMode = "detached";
  1255. //threeMesh.normalizeSkinWeights();
  1256. //threeMesh.pose();
  1257. }
  1258. if (threeMesh) {
  1259. threeMesh.castShadow = true;
  1260. node.add(threeMesh);
  1261. if (material instanceof THREE.ShaderMaterial) {
  1262. materialParams.joints = joints;
  1263. var glTFShader = new THREE.glTFShader(material, materialParams, threeMesh, theLoader.rootObj);
  1264. THREE.glTFShaders.add(glTFShader);
  1265. }
  1266. }
  1267. }, this);
  1268. }
  1269. }
  1270. }, this);
  1271. }
  1272. }
  1273. },
  1274. buildSkins: {
  1275. value: function(node) {
  1276. if (node.glTF && node.glTF.instanceSkin)
  1277. this.buildSkin(node);
  1278. var children = node.children;
  1279. if (children) {
  1280. children.forEach( function(child) {
  1281. this.buildSkins(child);
  1282. }, this);
  1283. }
  1284. }
  1285. },
  1286. createMeshAnimations : {
  1287. value : function(root) {
  1288. this.buildSkins(root);
  1289. }
  1290. },
  1291. handleScene: {
  1292. value: function(entryID, description, userInfo) {
  1293. if (!description.nodes) {
  1294. console.log("ERROR: invalid file required nodes property is missing from scene");
  1295. return false;
  1296. }
  1297. description.nodes.forEach( function(nodeUID) {
  1298. this.buildNodeHirerachy(nodeUID, userInfo.rootObj);
  1299. }, this);
  1300. if (this.delegate) {
  1301. this.delegate.loadCompleted(userInfo.callback, userInfo.rootObj);
  1302. }
  1303. theLoader.loadAllAssets();
  1304. return true;
  1305. }
  1306. },
  1307. handleImage: {
  1308. value: function(entryID, description, userInfo) {
  1309. this.resources.setEntry(entryID, null, description);
  1310. return true;
  1311. }
  1312. },
  1313. addNodeAnimationChannel : {
  1314. value : function(name, channel, interp) {
  1315. if (!this.nodeAnimationChannels)
  1316. this.nodeAnimationChannels = {};
  1317. if (!this.nodeAnimationChannels[name]) {
  1318. this.nodeAnimationChannels[name] = [];
  1319. }
  1320. this.nodeAnimationChannels[name].push(interp);
  1321. },
  1322. },
  1323. createAnimations : {
  1324. value : function() {
  1325. for (var name in this.nodeAnimationChannels) {
  1326. var nodeAnimationChannels = this.nodeAnimationChannels[name];
  1327. var i, len = nodeAnimationChannels.length;
  1328. //console.log(" animation channels for node " + name);
  1329. //for (i = 0; i < len; i++) {
  1330. // console.log(nodeAnimationChannels[i]);
  1331. //}
  1332. var anim = new THREE.glTFAnimation(nodeAnimationChannels);
  1333. anim.name = "animation_" + name;
  1334. this.animations.push(anim);
  1335. }
  1336. }
  1337. },
  1338. buildAnimation: {
  1339. value : function(animation) {
  1340. var interps = [];
  1341. var i, len = animation.channels.length;
  1342. for (i = 0; i < len; i++) {
  1343. var channel = animation.channels[i];
  1344. var sampler = animation.samplers[channel.sampler];
  1345. if (sampler) {
  1346. var input = animation.parameters[sampler.input];
  1347. if (input && input.data) {
  1348. var output = animation.parameters[sampler.output];
  1349. if (output && output.data) {
  1350. var target = channel.target;
  1351. var node = this.resources.getEntry(target.id);
  1352. if (node) {
  1353. var path = target.path;
  1354. var interp = {
  1355. keys : input.data,
  1356. values : output.data,
  1357. count : input.count,
  1358. target : node.object,
  1359. path : path,
  1360. type : sampler.interpolation
  1361. };
  1362. this.addNodeAnimationChannel(target.id, channel, interp);
  1363. interps.push(interp);
  1364. }
  1365. }
  1366. }
  1367. }
  1368. }
  1369. }
  1370. },
  1371. handleAnimation: {
  1372. value: function(entryID, description, userInfo) {
  1373. var self = this;
  1374. theLoader.animationsRequested++;
  1375. var animation = new Animation();
  1376. animation.name = entryID;
  1377. animation.onload = function() {
  1378. // self.buildAnimation(animation);
  1379. theLoader.animationsLoaded++;
  1380. theLoader.animations.push(animation);
  1381. theLoader.checkComplete();
  1382. };
  1383. animation.channels = description.channels;
  1384. animation.samplers = description.samplers;
  1385. this.resources.setEntry(entryID, animation, description);
  1386. var parameters = description.parameters;
  1387. if (!parameters) {
  1388. //FIXME: not implemented in delegate
  1389. console.log("MISSING_PARAMETERS for animation:"+ entryID);
  1390. return false;
  1391. }
  1392. // Load parameter buffers
  1393. var params = Object.keys(parameters);
  1394. params.forEach( function(param) {
  1395. // async help
  1396. animation.totalParameters++;
  1397. }, this);
  1398. var params = Object.keys(parameters);
  1399. params.forEach( function(param) {
  1400. var parameter = parameters[param];
  1401. var accessor = this.resources.getEntry(parameter);
  1402. if (!accessor)
  1403. debugger;
  1404. accessor = accessor.object;
  1405. var bufferView = this.resources.getEntry(accessor.bufferView);
  1406. var paramObject = {
  1407. bufferView : bufferView,
  1408. byteOffset : accessor.byteOffset,
  1409. count : accessor.count,
  1410. componentType : accessor.componentType,
  1411. type : accessor.type,
  1412. id : accessor.bufferView,
  1413. name : param
  1414. };
  1415. var paramContext = new AnimationParameterContext(paramObject, animation);
  1416. var loaddata = {
  1417. paramObject : paramObject,
  1418. animationParameterDelegate : animationParameterDelegate,
  1419. paramContext : paramContext
  1420. };
  1421. theLoader.scheduleLoad(function(data) {
  1422. var alreadyProcessedAttribute =
  1423. THREE.GLTFLoaderUtils.getBuffer(data.paramObject,
  1424. data.animationParameterDelegate, data.paramContext);
  1425. if (alreadyProcessedAttribute) {
  1426. data.animationParameterDelegate.resourceAvailable(
  1427. alreadyProcessedAttribute, data.paramContext);
  1428. }
  1429. }, loaddata);
  1430. }, this);
  1431. return true;
  1432. }
  1433. },
  1434. handleAccessor: {
  1435. value: function(entryID, description, userInfo) {
  1436. // Save attribute entry
  1437. this.resources.setEntry(entryID, description, description);
  1438. return true;
  1439. }
  1440. },
  1441. handleSkin: {
  1442. value: function(entryID, description, userInfo) {
  1443. // Save skin entry
  1444. var skin = {
  1445. };
  1446. var m = description.bindShapeMatrix;
  1447. skin.bindShapeMatrix = new THREE.Matrix4().set(
  1448. m[0], m[4], m[8], m[12],
  1449. m[1], m[5], m[9], m[13],
  1450. m[2], m[6], m[10], m[14],
  1451. m[3], m[7], m[11], m[15]
  1452. );
  1453. skin.jointNames = description.jointNames;
  1454. var inverseBindMatricesDescription = this.resources.getEntry(description.inverseBindMatrices);
  1455. inverseBindMatricesDescription = inverseBindMatricesDescription.description;
  1456. skin.inverseBindMatricesDescription = inverseBindMatricesDescription;
  1457. skin.inverseBindMatricesDescription.id = description.inverseBindMatrices;
  1458. var bufferEntry = this.resources.getEntry(inverseBindMatricesDescription.bufferView);
  1459. var paramObject = {
  1460. bufferView : bufferEntry,
  1461. byteOffset : inverseBindMatricesDescription.byteOffset,
  1462. count : inverseBindMatricesDescription.count,
  1463. componentType : inverseBindMatricesDescription.componentType,
  1464. type : inverseBindMatricesDescription.type,
  1465. id : inverseBindMatricesDescription.bufferView,
  1466. name : skin.inverseBindMatricesDescription.id
  1467. };
  1468. var context = new InverseBindMatricesContext(paramObject, skin);
  1469. var loaddata = {
  1470. paramObject : paramObject,
  1471. inverseBindMatricesDelegate : inverseBindMatricesDelegate,
  1472. context : context
  1473. };
  1474. theLoader.scheduleLoad(function(data) {
  1475. var alreadyProcessedAttribute =
  1476. THREE.GLTFLoaderUtils.getBuffer(data.paramObject,
  1477. data.inverseBindMatricesDelegate, data.context);
  1478. if (alreadyProcessedAttribute) {
  1479. data.inverseBindMatricesDelegate.resourceAvailable(
  1480. alreadyProcessedAttribute, data.context);
  1481. }
  1482. }, loaddata);
  1483. var bufferView = this.resources.getEntry(skin.inverseBindMatricesDescription.bufferView);
  1484. skin.inverseBindMatricesDescription.bufferView =
  1485. bufferView.object;
  1486. this.resources.setEntry(entryID, skin, description);
  1487. return true;
  1488. }
  1489. },
  1490. handleSampler: {
  1491. value: function(entryID, description, userInfo) {
  1492. // Save attribute entry
  1493. this.resources.setEntry(entryID, description, description);
  1494. return true;
  1495. }
  1496. },
  1497. handleTexture: {
  1498. value: function(entryID, description, userInfo) {
  1499. // Save attribute entry
  1500. this.resources.setEntry(entryID, null, description);
  1501. return true;
  1502. }
  1503. },
  1504. handleError: {
  1505. value: function(msg) {
  1506. throw new Error(msg);
  1507. return true;
  1508. }
  1509. },
  1510. _delegate: {
  1511. value: new LoadDelegate,
  1512. writable: true
  1513. },
  1514. delegate: {
  1515. enumerable: true,
  1516. get: function() {
  1517. return this._delegate;
  1518. },
  1519. set: function(value) {
  1520. this._delegate = value;
  1521. }
  1522. }
  1523. });
  1524. // Loader
  1525. var Context = function(rootObj, callback) {
  1526. this.rootObj = rootObj;
  1527. this.callback = callback;
  1528. };
  1529. var rootObj = new THREE.Object3D();
  1530. var self = this;
  1531. this.callback = callback;
  1532. this.rootObj = rootObj;
  1533. this.loader = Object.create(ThreeGLTFLoader);
  1534. this.loader.initWithPath(url);
  1535. this.loader.load(new Context(rootObj,
  1536. function(obj) {
  1537. }),
  1538. null);
  1539. return rootObj;
  1540. }
  1541. THREE.glTFLoader.prototype.scheduleLoad = function(loadFn, data) {
  1542. this.loadRequests.push({fn: loadFn, data:data});
  1543. }
  1544. THREE.glTFLoader.prototype.loadAllAssets = function() {
  1545. for (var i = 0, len = this.loadRequests.length; i < len; i++) {
  1546. var request = this.loadRequests[i];
  1547. request.fn(request.data);
  1548. }
  1549. }
  1550. THREE.glTFLoader.prototype.callLoadedCallback = function() {
  1551. var result = {
  1552. scene : this.rootObj,
  1553. cameras : this.loader.cameras,
  1554. animations : this.loader.animations,
  1555. shaders : this.loader.shaders,
  1556. };
  1557. this.callback(result);
  1558. }
  1559. THREE.glTFLoader.prototype.checkComplete = function() {
  1560. if (this.meshesLoaded == this.meshesRequested
  1561. && this.shadersLoaded == this.shadersRequested
  1562. && this.animationsLoaded == this.animationsRequested)
  1563. {
  1564. for (var i = 0; i < this.pendingMeshes.length; i++) {
  1565. var pending = this.pendingMeshes[i];
  1566. pending.mesh.attachToNode(pending.node);
  1567. }
  1568. for (var i = 0; i < this.animationsLoaded; i++) {
  1569. var animation = this.animations[i];
  1570. this.loader.buildAnimation(animation);
  1571. }
  1572. this.loader.createAnimations();
  1573. this.loader.createMeshAnimations(this.rootObj);
  1574. THREE.glTFShaders.bindShaderParameters(this.rootObj);
  1575. this.callLoadedCallback();
  1576. }
  1577. }