BinaryLoader.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. /**
  2. * @author alteredq / http://alteredqualia.com/
  3. */
  4. THREE.BinaryLoader = function ( showStatus ) {
  5. THREE.Loader.call( this, showStatus );
  6. };
  7. THREE.BinaryLoader.prototype = Object.create( THREE.Loader.prototype );
  8. THREE.BinaryLoader.prototype.constructor = THREE.BinaryLoader;
  9. // Load models generated by slim OBJ converter with BINARY option (converter_obj_three_slim.py -t binary)
  10. // - binary models consist of two files: JS and BIN
  11. // - parameters
  12. // - url (required)
  13. // - callback (required)
  14. // - texturePath (optional: if not specified, textures will be assumed to be in the same folder as JS model file)
  15. // - binaryPath (optional: if not specified, binary file will be assumed to be in the same folder as JS model file)
  16. THREE.BinaryLoader.prototype.load = function ( url, callback, texturePath, binaryPath ) {
  17. // todo: unify load API to for easier SceneLoader use
  18. texturePath = texturePath || this.extractUrlBase( url );
  19. binaryPath = binaryPath || this.extractUrlBase( url );
  20. var callbackProgress = this.showProgress ? THREE.Loader.prototype.updateProgress : undefined;
  21. this.onLoadStart();
  22. // #1 load JS part via web worker
  23. this.loadAjaxJSON( this, url, callback, texturePath, binaryPath, callbackProgress );
  24. };
  25. THREE.BinaryLoader.prototype.loadAjaxJSON = function ( context, url, callback, texturePath, binaryPath, callbackProgress ) {
  26. var xhr = new XMLHttpRequest();
  27. texturePath = texturePath && ( typeof texturePath === "string" ) ? texturePath : this.extractUrlBase( url );
  28. binaryPath = binaryPath && ( typeof binaryPath === "string" ) ? binaryPath : this.extractUrlBase( url );
  29. xhr.onreadystatechange = function () {
  30. if ( xhr.readyState == 4 ) {
  31. if ( xhr.status == 200 || xhr.status == 0 ) {
  32. var json = JSON.parse( xhr.responseText );
  33. context.loadAjaxBuffers( json, callback, binaryPath, texturePath, callbackProgress );
  34. } else {
  35. THREE.error( "THREE.BinaryLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
  36. }
  37. }
  38. };
  39. xhr.open( "GET", url, true );
  40. xhr.send( null );
  41. };
  42. THREE.BinaryLoader.prototype.loadAjaxBuffers = function ( json, callback, binaryPath, texturePath, callbackProgress ) {
  43. var scope = this;
  44. var xhr = new XMLHttpRequest(),
  45. url = binaryPath + json.buffers;
  46. xhr.addEventListener( 'load', function ( event ) {
  47. var buffer = xhr.response;
  48. if ( buffer === undefined ) {
  49. // IEWEBGL needs this
  50. buffer = ( new Uint8Array( xhr.responseBody ) ).buffer;
  51. }
  52. if ( buffer.byteLength == 0 ) { // iOS and other XMLHttpRequest level 1
  53. var buffer = new ArrayBuffer( xhr.responseText.length );
  54. var bufView = new Uint8Array( buffer );
  55. for ( var i = 0, l = xhr.responseText.length; i < l; i ++ ) {
  56. bufView[ i ] = xhr.responseText.charCodeAt( i ) & 0xff;
  57. }
  58. }
  59. scope.createBinModel( buffer, callback, texturePath, json.materials );
  60. }, false );
  61. if ( callbackProgress !== undefined ) {
  62. xhr.addEventListener( 'progress', function ( event ) {
  63. if ( event.lengthComputable ) {
  64. callbackProgress( event );
  65. }
  66. }, false );
  67. }
  68. xhr.addEventListener( 'error', function ( event ) {
  69. THREE.error( "THREE.BinaryLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
  70. }, false );
  71. xhr.open( "GET", url, true );
  72. xhr.responseType = "arraybuffer";
  73. if ( xhr.overrideMimeType ) xhr.overrideMimeType( "text/plain; charset=x-user-defined" );
  74. xhr.send( null );
  75. };
  76. // Binary AJAX parser
  77. THREE.BinaryLoader.prototype.createBinModel = function ( data, callback, texturePath, jsonMaterials ) {
  78. var Model = function ( texturePath ) {
  79. var scope = this,
  80. currentOffset = 0,
  81. md,
  82. normals = [],
  83. uvs = [],
  84. start_tri_flat, start_tri_smooth, start_tri_flat_uv, start_tri_smooth_uv,
  85. start_quad_flat, start_quad_smooth, start_quad_flat_uv, start_quad_smooth_uv,
  86. tri_size, quad_size,
  87. len_tri_flat, len_tri_smooth, len_tri_flat_uv, len_tri_smooth_uv,
  88. len_quad_flat, len_quad_smooth, len_quad_flat_uv, len_quad_smooth_uv;
  89. THREE.Geometry.call( this );
  90. md = parseMetaData( data, currentOffset );
  91. currentOffset += md.header_bytes;
  92. /*
  93. md.vertex_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
  94. md.material_index_bytes = Uint16Array.BYTES_PER_ELEMENT;
  95. md.normal_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
  96. md.uv_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
  97. */
  98. // buffers sizes
  99. tri_size = md.vertex_index_bytes * 3 + md.material_index_bytes;
  100. quad_size = md.vertex_index_bytes * 4 + md.material_index_bytes;
  101. len_tri_flat = md.ntri_flat * ( tri_size );
  102. len_tri_smooth = md.ntri_smooth * ( tri_size + md.normal_index_bytes * 3 );
  103. len_tri_flat_uv = md.ntri_flat_uv * ( tri_size + md.uv_index_bytes * 3 );
  104. len_tri_smooth_uv = md.ntri_smooth_uv * ( tri_size + md.normal_index_bytes * 3 + md.uv_index_bytes * 3 );
  105. len_quad_flat = md.nquad_flat * ( quad_size );
  106. len_quad_smooth = md.nquad_smooth * ( quad_size + md.normal_index_bytes * 4 );
  107. len_quad_flat_uv = md.nquad_flat_uv * ( quad_size + md.uv_index_bytes * 4 );
  108. len_quad_smooth_uv = md.nquad_smooth_uv * ( quad_size + md.normal_index_bytes * 4 + md.uv_index_bytes * 4 );
  109. // read buffers
  110. currentOffset += init_vertices( currentOffset );
  111. currentOffset += init_normals( currentOffset );
  112. currentOffset += handlePadding( md.nnormals * 3 );
  113. currentOffset += init_uvs( currentOffset );
  114. start_tri_flat = currentOffset;
  115. start_tri_smooth = start_tri_flat + len_tri_flat + handlePadding( md.ntri_flat * 2 );
  116. start_tri_flat_uv = start_tri_smooth + len_tri_smooth + handlePadding( md.ntri_smooth * 2 );
  117. start_tri_smooth_uv = start_tri_flat_uv + len_tri_flat_uv + handlePadding( md.ntri_flat_uv * 2 );
  118. start_quad_flat = start_tri_smooth_uv + len_tri_smooth_uv + handlePadding( md.ntri_smooth_uv * 2 );
  119. start_quad_smooth = start_quad_flat + len_quad_flat + handlePadding( md.nquad_flat * 2 );
  120. start_quad_flat_uv = start_quad_smooth + len_quad_smooth + handlePadding( md.nquad_smooth * 2 );
  121. start_quad_smooth_uv = start_quad_flat_uv + len_quad_flat_uv + handlePadding( md.nquad_flat_uv * 2 );
  122. // have to first process faces with uvs
  123. // so that face and uv indices match
  124. init_triangles_flat_uv( start_tri_flat_uv );
  125. init_triangles_smooth_uv( start_tri_smooth_uv );
  126. init_quads_flat_uv( start_quad_flat_uv );
  127. init_quads_smooth_uv( start_quad_smooth_uv );
  128. // now we can process untextured faces
  129. init_triangles_flat( start_tri_flat );
  130. init_triangles_smooth( start_tri_smooth );
  131. init_quads_flat( start_quad_flat );
  132. init_quads_smooth( start_quad_smooth );
  133. this.computeFaceNormals();
  134. function handlePadding( n ) {
  135. return ( n % 4 ) ? ( 4 - n % 4 ) : 0;
  136. };
  137. function parseMetaData( data, offset ) {
  138. var metaData = {
  139. 'signature' :parseString( data, offset, 12 ),
  140. 'header_bytes' :parseUChar8( data, offset + 12 ),
  141. 'vertex_coordinate_bytes' :parseUChar8( data, offset + 13 ),
  142. 'normal_coordinate_bytes' :parseUChar8( data, offset + 14 ),
  143. 'uv_coordinate_bytes' :parseUChar8( data, offset + 15 ),
  144. 'vertex_index_bytes' :parseUChar8( data, offset + 16 ),
  145. 'normal_index_bytes' :parseUChar8( data, offset + 17 ),
  146. 'uv_index_bytes' :parseUChar8( data, offset + 18 ),
  147. 'material_index_bytes' :parseUChar8( data, offset + 19 ),
  148. 'nvertices' :parseUInt32( data, offset + 20 ),
  149. 'nnormals' :parseUInt32( data, offset + 20 + 4 * 1 ),
  150. 'nuvs' :parseUInt32( data, offset + 20 + 4 * 2 ),
  151. 'ntri_flat' :parseUInt32( data, offset + 20 + 4 * 3 ),
  152. 'ntri_smooth' :parseUInt32( data, offset + 20 + 4 * 4 ),
  153. 'ntri_flat_uv' :parseUInt32( data, offset + 20 + 4 * 5 ),
  154. 'ntri_smooth_uv' :parseUInt32( data, offset + 20 + 4 * 6 ),
  155. 'nquad_flat' :parseUInt32( data, offset + 20 + 4 * 7 ),
  156. 'nquad_smooth' :parseUInt32( data, offset + 20 + 4 * 8 ),
  157. 'nquad_flat_uv' :parseUInt32( data, offset + 20 + 4 * 9 ),
  158. 'nquad_smooth_uv' :parseUInt32( data, offset + 20 + 4 * 10 )
  159. };
  160. /*
  161. THREE.log( "signature: " + metaData.signature );
  162. THREE.log( "header_bytes: " + metaData.header_bytes );
  163. THREE.log( "vertex_coordinate_bytes: " + metaData.vertex_coordinate_bytes );
  164. THREE.log( "normal_coordinate_bytes: " + metaData.normal_coordinate_bytes );
  165. THREE.log( "uv_coordinate_bytes: " + metaData.uv_coordinate_bytes );
  166. THREE.log( "vertex_index_bytes: " + metaData.vertex_index_bytes );
  167. THREE.log( "normal_index_bytes: " + metaData.normal_index_bytes );
  168. THREE.log( "uv_index_bytes: " + metaData.uv_index_bytes );
  169. THREE.log( "material_index_bytes: " + metaData.material_index_bytes );
  170. THREE.log( "nvertices: " + metaData.nvertices );
  171. THREE.log( "nnormals: " + metaData.nnormals );
  172. THREE.log( "nuvs: " + metaData.nuvs );
  173. THREE.log( "ntri_flat: " + metaData.ntri_flat );
  174. THREE.log( "ntri_smooth: " + metaData.ntri_smooth );
  175. THREE.log( "ntri_flat_uv: " + metaData.ntri_flat_uv );
  176. THREE.log( "ntri_smooth_uv: " + metaData.ntri_smooth_uv );
  177. THREE.log( "nquad_flat: " + metaData.nquad_flat );
  178. THREE.log( "nquad_smooth: " + metaData.nquad_smooth );
  179. THREE.log( "nquad_flat_uv: " + metaData.nquad_flat_uv );
  180. THREE.log( "nquad_smooth_uv: " + metaData.nquad_smooth_uv );
  181. var total = metaData.header_bytes
  182. + metaData.nvertices * metaData.vertex_coordinate_bytes * 3
  183. + metaData.nnormals * metaData.normal_coordinate_bytes * 3
  184. + metaData.nuvs * metaData.uv_coordinate_bytes * 2
  185. + metaData.ntri_flat * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes )
  186. + metaData.ntri_smooth * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 )
  187. + metaData.ntri_flat_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.uv_index_bytes*3 )
  188. + metaData.ntri_smooth_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 + metaData.uv_index_bytes*3 )
  189. + metaData.nquad_flat * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes )
  190. + metaData.nquad_smooth * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 )
  191. + metaData.nquad_flat_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.uv_index_bytes*4 )
  192. + metaData.nquad_smooth_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 + metaData.uv_index_bytes*4 );
  193. THREE.log( "total bytes: " + total );
  194. */
  195. return metaData;
  196. };
  197. function parseString( data, offset, length ) {
  198. var charArray = new Uint8Array( data, offset, length );
  199. var text = "";
  200. for ( var i = 0; i < length; i ++ ) {
  201. text += String.fromCharCode( charArray[ offset + i ] );
  202. }
  203. return text;
  204. };
  205. function parseUChar8( data, offset ) {
  206. var charArray = new Uint8Array( data, offset, 1 );
  207. return charArray[ 0 ];
  208. };
  209. function parseUInt32( data, offset ) {
  210. var intArray = new Uint32Array( data, offset, 1 );
  211. return intArray[ 0 ];
  212. };
  213. function init_vertices( start ) {
  214. var nElements = md.nvertices;
  215. var coordArray = new Float32Array( data, start, nElements * 3 );
  216. var i, x, y, z;
  217. for ( i = 0; i < nElements; i ++ ) {
  218. x = coordArray[ i * 3 ];
  219. y = coordArray[ i * 3 + 1 ];
  220. z = coordArray[ i * 3 + 2 ];
  221. scope.vertices.push( new THREE.Vector3( x, y, z ) );
  222. }
  223. return nElements * 3 * Float32Array.BYTES_PER_ELEMENT;
  224. };
  225. function init_normals( start ) {
  226. var nElements = md.nnormals;
  227. if ( nElements ) {
  228. var normalArray = new Int8Array( data, start, nElements * 3 );
  229. var i, x, y, z;
  230. for ( i = 0; i < nElements; i ++ ) {
  231. x = normalArray[ i * 3 ];
  232. y = normalArray[ i * 3 + 1 ];
  233. z = normalArray[ i * 3 + 2 ];
  234. normals.push( x / 127, y / 127, z / 127 );
  235. }
  236. }
  237. return nElements * 3 * Int8Array.BYTES_PER_ELEMENT;
  238. };
  239. function init_uvs( start ) {
  240. var nElements = md.nuvs;
  241. if ( nElements ) {
  242. var uvArray = new Float32Array( data, start, nElements * 2 );
  243. var i, u, v;
  244. for ( i = 0; i < nElements; i ++ ) {
  245. u = uvArray[ i * 2 ];
  246. v = uvArray[ i * 2 + 1 ];
  247. uvs.push( u, v );
  248. }
  249. }
  250. return nElements * 2 * Float32Array.BYTES_PER_ELEMENT;
  251. };
  252. function init_uvs3( nElements, offset ) {
  253. var i, uva, uvb, uvc, u1, u2, u3, v1, v2, v3;
  254. var uvIndexBuffer = new Uint32Array( data, offset, 3 * nElements );
  255. for ( i = 0; i < nElements; i ++ ) {
  256. uva = uvIndexBuffer[ i * 3 ];
  257. uvb = uvIndexBuffer[ i * 3 + 1 ];
  258. uvc = uvIndexBuffer[ i * 3 + 2 ];
  259. u1 = uvs[ uva * 2 ];
  260. v1 = uvs[ uva * 2 + 1 ];
  261. u2 = uvs[ uvb * 2 ];
  262. v2 = uvs[ uvb * 2 + 1 ];
  263. u3 = uvs[ uvc * 2 ];
  264. v3 = uvs[ uvc * 2 + 1 ];
  265. scope.faceVertexUvs[ 0 ].push( [
  266. new THREE.Vector2( u1, v1 ),
  267. new THREE.Vector2( u2, v2 ),
  268. new THREE.Vector2( u3, v3 )
  269. ] );
  270. }
  271. };
  272. function init_uvs4( nElements, offset ) {
  273. var i, uva, uvb, uvc, uvd, u1, u2, u3, u4, v1, v2, v3, v4;
  274. var uvIndexBuffer = new Uint32Array( data, offset, 4 * nElements );
  275. for ( i = 0; i < nElements; i ++ ) {
  276. uva = uvIndexBuffer[ i * 4 ];
  277. uvb = uvIndexBuffer[ i * 4 + 1 ];
  278. uvc = uvIndexBuffer[ i * 4 + 2 ];
  279. uvd = uvIndexBuffer[ i * 4 + 3 ];
  280. u1 = uvs[ uva * 2 ];
  281. v1 = uvs[ uva * 2 + 1 ];
  282. u2 = uvs[ uvb * 2 ];
  283. v2 = uvs[ uvb * 2 + 1 ];
  284. u3 = uvs[ uvc * 2 ];
  285. v3 = uvs[ uvc * 2 + 1 ];
  286. u4 = uvs[ uvd * 2 ];
  287. v4 = uvs[ uvd * 2 + 1 ];
  288. scope.faceVertexUvs[ 0 ].push( [
  289. new THREE.Vector2( u1, v1 ),
  290. new THREE.Vector2( u2, v2 ),
  291. new THREE.Vector2( u4, v4 )
  292. ] );
  293. scope.faceVertexUvs[ 0 ].push( [
  294. new THREE.Vector2( u2, v2 ),
  295. new THREE.Vector2( u3, v3 ),
  296. new THREE.Vector2( u4, v4 )
  297. ] );
  298. }
  299. };
  300. function init_faces3_flat( nElements, offsetVertices, offsetMaterials ) {
  301. var i, a, b, c, m;
  302. var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 3 * nElements );
  303. var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
  304. for ( i = 0; i < nElements; i ++ ) {
  305. a = vertexIndexBuffer[ i * 3 ];
  306. b = vertexIndexBuffer[ i * 3 + 1 ];
  307. c = vertexIndexBuffer[ i * 3 + 2 ];
  308. m = materialIndexBuffer[ i ];
  309. scope.faces.push( new THREE.Face3( a, b, c ) );
  310. }
  311. };
  312. function init_faces4_flat( nElements, offsetVertices, offsetMaterials ) {
  313. var i, a, b, c, d, m;
  314. var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 4 * nElements );
  315. var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
  316. for ( i = 0; i < nElements; i ++ ) {
  317. a = vertexIndexBuffer[ i * 4 ];
  318. b = vertexIndexBuffer[ i * 4 + 1 ];
  319. c = vertexIndexBuffer[ i * 4 + 2 ];
  320. d = vertexIndexBuffer[ i * 4 + 3 ];
  321. m = materialIndexBuffer[ i ];
  322. scope.faces.push( new THREE.Face3( a, b, d ) );
  323. scope.faces.push( new THREE.Face3( b, c, d ) );
  324. }
  325. };
  326. function init_faces3_smooth( nElements, offsetVertices, offsetNormals, offsetMaterials ) {
  327. var i, a, b, c, m;
  328. var na, nb, nc;
  329. var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 3 * nElements );
  330. var normalIndexBuffer = new Uint32Array( data, offsetNormals, 3 * nElements );
  331. var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
  332. for ( i = 0; i < nElements; i ++ ) {
  333. a = vertexIndexBuffer[ i * 3 ];
  334. b = vertexIndexBuffer[ i * 3 + 1 ];
  335. c = vertexIndexBuffer[ i * 3 + 2 ];
  336. na = normalIndexBuffer[ i * 3 ];
  337. nb = normalIndexBuffer[ i * 3 + 1 ];
  338. nc = normalIndexBuffer[ i * 3 + 2 ];
  339. m = materialIndexBuffer[ i ];
  340. var nax = normals[ na * 3 ],
  341. nay = normals[ na * 3 + 1 ],
  342. naz = normals[ na * 3 + 2 ],
  343. nbx = normals[ nb * 3 ],
  344. nby = normals[ nb * 3 + 1 ],
  345. nbz = normals[ nb * 3 + 2 ],
  346. ncx = normals[ nc * 3 ],
  347. ncy = normals[ nc * 3 + 1 ],
  348. ncz = normals[ nc * 3 + 2 ];
  349. scope.faces.push( new THREE.Face3( a, b, c, [
  350. new THREE.Vector3( nax, nay, naz ),
  351. new THREE.Vector3( nbx, nby, nbz ),
  352. new THREE.Vector3( ncx, ncy, ncz )
  353. ] ) );
  354. }
  355. };
  356. function init_faces4_smooth( nElements, offsetVertices, offsetNormals, offsetMaterials ) {
  357. var i, a, b, c, d, m;
  358. var na, nb, nc, nd;
  359. var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 4 * nElements );
  360. var normalIndexBuffer = new Uint32Array( data, offsetNormals, 4 * nElements );
  361. var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
  362. for ( i = 0; i < nElements; i ++ ) {
  363. a = vertexIndexBuffer[ i * 4 ];
  364. b = vertexIndexBuffer[ i * 4 + 1 ];
  365. c = vertexIndexBuffer[ i * 4 + 2 ];
  366. d = vertexIndexBuffer[ i * 4 + 3 ];
  367. na = normalIndexBuffer[ i * 4 ];
  368. nb = normalIndexBuffer[ i * 4 + 1 ];
  369. nc = normalIndexBuffer[ i * 4 + 2 ];
  370. nd = normalIndexBuffer[ i * 4 + 3 ];
  371. m = materialIndexBuffer[ i ];
  372. var nax = normals[ na * 3 ],
  373. nay = normals[ na * 3 + 1 ],
  374. naz = normals[ na * 3 + 2 ],
  375. nbx = normals[ nb * 3 ],
  376. nby = normals[ nb * 3 + 1 ],
  377. nbz = normals[ nb * 3 + 2 ],
  378. ncx = normals[ nc * 3 ],
  379. ncy = normals[ nc * 3 + 1 ],
  380. ncz = normals[ nc * 3 + 2 ],
  381. ndx = normals[ nd * 3 ],
  382. ndy = normals[ nd * 3 + 1 ],
  383. ndz = normals[ nd * 3 + 2 ];
  384. scope.faces.push( new THREE.Face3( a, b, d, [
  385. new THREE.Vector3( nax, nay, naz ),
  386. new THREE.Vector3( nbx, nby, nbz ),
  387. new THREE.Vector3( ndx, ndy, ndz )
  388. ] ) );
  389. scope.faces.push( new THREE.Face3( b, c, d, [
  390. new THREE.Vector3( nbx, nby, nbz ),
  391. new THREE.Vector3( ncx, ncy, ncz ),
  392. new THREE.Vector3( ndx, ndy, ndz )
  393. ] ) );
  394. }
  395. };
  396. function init_triangles_flat( start ) {
  397. var nElements = md.ntri_flat;
  398. if ( nElements ) {
  399. var offsetMaterials = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  400. init_faces3_flat( nElements, start, offsetMaterials );
  401. }
  402. };
  403. function init_triangles_flat_uv( start ) {
  404. var nElements = md.ntri_flat_uv;
  405. if ( nElements ) {
  406. var offsetUvs = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  407. var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  408. init_faces3_flat( nElements, start, offsetMaterials );
  409. init_uvs3( nElements, offsetUvs );
  410. }
  411. };
  412. function init_triangles_smooth( start ) {
  413. var nElements = md.ntri_smooth;
  414. if ( nElements ) {
  415. var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  416. var offsetMaterials = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  417. init_faces3_smooth( nElements, start, offsetNormals, offsetMaterials );
  418. }
  419. };
  420. function init_triangles_smooth_uv( start ) {
  421. var nElements = md.ntri_smooth_uv;
  422. if ( nElements ) {
  423. var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  424. var offsetUvs = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  425. var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
  426. init_faces3_smooth( nElements, start, offsetNormals, offsetMaterials );
  427. init_uvs3( nElements, offsetUvs );
  428. }
  429. };
  430. function init_quads_flat( start ) {
  431. var nElements = md.nquad_flat;
  432. if ( nElements ) {
  433. var offsetMaterials = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  434. init_faces4_flat( nElements, start, offsetMaterials );
  435. }
  436. };
  437. function init_quads_flat_uv( start ) {
  438. var nElements = md.nquad_flat_uv;
  439. if ( nElements ) {
  440. var offsetUvs = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  441. var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  442. init_faces4_flat( nElements, start, offsetMaterials );
  443. init_uvs4( nElements, offsetUvs );
  444. }
  445. };
  446. function init_quads_smooth( start ) {
  447. var nElements = md.nquad_smooth;
  448. if ( nElements ) {
  449. var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  450. var offsetMaterials = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  451. init_faces4_smooth( nElements, start, offsetNormals, offsetMaterials );
  452. }
  453. };
  454. function init_quads_smooth_uv( start ) {
  455. var nElements = md.nquad_smooth_uv;
  456. if ( nElements ) {
  457. var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  458. var offsetUvs = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  459. var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
  460. init_faces4_smooth( nElements, start, offsetNormals, offsetMaterials );
  461. init_uvs4( nElements, offsetUvs );
  462. }
  463. };
  464. };
  465. Model.prototype = Object.create( THREE.Geometry.prototype );
  466. Model.prototype.constructor = Model;
  467. var geometry = new Model( texturePath );
  468. var materials = this.initMaterials( jsonMaterials, texturePath );
  469. if ( this.needsTangents( materials ) ) geometry.computeTangents();
  470. callback( geometry, materials );
  471. };