Loader.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. /**
  2. * @author alteredq / http://alteredqualia.com/
  3. */
  4. THREE.Loader = function() {
  5. };
  6. THREE.Loader.prototype = {
  7. // Load models generated by Blender exporter and original OBJ converter (converter_obj_three.py)
  8. loadAsciiOld: function( url, callback ) {
  9. var element = document.createElement( 'script' );
  10. element.type = 'text/javascript';
  11. element.onload = callback;
  12. element.src = url;
  13. document.getElementsByTagName( "head" )[ 0 ].appendChild( element );
  14. },
  15. // Load models generated by slim OBJ converter with ASCII option (converter_obj_three_slim.py -t ascii)
  16. // - urlbase parameter is optional (it only applies to models with textures)
  17. loadAscii: function ( url, callback, urlbase ) {
  18. var s = (new Date).getTime(),
  19. worker = new Worker( url );
  20. worker.onmessage = function( event ) {
  21. THREE.Loader.prototype.createModel( event.data, callback, urlbase );
  22. };
  23. worker.postMessage( s );
  24. },
  25. // Load models generated by slim OBJ converter with BINARY option (converter_obj_three_slim.py -t binary)
  26. // - urlbase parameter is mandatory (it applies to all models, it tells where to find the file with binary buffers)
  27. // - binary models consist of two files: JS and BIN
  28. loadBinary: function( url, callback, urlbase ) {
  29. // #1 load JS part via web worker
  30. // This isn't really necessary, JS part is tiny,
  31. // could be done by more ordinary means.
  32. var s = (new Date).getTime(),
  33. worker = new Worker( url );
  34. worker.onmessage = function( event ) {
  35. var materials = event.data.materials,
  36. buffers = event.data.buffers;
  37. // #2 load BIN part via Ajax
  38. // For some reason it is faster doing loading from here than from within the worker.
  39. // Maybe passing of ginormous string as message between threads is costly?
  40. // Also, worker loading huge data by Ajax still freezes browser. Go figure,
  41. // worker with baked ascii JSON data keeps browser more responsive.
  42. THREE.Loader.prototype.loadAjaxBuffers( buffers, materials, callback, urlbase );
  43. };
  44. worker.onerror = function (event) {
  45. alert( "worker.onerror: " + event.message + "\n" + event.data );
  46. event.preventDefault();
  47. };
  48. worker.postMessage( s );
  49. },
  50. // Binary AJAX parser based on Magi binary loader
  51. // https://github.com/kig/magi
  52. // Should look more into HTML5 File API
  53. // See also other suggestions by Gregg Tavares
  54. // https://groups.google.com/group/o3d-discuss/browse_thread/thread/a8967bc9ce1e0978
  55. loadAjaxBuffers: function( buffers, materials, callback, urlbase ) {
  56. var xhr = new XMLHttpRequest(),
  57. url = urlbase + "/" + buffers;
  58. xhr.onreadystatechange = function() {
  59. if ( xhr.readyState == 4 ) {
  60. if ( xhr.status == 200 || xhr.status == 0 ) {
  61. THREE.Loader.prototype.createBinModel( xhr.responseText, callback, urlbase, materials );
  62. } else {
  63. alert( "Couldn't load [" + url + "] [" + xhr.status + "]" );
  64. }
  65. }
  66. }
  67. xhr.open("GET", url, true);
  68. xhr.overrideMimeType("text/plain; charset=x-user-defined");
  69. xhr.setRequestHeader("Content-Type", "text/plain");
  70. xhr.send(null);
  71. },
  72. createBinModel: function ( data, callback, urlbase, materials ) {
  73. var Model = function ( urlbase ) {
  74. //var s = (new Date).getTime();
  75. var scope = this,
  76. currentOffset = 0,
  77. md,
  78. normals = [];
  79. THREE.Geometry.call(this);
  80. init_materials();
  81. md = parseMetaData( data, currentOffset );
  82. currentOffset += md.header_bytes;
  83. currentOffset += init_vertices( currentOffset );
  84. currentOffset += init_normals( currentOffset );
  85. currentOffset += init_triangles_flat( currentOffset );
  86. currentOffset += init_triangles_smooth( currentOffset );
  87. currentOffset += init_quads_flat( currentOffset );
  88. currentOffset += init_quads_smooth( currentOffset );
  89. currentOffset += init_uvs_tri( currentOffset );
  90. init_uvs_quad( data, currentOffset, md.nuvtri );
  91. this.computeCentroids();
  92. this.computeNormals();
  93. //var e = (new Date).getTime();
  94. //log( "binary data parse time: " + (e-s) + " ms" );
  95. function parseMetaData( data, offset ) {
  96. var metaData = {
  97. 'signature' :parseString( data, offset, 8 ),
  98. 'header_bytes' :parseUChar8( data, offset + 8 ),
  99. 'vertex_coordinate_bytes' :parseUChar8( data, offset + 9 ),
  100. 'vertex_index_bytes' :parseUChar8( data, offset + 10 ),
  101. 'normal_index_bytes' :parseUChar8( data, offset + 11 ),
  102. 'material_index_bytes' :parseUChar8( data, offset + 12 ),
  103. 'normal_coordinate_bytes' :parseUChar8( data, offset + 13 ),
  104. 'uv_coordinate_bytes' :parseUChar8( data, offset + 14 ),
  105. 'nvertices' :parseUInt32( data, offset + 15 ),
  106. 'ntri_flat' :parseUInt32( data, offset + 15 + 4*1 ),
  107. 'ntri_smooth' :parseUInt32( data, offset + 15 + 4*2 ),
  108. 'nquad_flat' :parseUInt32( data, offset + 15 + 4*3 ),
  109. 'nquad_smooth' :parseUInt32( data, offset + 15 + 4*4 ),
  110. 'nnormals' :parseUInt32( data, offset + 15 + 4*5 ),
  111. 'nuvtri' :parseUInt32( data, offset + 15 + 4*6 ),
  112. 'nuvquad' :parseUInt32( data, offset + 15 + 4*7 ),
  113. };
  114. /*
  115. log( "signature: " + metaData.signature );
  116. log( "header_bytes: " + metaData.header_bytes );
  117. log( "vertex_coordinate_bytes: " + metaData.vertex_coordinate_bytes );
  118. log( "vertex_index_bytes: " + metaData.vertex_index_bytes );
  119. log( "normal_index_bytes: " + metaData.normal_index_bytes );
  120. log( "material_index_bytes: " + metaData.material_index_bytes );
  121. log( "normal_coordinate_bytes: " + metaData.normal_coordinate_bytes );
  122. log( "uv_coordinate_bytes: " + metaData.uv_coordinate_bytes );
  123. log( "nvertices: " + metaData.nvertices );
  124. log( "ntri_flat: " + metaData.ntri_flat );
  125. log( "ntri_smooth: " + metaData.ntri_smooth );
  126. log( "nquad_flat: " + metaData.nquad_flat );
  127. log( "nquad_smooth: " + metaData.nquad_smooth );
  128. log( "nnormals: " + metaData.nnormals );
  129. log( "nuvtri: " + metaData.nuvtri );
  130. log( "nuvquad: " + metaData.nuvquad );
  131. */
  132. return metaData;
  133. }
  134. function parseString( data, offset, length ) {
  135. return data.substr( offset, length );
  136. }
  137. function parseFloat32( data, offset ) {
  138. var b3 = parseUChar8( data, offset ),
  139. b2 = parseUChar8( data, offset + 1 ),
  140. b1 = parseUChar8( data, offset + 2 ),
  141. b0 = parseUChar8( data, offset + 3 ),
  142. sign = 1 - ( 2 * ( b0 >> 7 ) ),
  143. exponent = ((( b0 << 1 ) & 0xff) | ( b1 >> 7 )) - 127,
  144. mantissa = (( b1 & 0x7f ) << 16) | (b2 << 8) | b3;
  145. if (mantissa == 0 && exponent == -127)
  146. return 0.0;
  147. return sign * ( 1 + mantissa * Math.pow( 2, -23 ) ) * Math.pow( 2, exponent );
  148. }
  149. function parseUInt32( data, offset ) {
  150. var b0 = parseUChar8( data, offset ),
  151. b1 = parseUChar8( data, offset + 1 ),
  152. b2 = parseUChar8( data, offset + 2 ),
  153. b3 = parseUChar8( data, offset + 3 );
  154. return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
  155. }
  156. function parseUInt16( data, offset ) {
  157. var b0 = parseUChar8( data, offset ),
  158. b1 = parseUChar8( data, offset + 1 );
  159. return (b1 << 8) + b0;
  160. }
  161. function parseSChar8( data, offset ) {
  162. var b = parseUChar8( data, offset );
  163. return b > 127 ? b - 256 : b;
  164. }
  165. function parseUChar8( data, offset ) {
  166. return data.charCodeAt( offset ) & 0xff;
  167. }
  168. function init_vertices( start ) {
  169. var i, x, y, z,
  170. stride = md.vertex_coordinate_bytes * 3;
  171. for( i = 0; i < md.nvertices; ++i ) {
  172. x = parseFloat32( data, start + i*stride );
  173. y = parseFloat32( data, start + i*stride + md.vertex_coordinate_bytes );
  174. z = parseFloat32( data, start + i*stride + md.vertex_coordinate_bytes*2 );
  175. scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
  176. }
  177. return md.nvertices * stride;
  178. }
  179. function init_triangles_flat( start ) {
  180. var i, a, b, c, m, material,
  181. stride = md.vertex_index_bytes * 3 + md.material_index_bytes;
  182. for( i = 0; i < md.ntri_flat; ++i ) {
  183. a = parseUInt32( data, start + i*stride );
  184. b = parseUInt32( data, start + i*stride + md.vertex_index_bytes );
  185. c = parseUInt32( data, start + i*stride + md.vertex_index_bytes*2 );
  186. m = parseUInt16( data, start + i*stride + md.vertex_index_bytes*3 );
  187. material = scope.materials[ m ];
  188. scope.faces.push( new THREE.Face3( a, b, c, null, material ) );
  189. }
  190. return md.ntri_flat * stride;
  191. }
  192. function init_triangles_smooth( start ) {
  193. var i, a, b, c, m, na, nb, nc, material,
  194. nax, nay, naz, nbx, nby, nbz, ncx, ncy, ncz,
  195. stride = md.vertex_index_bytes * 3 + md.material_index_bytes + md.normal_index_bytes * 3;
  196. for( i = 0; i < md.ntri_smooth; ++i ) {
  197. a = parseUInt32( data, start + i*stride );
  198. b = parseUInt32( data, start + i*stride + md.vertex_index_bytes );
  199. c = parseUInt32( data, start + i*stride + md.vertex_index_bytes*2 );
  200. m = parseUInt16( data, start + i*stride + md.vertex_index_bytes*3 );
  201. na = parseUInt32( data, start + i*stride + md.vertex_index_bytes*3 + md.material_index_bytes );
  202. nb = parseUInt32( data, start + i*stride + md.vertex_index_bytes*3 + md.material_index_bytes + md.normal_index_bytes );
  203. nc = parseUInt32( data, start + i*stride + md.vertex_index_bytes*3 + md.material_index_bytes + md.normal_index_bytes*2 );
  204. material = scope.materials[ m ];
  205. nax = normals[ na*3 ],
  206. nay = normals[ na*3 + 1 ],
  207. naz = normals[ na*3 + 2 ],
  208. nbx = normals[ nb*3 ],
  209. nby = normals[ nb*3 + 1 ],
  210. nbz = normals[ nb*3 + 2 ],
  211. ncx = normals[ nc*3 ],
  212. ncy = normals[ nc*3 + 1 ],
  213. ncz = normals[ nc*3 + 2 ];
  214. scope.faces.push( new THREE.Face3( a, b, c,
  215. [new THREE.Vector3( nax, nay, naz ),
  216. new THREE.Vector3( nbx, nby, nbz ),
  217. new THREE.Vector3( ncx, ncy, ncz )],
  218. material ) );
  219. }
  220. return md.ntri_smooth * stride;
  221. }
  222. function init_quads_flat( start ) {
  223. var i, a, b, c, d, m, material,
  224. stride = md.vertex_index_bytes * 4 + md.material_index_bytes;;
  225. for( i = 0; i < md.nquad_flat; ++i ) {
  226. a = parseUInt32( data, start + i*stride );
  227. b = parseUInt32( data, start + i*stride + md.vertex_index_bytes );
  228. c = parseUInt32( data, start + i*stride + md.vertex_index_bytes*2 );
  229. d = parseUInt32( data, start + i*stride + md.vertex_index_bytes*3 );
  230. m = parseUInt16( data, start + i*stride + md.vertex_index_bytes*4 );
  231. material = scope.materials[ m ];
  232. scope.faces.push( new THREE.Face4( a, b, c, d, null, material ) );
  233. }
  234. return md.nquad_flat * stride;
  235. }
  236. function init_quads_smooth( start ) {
  237. var i, a, b, c, d, m, na, nb, nc, nd, material,
  238. nax, nay, naz, nbx, nby, nbz, ncx, ncy, ncz, ndx, ndy, ndz,
  239. stride = md.vertex_index_bytes * 4 + md.material_index_bytes + md.normal_index_bytes * 4;
  240. for( i = 0; i < md.nquad_smooth; ++i ) {
  241. a = parseUInt32( data, start + i*stride );
  242. b = parseUInt32( data, start + i*stride + md.vertex_index_bytes );
  243. c = parseUInt32( data, start + i*stride + md.vertex_index_bytes*2 );
  244. d = parseUInt32( data, start + i*stride + md.vertex_index_bytes*3 );
  245. m = parseUInt16( data, start + i*stride + md.vertex_index_bytes*4 );
  246. na = parseUInt32( data, start + i*stride + md.vertex_index_bytes*4 + md.material_index_bytes );
  247. nb = parseUInt32( data, start + i*stride + md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes );
  248. nc = parseUInt32( data, start + i*stride + md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes*2 );
  249. nd = parseUInt32( data, start + i*stride + md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes*3 );
  250. material = scope.materials[ m ];
  251. nax = normals[ na*3 ],
  252. nay = normals[ na*3 + 1 ],
  253. naz = normals[ na*3 + 2 ],
  254. nbx = normals[ nb*3 ],
  255. nby = normals[ nb*3 + 1 ],
  256. nbz = normals[ nb*3 + 2 ],
  257. ncx = normals[ nc*3 ],
  258. ncy = normals[ nc*3 + 1 ],
  259. ncz = normals[ nc*3 + 2 ];
  260. ndx = normals[ nd*3 ],
  261. ndy = normals[ nd*3 + 1 ],
  262. ndz = normals[ nd*3 + 2 ];
  263. scope.faces.push( new THREE.Face4( a, b, c, d,
  264. [new THREE.Vector3( nax, nay, naz ),
  265. new THREE.Vector3( nbx, nby, nbz ),
  266. new THREE.Vector3( ncx, ncy, ncz ),
  267. new THREE.Vector3( ndx, ndy, ndz )],
  268. material ) );
  269. }
  270. return md.nquad_smooth * stride;
  271. }
  272. function init_uvs_tri( start ) {
  273. var i, ua, ub, uc, va, vb, vc, uv,
  274. stride = md.uv_coordinate_bytes * 6;
  275. for( i = 0; i < md.nuvtri; i++ ) {
  276. ua = parseFloat32( data, start + i*stride );
  277. va = parseFloat32( data, start + i*stride + 4 );
  278. ub = parseFloat32( data, start + i*stride + 8 );
  279. vb = parseFloat32( data, start + i*stride + 12 );
  280. uc = parseFloat32( data, start + i*stride + 16 );
  281. vc = parseFloat32( data, start + i*stride + 20 );
  282. uv = [];
  283. uv.push( new THREE.UV( ua, va ) );
  284. uv.push( new THREE.UV( ub, vb ) );
  285. uv.push( new THREE.UV( uc, vc ) );
  286. scope.uvs.push( uv );
  287. }
  288. return md.nuvtri * stride;
  289. }
  290. function init_uvs_quad( start ) {
  291. var i, ua, ub, uc, ud, va, vb, vc, vd, uv,
  292. stride = md.uv_coordinate_bytes * 8;
  293. for( i = 0; i < md.nuvquad; i++ ) {
  294. ua = parseFloat32( data, start + i*stride );
  295. va = parseFloat32( data, start + i*stride + 4 );
  296. ub = parseFloat32( data, start + i*stride + 8 );
  297. vb = parseFloat32( data, start + i*stride + 12 );
  298. uc = parseFloat32( data, start + i*stride + 16 );
  299. vc = parseFloat32( data, start + i*stride + 20 );
  300. ud = parseFloat32( data, start + i*stride + 24 );
  301. vd = parseFloat32( data, start + i*stride + 28 );
  302. uv = [];
  303. uv.push( new THREE.UV( ua, va ) );
  304. uv.push( new THREE.UV( ub, vb ) );
  305. uv.push( new THREE.UV( uc, vc ) );
  306. uv.push( new THREE.UV( ud, vd ) );
  307. scope.uvs.push( uv );
  308. }
  309. return md.nuvquad * stride;
  310. }
  311. function init_normals( start ) {
  312. var i, x, y, z,
  313. stride = md.normal_coordinate_bytes * 3;
  314. for( i = 0; i < md.nnormals; ++i ) {
  315. x = parseSChar8( data, start + i*stride );
  316. y = parseSChar8( data, start + i*stride + md.normal_coordinate_bytes );
  317. z = parseSChar8( data, start + i*stride + md.normal_coordinate_bytes*2 );
  318. normals.push( x/127, y/127, z/127 );
  319. }
  320. return md.nnormals * stride;
  321. }
  322. function init_materials() {
  323. scope.materials = [];
  324. for( var i = 0; i < materials.length; ++i ) {
  325. scope.materials[i] = [ create_material( materials[i], urlbase ) ];
  326. }
  327. //log( "materials: " + scope.materials.length );
  328. }
  329. function is_pow2( n ) {
  330. var l = Math.log(n) / Math.LN2;
  331. return Math.floor(l) == l;
  332. }
  333. function nearest_pow2(n) {
  334. var l = Math.log(n) / Math.LN2;
  335. return Math.pow( 2, Math.round(l) );
  336. }
  337. function create_material( m ) {
  338. var material, texture, image, color;
  339. if( m.map_diffuse && urlbase ) {
  340. texture = document.createElement( 'canvas' );
  341. material = new THREE.MeshBitmapMaterial( texture );
  342. image = new Image();
  343. image.onload = function () {
  344. if ( !is_pow2( this.width ) || !is_pow2( this.height ) ) {
  345. var w = nearest_pow2( this.width ),
  346. h = nearest_pow2( this.height );
  347. material.bitmap.width = w;
  348. material.bitmap.height = h;
  349. material.bitmap.getContext("2d").drawImage( this, 0, 0, w, h );
  350. } else {
  351. material.bitmap = this;
  352. }
  353. material.loaded = 1;
  354. };
  355. image.src = urlbase + "/" + m.map_diffuse;
  356. } else if( m.col_diffuse ) {
  357. color = (m.col_diffuse[0]*255 << 16) + (m.col_diffuse[1]*255 << 8) + m.col_diffuse[2]*255;
  358. material = new THREE.MeshColorFillMaterial( color, m.transparency );
  359. } else if( m.a_dbg_color ) {
  360. material = new THREE.MeshColorFillMaterial( m.a_dbg_color );
  361. } else {
  362. material = new THREE.MeshColorFillMaterial( 0xeeeeee );
  363. }
  364. return material;
  365. }
  366. }
  367. Model.prototype = new THREE.Geometry();
  368. Model.prototype.constructor = Model;
  369. callback( new Model( urlbase ) );
  370. },
  371. createModel: function ( data, callback, urlbase ) {
  372. var Model = function ( urlbase ) {
  373. var scope = this;
  374. THREE.Geometry.call(this);
  375. init_materials();
  376. init_vertices();
  377. init_uvs();
  378. init_faces();
  379. this.computeCentroids();
  380. this.computeNormals();
  381. function init_vertices() {
  382. var i, l, x, y, z;
  383. for( i = 0, l = data.vertices.length/3; i < l; i++ ) {
  384. x = data.vertices[ i*3 ];
  385. y = data.vertices[ i*3 + 1 ];
  386. z = data.vertices[ i*3 + 2 ];
  387. v( x, y, z );
  388. }
  389. }
  390. function init_uvs() {
  391. var i, l, ua, ub, uc, ud, va, vb, vc, vd;
  392. for( i = 0, l = data.uvs_tri.length; i < l; i++ ) {
  393. ua = data.uvs_tri[ i*6 ];
  394. va = data.uvs_tri[ i*6 + 1 ];
  395. ub = data.uvs_tri[ i*6 + 2 ];
  396. vb = data.uvs_tri[ i*6 + 3 ];
  397. uc = data.uvs_tri[ i*6 + 4 ];
  398. vc = data.uvs_tri[ i*6 + 5 ];
  399. uv( ua, va, ub, vb, uc, vc );
  400. }
  401. for( i = 0, l = data.uvs_quad.length; i < l; i++ ) {
  402. ua = data.uvs_quad[ i*8 ];
  403. va = data.uvs_quad[ i*8 + 1 ];
  404. ub = data.uvs_quad[ i*8 + 2 ];
  405. vb = data.uvs_quad[ i*8 + 3 ];
  406. uc = data.uvs_quad[ i*8 + 4 ];
  407. vc = data.uvs_quad[ i*8 + 5 ];
  408. ud = data.uvs_quad[ i*8 + 6 ];
  409. vd = data.uvs_quad[ i*8 + 7 ];
  410. uv( ua, va, ub, vb, uc, vc, ud, vd );
  411. }
  412. }
  413. function init_faces() {
  414. var i, l, a, b, c, d, m, na, nb, nc, nd;
  415. for( i = 0, l = data.triangles.length/4; i < l; i++ ) {
  416. a = data.triangles[ i*4 ];
  417. b = data.triangles[ i*4 + 1 ];
  418. c = data.triangles[ i*4 + 2 ];
  419. m = data.triangles[ i*4 + 3 ];
  420. f3( a, b, c, m );
  421. }
  422. for( i = 0, l = data.triangles_n.length/7; i < l; i++ ) {
  423. a = data.triangles_n[ i*7 ];
  424. b = data.triangles_n[ i*7 + 1 ];
  425. c = data.triangles_n[ i*7 + 2 ];
  426. m = data.triangles_n[ i*7 + 3 ];
  427. na = data.triangles_n[ i*7 + 4 ];
  428. nb = data.triangles_n[ i*7 + 5 ];
  429. nc = data.triangles_n[ i*7 + 6 ];
  430. f3n( a, b, c, m, na, nb, nc );
  431. }
  432. for( i = 0, l = data.quads.length/5; i < l; i++ ) {
  433. a = data.quads[ i*5 ];
  434. b = data.quads[ i*5 + 1 ];
  435. c = data.quads[ i*5 + 2 ];
  436. d = data.quads[ i*5 + 3 ];
  437. m = data.quads[ i*5 + 4 ];
  438. f4( a, b, c, d, m );
  439. }
  440. for( i = 0, l = data.quads_n.length/9; i < l; i++ ) {
  441. a = data.quads_n[ i*9 ];
  442. b = data.quads_n[ i*9 + 1 ];
  443. c = data.quads_n[ i*9 + 2 ];
  444. d = data.quads_n[ i*9 + 3 ];
  445. m = data.quads_n[ i*9 + 4 ];
  446. na = data.quads_n[ i*9 + 5 ];
  447. nb = data.quads_n[ i*9 + 6 ];
  448. nc = data.quads_n[ i*9 + 7 ];
  449. nd = data.quads_n[ i*9 + 8 ];
  450. f4n( a, b, c, d, m, na, nb, nc, nd );
  451. }
  452. }
  453. function v( x, y, z ) {
  454. scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
  455. }
  456. function f3( a, b, c, mi ) {
  457. var material = scope.materials[ mi ];
  458. scope.faces.push( new THREE.Face3( a, b, c, null, material ) );
  459. }
  460. function f4( a, b, c, d, mi ) {
  461. var material = scope.materials[ mi ];
  462. scope.faces.push( new THREE.Face4( a, b, c, d, null, material ) );
  463. }
  464. function f3n( a, b, c, mi, na, nb, nc ) {
  465. var material = scope.materials[ mi ],
  466. nax = data.normals[ na*3 ],
  467. nay = data.normals[ na*3 + 1 ],
  468. naz = data.normals[ na*3 + 2 ],
  469. nbx = data.normals[ nb*3 ],
  470. nby = data.normals[ nb*3 + 1 ],
  471. nbz = data.normals[ nb*3 + 2 ],
  472. ncx = data.normals[ nc*3 ],
  473. ncy = data.normals[ nc*3 + 1 ],
  474. ncz = data.normals[ nc*3 + 2 ];
  475. scope.faces.push( new THREE.Face3( a, b, c,
  476. [new THREE.Vector3( nax, nay, naz ), new THREE.Vector3( nbx, nby, nbz ), new THREE.Vector3( ncx, ncy, ncz )],
  477. material ) );
  478. }
  479. function f4n( a, b, c, d, mi, na, nb, nc, nd ) {
  480. var material = scope.materials[ mi ],
  481. nax = data.normals[ na*3 ],
  482. nay = data.normals[ na*3 + 1 ],
  483. naz = data.normals[ na*3 + 2 ],
  484. nbx = data.normals[ nb*3 ],
  485. nby = data.normals[ nb*3 + 1 ],
  486. nbz = data.normals[ nb*3 + 2 ],
  487. ncx = data.normals[ nc*3 ],
  488. ncy = data.normals[ nc*3 + 1 ],
  489. ncz = data.normals[ nc*3 + 2 ],
  490. ndx = data.normals[ nd*3 ],
  491. ndy = data.normals[ nd*3 + 1 ],
  492. ndz = data.normals[ nd*3 + 2 ];
  493. scope.faces.push( new THREE.Face4( a, b, c, d,
  494. [new THREE.Vector3( nax, nay, naz ), new THREE.Vector3( nbx, nby, nbz ), new THREE.Vector3( ncx, ncy, ncz ), new THREE.Vector3( ndx, ndy, ndz )],
  495. material ) );
  496. }
  497. function uv( u1, v1, u2, v2, u3, v3, u4, v4 ) {
  498. var uv = [];
  499. uv.push( new THREE.UV( u1, v1 ) );
  500. uv.push( new THREE.UV( u2, v2 ) );
  501. uv.push( new THREE.UV( u3, v3 ) );
  502. if ( u4 && v4 ) uv.push( new THREE.UV( u4, v4 ) );
  503. scope.uvs.push( uv );
  504. }
  505. function init_materials() {
  506. scope.materials = [];
  507. for( var i = 0; i < data.materials.length; ++i ) {
  508. scope.materials[i] = [ create_material( data.materials[i], urlbase ) ];
  509. }
  510. }
  511. function is_pow2( n ) {
  512. var l = Math.log(n) / Math.LN2;
  513. return Math.floor(l) == l;
  514. }
  515. function nearest_pow2(n) {
  516. var l = Math.log(n) / Math.LN2;
  517. return Math.pow( 2, Math.round(l) );
  518. }
  519. function create_material( m ) {
  520. var material, texture, image, color;
  521. if( m.map_diffuse && urlbase ) {
  522. texture = document.createElement( 'canvas' );
  523. material = new THREE.MeshBitmapMaterial( texture );
  524. image = new Image();
  525. image.onload = function () {
  526. if ( !is_pow2( this.width ) || !is_pow2( this.height ) ) {
  527. var w = nearest_pow2( this.width ),
  528. h = nearest_pow2( this.height );
  529. material.bitmap.width = w;
  530. material.bitmap.height = h;
  531. material.bitmap.getContext("2d").drawImage( this, 0, 0, w, h );
  532. } else {
  533. material.bitmap = this;
  534. }
  535. material.loaded = 1;
  536. };
  537. image.src = urlbase + "/" + m.map_diffuse;
  538. } else if( m.col_diffuse ) {
  539. color = (m.col_diffuse[0]*255 << 16) + (m.col_diffuse[1]*255 << 8) + m.col_diffuse[2]*255;
  540. material = new THREE.MeshColorFillMaterial( color, m.transparency );
  541. } else if( m.a_dbg_color ) {
  542. material = new THREE.MeshColorFillMaterial( m.a_dbg_color );
  543. } else {
  544. material = new THREE.MeshColorFillMaterial( 0xeeeeee );
  545. }
  546. return material;
  547. }
  548. }
  549. Model.prototype = new THREE.Geometry();
  550. Model.prototype.constructor = Model;
  551. callback( new Model( urlbase ) );
  552. }
  553. };
粤ICP备19079148号