| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228 |
- /**
- * @author alteredq / http://alteredqualia.com/
- */
- THREE.Loader = function( showStatus ) {
-
- this.showStatus = showStatus;
-
- this.statusDomElement = showStatus ? this.addStatusElement() : null;
- };
- THREE.Loader.prototype = {
- addStatusElement: function ( ) {
-
- var e = document.createElement( "div" );
-
- e.style.fontSize = "0.8em";
- e.style.textAlign = "left";
- e.style.background = "#b00";
- e.style.color = "#fff";
- e.style.width = "140px";
- e.style.padding = "0.25em 0.25em 0.25em 0.5em";
- e.style.position = "absolute";
- e.style.right = "0px";
- e.style.top = "0px";
- e.style.zIndex = 1000;
-
- e.innerHTML = "Loading ...";
-
- return e;
-
- },
-
- updateProgress: function ( progress ) {
- var message = "Loaded ";
- if ( progress.total ) {
- message += ( 100 * progress.loaded / progress.total ).toFixed(0) + "%";
- } else {
- message += ( progress.loaded / 1000 ).toFixed(2) + " KB";
- }
- this.statusDomElement.innerHTML = message;
- },
-
- // Load models generated by Blender exporter and original OBJ converter (converter_obj_three.py)
- loadAsciiOld: function( url, callback ) {
- var element = document.createElement( 'script' );
- element.type = 'text/javascript';
- element.onload = callback;
- element.src = url;
- document.getElementsByTagName( "head" )[ 0 ].appendChild( element );
- },
- // Load models generated by slim OBJ converter with ASCII option (converter_obj_three_slim.py -t ascii)
- // - parameters
- // - model (required)
- // - callback (required)
- // - texture_path (optional: if not specified, textures will be assumed to be in the same folder as JS model file)
- loadAscii: function ( parameters ) {
- var url = parameters.model,
- callback = parameters.callback,
- texture_path = parameters.texture_path ? parameters.texture_path : THREE.Loader.prototype.extractUrlbase( url ),
-
- s = (new Date).getTime(),
- worker = new Worker( url );
-
- worker.onmessage = function( event ) {
-
- THREE.Loader.prototype.createModel( event.data, callback, texture_path );
- };
- worker.postMessage( s );
- },
- // Load models generated by slim OBJ converter with BINARY option (converter_obj_three_slim.py -t binary)
- // - binary models consist of two files: JS and BIN
- // - parameters
- // - model (required)
- // - callback (required)
- // - bin_path (optional: if not specified, binary file will be assumed to be in the same folder as JS model file)
- // - texture_path (optional: if not specified, textures will be assumed to be in the same folder as JS model file)
- loadBinary: function( parameters ) {
-
- // #1 load JS part via web worker
- // This isn't really necessary, JS part is tiny,
- // could be done by more ordinary means.
- var url = parameters.model,
- callback = parameters.callback,
- texture_path = parameters.texture_path ? parameters.texture_path : THREE.Loader.prototype.extractUrlbase( url ),
- bin_path = parameters.bin_path ? parameters.bin_path : THREE.Loader.prototype.extractUrlbase( url ),
- s = (new Date).getTime(),
- worker = new Worker( url ),
- callback_progress = this.showProgress ? THREE.Loader.prototype.updateProgress : null;
-
- worker.onmessage = function( event ) {
- var materials = event.data.materials,
- buffers = event.data.buffers;
- // #2 load BIN part via Ajax
- // For some reason it is faster doing loading from here than from within the worker.
- // Maybe passing of ginormous string as message between threads is costly?
- // Also, worker loading huge data by Ajax still freezes browser. Go figure,
- // worker with baked ascii JSON data keeps browser more responsive.
- THREE.Loader.prototype.loadAjaxBuffers( buffers, materials, callback, bin_path, texture_path, callback_progress );
- };
- worker.onerror = function (event) {
- alert( "worker.onerror: " + event.message + "\n" + event.data );
- event.preventDefault();
- };
- worker.postMessage( s );
- },
- // Binary AJAX parser based on Magi binary loader
- // https://github.com/kig/magi
- // Should look more into HTML5 File API
- // See also other suggestions by Gregg Tavares
- // https://groups.google.com/group/o3d-discuss/browse_thread/thread/a8967bc9ce1e0978
- loadAjaxBuffers: function( buffers, materials, callback, bin_path, texture_path, callback_progress ) {
- var xhr = new XMLHttpRequest(),
- url = bin_path + "/" + buffers;
- var length = 0;
-
- xhr.onreadystatechange = function() {
-
- if ( xhr.readyState == 4 ) {
- if ( xhr.status == 200 || xhr.status == 0 ) {
- THREE.Loader.prototype.createBinModel( xhr.responseText, callback, texture_path, materials );
- } else {
- alert( "Couldn't load [" + url + "] [" + xhr.status + "]" );
- }
-
- } else if ( xhr.readyState == 3 ) {
-
- if ( callback_progress ) {
-
- if ( length == 0 ) {
-
- length = xhr.getResponseHeader( "Content-Length" );
-
- }
-
- callback_progress( { total: length, loaded: xhr.responseText.length } );
-
- }
-
- } else if ( xhr.readyState == 2 ) {
-
- length = xhr.getResponseHeader( "Content-Length" );
-
- }
-
- }
- xhr.open("GET", url, true);
- xhr.overrideMimeType("text/plain; charset=x-user-defined");
- xhr.setRequestHeader("Content-Type", "text/plain");
- xhr.send(null);
- },
- createBinModel: function ( data, callback, texture_path, materials ) {
- var Model = function ( texture_path ) {
- //var s = (new Date).getTime();
- var scope = this,
- currentOffset = 0,
- md,
- normals = [],
- uvs = [],
- tri_b, tri_c, tri_m, tri_na, tri_nb, tri_nc,
- quad_b, quad_c, quad_d, quad_m, quad_na, quad_nb, quad_nc, quad_nd,
- tri_uvb, tri_uvc, quad_uvb, quad_uvc, quad_uvd,
- start_tri_flat, start_tri_smooth, start_tri_flat_uv, start_tri_smooth_uv,
- start_quad_flat, start_quad_smooth, start_quad_flat_uv, start_quad_smooth_uv,
- tri_size, quad_size,
- len_tri_flat, len_tri_smooth, len_tri_flat_uv, len_tri_smooth_uv,
- len_quad_flat, len_quad_smooth, len_quad_flat_uv, len_quad_smooth_uv;
- THREE.Geometry.call(this);
- THREE.Loader.prototype.init_materials( scope, materials, texture_path );
- md = parseMetaData( data, currentOffset );
- currentOffset += md.header_bytes;
- // cache offsets
-
- tri_b = md.vertex_index_bytes,
- tri_c = md.vertex_index_bytes*2,
- tri_m = md.vertex_index_bytes*3,
- tri_na = md.vertex_index_bytes*3 + md.material_index_bytes,
- tri_nb = md.vertex_index_bytes*3 + md.material_index_bytes + md.normal_index_bytes,
- tri_nc = md.vertex_index_bytes*3 + md.material_index_bytes + md.normal_index_bytes*2,
-
- quad_b = md.vertex_index_bytes,
- quad_c = md.vertex_index_bytes*2,
- quad_d = md.vertex_index_bytes*3,
- quad_m = md.vertex_index_bytes*4,
- quad_na = md.vertex_index_bytes*4 + md.material_index_bytes,
- quad_nb = md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes,
- quad_nc = md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes*2,
- quad_nd = md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes*3,
-
- tri_uvb = md.uv_index_bytes,
- tri_uvc = md.uv_index_bytes * 2,
-
- quad_uvb = md.uv_index_bytes,
- quad_uvc = md.uv_index_bytes * 2,
- quad_uvd = md.uv_index_bytes * 3;
-
- // buffers sizes
-
- tri_size = md.vertex_index_bytes * 3 + md.material_index_bytes;
- quad_size = md.vertex_index_bytes * 4 + md.material_index_bytes;
- len_tri_flat = md.ntri_flat * ( tri_size );
- len_tri_smooth = md.ntri_smooth * ( tri_size + md.normal_index_bytes * 3 );
- len_tri_flat_uv = md.ntri_flat_uv * ( tri_size + md.uv_index_bytes * 3 );
- len_tri_smooth_uv = md.ntri_smooth_uv * ( tri_size + md.normal_index_bytes * 3 + md.uv_index_bytes * 3 );
- len_quad_flat = md.nquad_flat * ( quad_size );
- len_quad_smooth = md.nquad_smooth * ( quad_size + md.normal_index_bytes * 4 );
- len_quad_flat_uv = md.nquad_flat_uv * ( quad_size + md.uv_index_bytes * 4 );
- len_quad_smooth_uv = md.nquad_smooth_uv * ( quad_size + md.normal_index_bytes * 4 + md.uv_index_bytes * 4 );
-
- // read buffers
-
- currentOffset += init_vertices( currentOffset );
- currentOffset += init_normals( currentOffset );
- currentOffset += init_uvs( currentOffset );
- start_tri_flat = currentOffset;
- start_tri_smooth = start_tri_flat + len_tri_flat;
- start_tri_flat_uv = start_tri_smooth + len_tri_smooth;
- start_tri_smooth_uv = start_tri_flat_uv + len_tri_flat_uv;
-
- start_quad_flat = start_tri_smooth_uv + len_tri_smooth_uv;
- start_quad_smooth = start_quad_flat + len_quad_flat;
- start_quad_flat_uv = start_quad_smooth + len_quad_smooth;
- start_quad_smooth_uv= start_quad_flat_uv +len_quad_flat_uv;
- // have to first process faces with uvs
- // so that face and uv indices match
-
- init_triangles_flat_uv( start_tri_flat_uv );
- init_triangles_smooth_uv( start_tri_smooth_uv );
- init_quads_flat_uv( start_quad_flat_uv );
- init_quads_smooth_uv( start_quad_smooth_uv );
- // now we can process untextured faces
-
- init_triangles_flat( start_tri_flat );
- init_triangles_smooth( start_tri_smooth );
- init_quads_flat( start_quad_flat );
- init_quads_smooth( start_quad_smooth );
- this.computeCentroids();
- this.computeFaceNormals();
- this.sortFacesByMaterial();
- //var e = (new Date).getTime();
- //log( "binary data parse time: " + (e-s) + " ms" );
- function parseMetaData( data, offset ) {
- var metaData = {
- 'signature' :parseString( data, offset, 8 ),
- 'header_bytes' :parseUChar8( data, offset + 8 ),
- 'vertex_coordinate_bytes' :parseUChar8( data, offset + 9 ),
- 'normal_coordinate_bytes' :parseUChar8( data, offset + 10 ),
- 'uv_coordinate_bytes' :parseUChar8( data, offset + 11 ),
- 'vertex_index_bytes' :parseUChar8( data, offset + 12 ),
- 'normal_index_bytes' :parseUChar8( data, offset + 13 ),
- 'uv_index_bytes' :parseUChar8( data, offset + 14 ),
- 'material_index_bytes' :parseUChar8( data, offset + 15 ),
- 'nvertices' :parseUInt32( data, offset + 16 ),
- 'nnormals' :parseUInt32( data, offset + 16 + 4*1 ),
- 'nuvs' :parseUInt32( data, offset + 16 + 4*2 ),
- 'ntri_flat' :parseUInt32( data, offset + 16 + 4*3 ),
- 'ntri_smooth' :parseUInt32( data, offset + 16 + 4*4 ),
- 'ntri_flat_uv' :parseUInt32( data, offset + 16 + 4*5 ),
- 'ntri_smooth_uv' :parseUInt32( data, offset + 16 + 4*6 ),
- 'nquad_flat' :parseUInt32( data, offset + 16 + 4*7 ),
- 'nquad_smooth' :parseUInt32( data, offset + 16 + 4*8 ),
- 'nquad_flat_uv' :parseUInt32( data, offset + 16 + 4*9 ),
- 'nquad_smooth_uv' :parseUInt32( data, offset + 16 + 4*10 )
- };
- /*
- log( "signature: " + metaData.signature );
- log( "header_bytes: " + metaData.header_bytes );
- log( "vertex_coordinate_bytes: " + metaData.vertex_coordinate_bytes );
- log( "normal_coordinate_bytes: " + metaData.normal_coordinate_bytes );
- log( "uv_coordinate_bytes: " + metaData.uv_coordinate_bytes );
- log( "vertex_index_bytes: " + metaData.vertex_index_bytes );
- log( "normal_index_bytes: " + metaData.normal_index_bytes );
- log( "uv_index_bytes: " + metaData.uv_index_bytes );
- log( "material_index_bytes: " + metaData.material_index_bytes );
- log( "nvertices: " + metaData.nvertices );
- log( "nnormals: " + metaData.nnormals );
- log( "nuvs: " + metaData.nuvs );
- log( "ntri_flat: " + metaData.ntri_flat );
- log( "ntri_smooth: " + metaData.ntri_smooth );
- log( "ntri_flat_uv: " + metaData.ntri_flat_uv );
- log( "ntri_smooth_uv: " + metaData.ntri_smooth_uv );
- log( "nquad_flat: " + metaData.nquad_flat );
- log( "nquad_smooth: " + metaData.nquad_smooth );
- log( "nquad_flat_uv: " + metaData.nquad_flat_uv );
- log( "nquad_smooth_uv: " + metaData.nquad_smooth_uv );
- var total = metaData.header_bytes
- + metaData.nvertices * metaData.vertex_coordinate_bytes * 3
- + metaData.nnormals * metaData.normal_coordinate_bytes * 3
- + metaData.nuvs * metaData.uv_coordinate_bytes * 2
- + metaData.ntri_flat * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes )
- + metaData.ntri_smooth * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 )
- + metaData.ntri_flat_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.uv_index_bytes*3 )
- + metaData.ntri_smooth_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 + metaData.uv_index_bytes*3 )
- + metaData.nquad_flat * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes )
- + metaData.nquad_smooth * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 )
- + metaData.nquad_flat_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.uv_index_bytes*4 )
- + metaData.nquad_smooth_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 + metaData.uv_index_bytes*4 );
- log( "total bytes: " + total );
- */
- return metaData;
- }
- function parseString( data, offset, length ) {
- return data.substr( offset, length );
- }
- function parseFloat32( data, offset ) {
- var b3 = parseUChar8( data, offset ),
- b2 = parseUChar8( data, offset + 1 ),
- b1 = parseUChar8( data, offset + 2 ),
- b0 = parseUChar8( data, offset + 3 ),
- sign = 1 - ( 2 * ( b0 >> 7 ) ),
- exponent = ((( b0 << 1 ) & 0xff) | ( b1 >> 7 )) - 127,
- mantissa = (( b1 & 0x7f ) << 16) | (b2 << 8) | b3;
- if (mantissa == 0 && exponent == -127)
- return 0.0;
- return sign * ( 1 + mantissa * Math.pow( 2, -23 ) ) * Math.pow( 2, exponent );
- }
- function parseUInt32( data, offset ) {
- var b0 = parseUChar8( data, offset ),
- b1 = parseUChar8( data, offset + 1 ),
- b2 = parseUChar8( data, offset + 2 ),
- b3 = parseUChar8( data, offset + 3 );
- return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
- }
- function parseUInt16( data, offset ) {
- var b0 = parseUChar8( data, offset ),
- b1 = parseUChar8( data, offset + 1 );
- return (b1 << 8) + b0;
- }
- function parseSChar8( data, offset ) {
- var b = parseUChar8( data, offset );
- return b > 127 ? b - 256 : b;
- }
- function parseUChar8( data, offset ) {
- return data.charCodeAt( offset ) & 0xff;
- }
- function init_vertices( start ) {
- var i, x, y, z,
- stride = md.vertex_coordinate_bytes * 3,
- end = start + md.nvertices * stride;
- for( i = start; i < end; i += stride ) {
- x = parseFloat32( data, i );
- y = parseFloat32( data, i + md.vertex_coordinate_bytes );
- z = parseFloat32( data, i + md.vertex_coordinate_bytes*2 );
- THREE.Loader.prototype.v( scope, x, y, z );
- }
- return md.nvertices * stride;
- }
- function init_normals( start ) {
- var i, x, y, z,
- stride = md.normal_coordinate_bytes * 3,
- end = start + md.nnormals * stride;
- for( i = start; i < end; i += stride ) {
- x = parseSChar8( data, i );
- y = parseSChar8( data, i + md.normal_coordinate_bytes );
- z = parseSChar8( data, i + md.normal_coordinate_bytes*2 );
- normals.push( x/127, y/127, z/127 );
- }
- return md.nnormals * stride;
- }
- function init_uvs( start ) {
- var i, u, v,
- stride = md.uv_coordinate_bytes * 2,
- end = start + md.nuvs * stride;
- for( i = start; i < end; i += stride ) {
- u = parseFloat32( data, i );
- v = parseFloat32( data, i + md.uv_coordinate_bytes );
- uvs.push( u, v );
- }
-
- return md.nuvs * stride;
- }
-
- function add_tri( i ) {
- var a, b, c, m;
- a = parseUInt32( data, i );
- b = parseUInt32( data, i + tri_b );
- c = parseUInt32( data, i + tri_c );
- m = parseUInt16( data, i + tri_m );
- THREE.Loader.prototype.f3( scope, a, b, c, m );
- }
- function add_tri_n( i ) {
- var a, b, c, m, na, nb, nc;
- a = parseUInt32( data, i );
- b = parseUInt32( data, i + tri_b );
- c = parseUInt32( data, i + tri_c );
- m = parseUInt16( data, i + tri_m );
- na = parseUInt32( data, i + tri_na );
- nb = parseUInt32( data, i + tri_nb );
- nc = parseUInt32( data, i + tri_nc );
- THREE.Loader.prototype.f3n( scope, normals, a, b, c, m, na, nb, nc );
- }
- function add_quad( i ) {
- var a, b, c, d, m;
- a = parseUInt32( data, i );
- b = parseUInt32( data, i + quad_b );
- c = parseUInt32( data, i + quad_c );
- d = parseUInt32( data, i + quad_d );
- m = parseUInt16( data, i + quad_m );
- THREE.Loader.prototype.f4( scope, a, b, c, d, m );
- }
- function add_quad_n( i ) {
- var a, b, c, d, m, na, nb, nc, nd;
- a = parseUInt32( data, i );
- b = parseUInt32( data, i + quad_b );
- c = parseUInt32( data, i + quad_c );
- d = parseUInt32( data, i + quad_d );
- m = parseUInt16( data, i + quad_m );
- na = parseUInt32( data, i + quad_na );
- nb = parseUInt32( data, i + quad_nb );
- nc = parseUInt32( data, i + quad_nc );
- nd = parseUInt32( data, i + quad_nd );
- THREE.Loader.prototype.f4n( scope, normals, a, b, c, d, m, na, nb, nc, nd );
- }
- function add_uv3( i ) {
- var uva, uvb, uvc, u1, u2, u3, v1, v2, v3;
- uva = parseUInt32( data, i );
- uvb = parseUInt32( data, i + tri_uvb );
- uvc = parseUInt32( data, i + tri_uvc );
- u1 = uvs[ uva*2 ];
- v1 = uvs[ uva*2 + 1 ];
- u2 = uvs[ uvb*2 ];
- v2 = uvs[ uvb*2 + 1 ];
- u3 = uvs[ uvc*2 ];
- v3 = uvs[ uvc*2 + 1 ];
- THREE.Loader.prototype.uv3( scope.uvs, u1, v1, u2, v2, u3, v3 );
- }
- function add_uv4( i ) {
- var uva, uvb, uvc, uvd, u1, u2, u3, u4, v1, v2, v3, v4;
- uva = parseUInt32( data, i );
- uvb = parseUInt32( data, i + quad_uvb );
- uvc = parseUInt32( data, i + quad_uvc );
- uvd = parseUInt32( data, i + quad_uvd );
- u1 = uvs[ uva*2 ];
- v1 = uvs[ uva*2 + 1 ];
- u2 = uvs[ uvb*2 ];
- v2 = uvs[ uvb*2 + 1 ];
- u3 = uvs[ uvc*2 ];
- v3 = uvs[ uvc*2 + 1 ];
- u4 = uvs[ uvd*2 ];
- v4 = uvs[ uvd*2 + 1 ];
- THREE.Loader.prototype.uv4( scope.uvs, u1, v1, u2, v2, u3, v3, u4, v4 );
- }
- function init_triangles_flat( start ) {
- var i, stride = md.vertex_index_bytes * 3 + md.material_index_bytes,
- end = start + md.ntri_flat * stride;
- for( i = start; i < end; i += stride ) {
- add_tri( i );
- }
- return end - start;
- }
- function init_triangles_flat_uv( start ) {
- var i, offset = md.vertex_index_bytes * 3 + md.material_index_bytes,
- stride = offset + md.uv_index_bytes * 3,
- end = start + md.ntri_flat_uv * stride;
- for( i = start; i < end; i += stride ) {
- add_tri( i );
- add_uv3( i + offset );
- }
- return end - start;
- }
- function init_triangles_smooth( start ) {
- var i, stride = md.vertex_index_bytes * 3 + md.material_index_bytes + md.normal_index_bytes * 3,
- end = start + md.ntri_smooth * stride;
- for( i = start; i < end; i += stride ) {
- add_tri_n( i );
- }
- return end - start;
- }
- function init_triangles_smooth_uv( start ) {
- var i, offset = md.vertex_index_bytes * 3 + md.material_index_bytes + md.normal_index_bytes * 3,
- stride = offset + md.uv_index_bytes * 3,
- end = start + md.ntri_smooth_uv * stride;
- for( i = start; i < end; i += stride ) {
- add_tri_n( i );
- add_uv3( i + offset );
- }
- return end - start;
- }
- function init_quads_flat( start ) {
- var i, stride = md.vertex_index_bytes * 4 + md.material_index_bytes,
- end = start + md.nquad_flat * stride;
- for( i = start; i < end; i += stride ) {
- add_quad( i );
- }
- return end - start;
- }
- function init_quads_flat_uv( start ) {
- var i, offset = md.vertex_index_bytes * 4 + md.material_index_bytes,
- stride = offset + md.uv_index_bytes * 4,
- end = start + md.nquad_flat_uv * stride;
- for( i = start; i < end; i += stride ) {
- add_quad( i );
- add_uv4( i + offset );
- }
- return end - start;
- }
- function init_quads_smooth( start ) {
- var i, stride = md.vertex_index_bytes * 4 + md.material_index_bytes + md.normal_index_bytes * 4,
- end = start + md.nquad_smooth * stride;
- for( i = start; i < end; i += stride ) {
- add_quad_n( i );
- }
- return end - start;
- }
- function init_quads_smooth_uv( start ) {
- var i, offset = md.vertex_index_bytes * 4 + md.material_index_bytes + md.normal_index_bytes * 4,
- stride = offset + md.uv_index_bytes * 4,
- end = start + md.nquad_smooth_uv * stride;
- for( i = start; i < end; i += stride ) {
- add_quad_n( i );
- add_uv4( i + offset );
- }
- return end - start;
- }
- }
- Model.prototype = new THREE.Geometry();
- Model.prototype.constructor = Model;
- callback( new Model( texture_path ) );
- },
- createModel: function ( data, callback, texture_path ) {
- var Model = function ( texture_path ) {
- var scope = this;
- THREE.Geometry.call( this );
- THREE.Loader.prototype.init_materials( scope, data.materials, texture_path );
- init_vertices();
- init_faces();
- this.computeCentroids();
- this.computeFaceNormals();
- this.sortFacesByMaterial();
- function init_vertices() {
- var i, l, x, y, z, r, g, b;
- for( i = 0, l = data.vertices.length; i < l; i += 3 ) {
- x = data.vertices[ i ];
- y = data.vertices[ i + 1 ];
- z = data.vertices[ i + 2 ];
- THREE.Loader.prototype.v( scope, x, y, z );
- }
-
- if ( data.colors ) {
-
- for( i = 0, l = data.colors.length; i < l; i += 3 ) {
-
- r = data.colors[ i ];
- g = data.colors[ i + 1 ];
- b = data.colors[ i + 2 ];
- THREE.Loader.prototype.vc( scope, r, g, b );
-
- }
-
- }
- }
- function init_faces() {
- function add_tri( src, i ) {
- var a, b, c, m;
- a = src[ i ];
- b = src[ i + 1 ];
- c = src[ i + 2 ];
- m = src[ i + 3 ];
- THREE.Loader.prototype.f3( scope, a, b, c, m );
- }
- function add_tri_n( src, i ) {
- var a, b, c, m, na, nb, nc;
- a = src[ i ];
- b = src[ i + 1 ];
- c = src[ i + 2 ];
- m = src[ i + 3 ];
- na = src[ i + 4 ];
- nb = src[ i + 5 ];
- nc = src[ i + 6 ];
- THREE.Loader.prototype.f3n( scope, data.normals, a, b, c, m, na, nb, nc );
- }
- function add_quad( src, i ) {
- var a, b, c, d, m;
- a = src[ i ];
- b = src[ i + 1 ];
- c = src[ i + 2 ];
- d = src[ i + 3 ];
- m = src[ i + 4 ];
- THREE.Loader.prototype.f4( scope, a, b, c, d, m );
- }
- function add_quad_n( src, i ) {
- var a, b, c, d, m, na, nb, nc, nd;
- a = src[ i ];
- b = src[ i + 1 ];
- c = src[ i + 2 ];
- d = src[ i + 3 ];
- m = src[ i + 4 ];
- na = src[ i + 5 ];
- nb = src[ i + 6 ];
- nc = src[ i + 7 ];
- nd = src[ i + 8 ];
- THREE.Loader.prototype.f4n( scope, data.normals, a, b, c, d, m, na, nb, nc, nd );
- }
- function add_uv3( src, i ) {
- var uva, uvb, uvc, u1, u2, u3, v1, v2, v3;
- uva = src[ i ];
- uvb = src[ i + 1 ];
- uvc = src[ i + 2 ];
- u1 = data.uvs[ uva * 2 ];
- v1 = data.uvs[ uva * 2 + 1 ];
- u2 = data.uvs[ uvb * 2 ];
- v2 = data.uvs[ uvb * 2 + 1 ];
- u3 = data.uvs[ uvc * 2 ];
- v3 = data.uvs[ uvc * 2 + 1 ];
- THREE.Loader.prototype.uv3( scope.uvs, u1, v1, u2, v2, u3, v3 );
-
- if( data.uvs2 ) {
-
- u1 = data.uvs2[ uva * 2 ];
- v1 = data.uvs2[ uva * 2 + 1 ];
- u2 = data.uvs2[ uvb * 2 ];
- v2 = data.uvs2[ uvb * 2 + 1 ];
- u3 = data.uvs2[ uvc * 2 ];
- v3 = data.uvs2[ uvc * 2 + 1 ];
- THREE.Loader.prototype.uv3( scope.uvs2, u1, 1-v1, u2, 1-v2, u3, 1-v3 );
-
- }
- }
- function add_uv4( src, i ) {
- var uva, uvb, uvc, uvd, u1, u2, u3, u4, v1, v2, v3, v4;
- uva = src[ i ];
- uvb = src[ i + 1 ];
- uvc = src[ i + 2 ];
- uvd = src[ i + 3 ];
- u1 = data.uvs[ uva * 2 ];
- v1 = data.uvs[ uva * 2 + 1 ];
- u2 = data.uvs[ uvb * 2 ];
- v2 = data.uvs[ uvb * 2 + 1 ];
- u3 = data.uvs[ uvc * 2 ];
- v3 = data.uvs[ uvc * 2 + 1 ];
- u4 = data.uvs[ uvd * 2 ];
- v4 = data.uvs[ uvd * 2 + 1 ];
- THREE.Loader.prototype.uv4( scope.uvs, u1, v1, u2, v2, u3, v3, u4, v4 );
-
- if( data.uvs2 ) {
-
- u1 = data.uvs2[ uva * 2 ];
- v1 = data.uvs2[ uva * 2 + 1 ];
- u2 = data.uvs2[ uvb * 2 ];
- v2 = data.uvs2[ uvb * 2 + 1 ];
- u3 = data.uvs2[ uvc * 2 ];
- v3 = data.uvs2[ uvc * 2 + 1 ];
- u4 = data.uvs2[ uvd * 2 ];
- v4 = data.uvs2[ uvd * 2 + 1 ];
- THREE.Loader.prototype.uv4( scope.uvs2, u1, 1-v1, u2, 1-v2, u3, 1-v3, u4, 1-v4 );
-
- }
- }
- var i, l;
-
- // need to process first faces with uvs
- // as uvs are indexed by face indices
-
- for ( i = 0, l = data.triangles_uv.length; i < l; i+= 7 ) {
- add_tri( data.triangles_uv, i );
- add_uv3( data.triangles_uv, i + 4 );
- }
- for ( i = 0, l = data.triangles_n_uv.length; i < l; i += 10 ) {
- add_tri_n( data.triangles_n_uv, i );
- add_uv3( data.triangles_n_uv, i + 7 );
- }
-
- for ( i = 0, l = data.quads_uv.length; i < l; i += 9 ) {
- add_quad( data.quads_uv, i );
- add_uv4( data.quads_uv, i + 5 );
- }
-
- for ( i = 0, l = data.quads_n_uv.length; i < l; i += 13 ) {
- add_quad_n( data.quads_n_uv, i );
- add_uv4( data.quads_n_uv, i + 9 );
- }
-
- // now can process untextured faces
-
- for ( i = 0, l = data.triangles.length; i < l; i += 4 ) {
- add_tri( data.triangles, i );
- }
- for ( i = 0, l = data.triangles_n.length; i < l; i += 7 ) {
- add_tri_n( data.triangles_n, i );
- }
- for ( i = 0, l = data.quads.length; i < l; i += 5 ) {
- add_quad( data.quads, i );
- }
- for ( i = 0, l = data.quads_n.length; i < l; i += 9 ) {
- add_quad_n( data.quads_n, i );
- }
- }
- }
- Model.prototype = new THREE.Geometry();
- Model.prototype.constructor = Model;
- callback( new Model( texture_path ) );
- },
- v: function( scope, x, y, z ) {
- scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
- },
- vc: function( scope, r, g, b ) {
- var color = new THREE.Color( 0xffffff );
- color.setRGB( r, g, b );
- scope.colors.push( color );
- },
- f3: function( scope, a, b, c, mi ) {
- var material = scope.materials[ mi ];
- scope.faces.push( new THREE.Face3( a, b, c, null, material ) );
- },
- f4: function( scope, a, b, c, d, mi ) {
- var material = scope.materials[ mi ];
- scope.faces.push( new THREE.Face4( a, b, c, d, null, material ) );
- },
- f3n: function( scope, normals, a, b, c, mi, na, nb, nc ) {
- var material = scope.materials[ mi ],
- nax = normals[ na*3 ],
- nay = normals[ na*3 + 1 ],
- naz = normals[ na*3 + 2 ],
- nbx = normals[ nb*3 ],
- nby = normals[ nb*3 + 1 ],
- nbz = normals[ nb*3 + 2 ],
- ncx = normals[ nc*3 ],
- ncy = normals[ nc*3 + 1 ],
- ncz = normals[ nc*3 + 2 ];
- scope.faces.push( new THREE.Face3( a, b, c,
- [new THREE.Vector3( nax, nay, naz ),
- new THREE.Vector3( nbx, nby, nbz ),
- new THREE.Vector3( ncx, ncy, ncz )],
- material ) );
- },
- f4n: function( scope, normals, a, b, c, d, mi, na, nb, nc, nd ) {
- var material = scope.materials[ mi ],
- nax = normals[ na*3 ],
- nay = normals[ na*3 + 1 ],
- naz = normals[ na*3 + 2 ],
- nbx = normals[ nb*3 ],
- nby = normals[ nb*3 + 1 ],
- nbz = normals[ nb*3 + 2 ],
- ncx = normals[ nc*3 ],
- ncy = normals[ nc*3 + 1 ],
- ncz = normals[ nc*3 + 2 ],
- ndx = normals[ nd*3 ],
- ndy = normals[ nd*3 + 1 ],
- ndz = normals[ nd*3 + 2 ];
- scope.faces.push( new THREE.Face4( a, b, c, d,
- [new THREE.Vector3( nax, nay, naz ),
- new THREE.Vector3( nbx, nby, nbz ),
- new THREE.Vector3( ncx, ncy, ncz ),
- new THREE.Vector3( ndx, ndy, ndz )],
- material ) );
- },
- uv3: function( where, u1, v1, u2, v2, u3, v3 ) {
- var uv = [];
- uv.push( new THREE.UV( u1, v1 ) );
- uv.push( new THREE.UV( u2, v2 ) );
- uv.push( new THREE.UV( u3, v3 ) );
- where.push( uv );
- },
- uv4: function( where, u1, v1, u2, v2, u3, v3, u4, v4 ) {
- var uv = [];
- uv.push( new THREE.UV( u1, v1 ) );
- uv.push( new THREE.UV( u2, v2 ) );
- uv.push( new THREE.UV( u3, v3 ) );
- uv.push( new THREE.UV( u4, v4 ) );
- where.push( uv );
- },
- init_materials: function( scope, materials, texture_path ) {
- scope.materials = [];
- for ( var i = 0; i < materials.length; ++i ) {
- scope.materials[i] = [ THREE.Loader.prototype.createMaterial( materials[i], texture_path ) ];
- }
- },
- createMaterial: function ( m, texture_path ) {
- function is_pow2( n ) {
- var l = Math.log(n) / Math.LN2;
- return Math.floor(l) == l;
- }
- function nearest_pow2( n ) {
- var l = Math.log(n) / Math.LN2;
- return Math.pow( 2, Math.round(l) );
- }
- function load_image( where, url ) {
-
- var image = new Image();
-
- image.onload = function () {
- if ( !is_pow2( this.width ) || !is_pow2( this.height ) ) {
- var w = nearest_pow2( this.width ),
- h = nearest_pow2( this.height );
- where.image.width = w;
- where.image.height = h;
- where.image.getContext("2d").drawImage( this, 0, 0, w, h );
- } else {
- where.image = this;
- }
- where.image.loaded = 1;
- };
- image.src = url;
-
- }
-
- var material, mtype, mpars, texture, color;
- // defaults
-
- mtype = "MeshLambertMaterial";
- mpars = { color: 0xeeeeee, opacity: 1.0, map: null, light_map: null, vertex_colors: m.vertex_colors };
-
- // parameters from model file
-
- if ( m.shading ) {
-
- if ( m.shading == "Phong" ) mtype = "MeshPhongMaterial";
-
- }
-
- if ( m.map_diffuse && texture_path ) {
- texture = document.createElement( 'canvas' );
- mpars.map = new THREE.Texture( texture );
- load_image( mpars.map, texture_path + "/" + m.map_diffuse );
- } else if ( m.col_diffuse ) {
- color = ( m.col_diffuse[0] * 255 << 16 ) + ( m.col_diffuse[1] * 255 << 8 ) + m.col_diffuse[2] * 255;
- mpars.color = color;
- mpars.opacity = m.transparency;
- } else if ( m.a_dbg_color ) {
- mpars.color = m.a_dbg_color;
- }
- if ( m.map_lightmap && texture_path ) {
- texture = document.createElement( 'canvas' );
- mpars.light_map = new THREE.Texture( texture );
-
- load_image( mpars.light_map, texture_path + "/" + m.map_lightmap );
- }
-
- material = new THREE[ mtype ]( mpars );
- return material;
- },
-
- extractUrlbase: function( url ) {
-
- var chunks = url.split( "/" );
- chunks.pop();
- return chunks.join( "/" );
-
- }
- };
|