UTF8Loader.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /**
  2. * Loader for UTF8 encoded models generated by:
  3. * http://code.google.com/p/webgl-loader/
  4. *
  5. * Limitations:
  6. * - number of vertices < 65536 (this is after optimizations in compressor, input OBJ may have even less)
  7. * - models must have normals and texture coordinates
  8. * - texture coordinates must be only from <0,1>
  9. * - no materials support yet
  10. * - models are scaled and offset (copy numbers from compressor and use them as parameters in UTF8Loader.load() )
  11. *
  12. * @author alteredq / http://alteredqualia.com/
  13. * @author won3d / http://twitter.com/won3d
  14. */
  15. THREE.UTF8Loader = function ( ) {
  16. };
  17. THREE.UTF8Loader.prototype = new THREE.UTF8Loader();
  18. THREE.UTF8Loader.prototype.constructor = THREE.UTF8Loader;
  19. // Load UTF8 compressed models generated by objcompress
  20. // - parameters
  21. // - url (required)
  22. // - callback (required)
  23. // - metaData (optional)
  24. THREE.UTF8Loader.prototype.load = function( url, callback, metaData ) {
  25. if ( url instanceof Object ) {
  26. console.warn( 'DEPRECATED: UTF8Loader( parameters ) is now UTF8Loader( url, callback, metaData ).' );
  27. var parameters = url;
  28. url = parameters.model;
  29. callback = parameters.callback;
  30. metaData = { scale: parameters.scale, offsetX: parameters.offsetX, offsetY: parameters.offsetY, offsetZ: parameters.offsetZ };
  31. }
  32. var xhr = new XMLHttpRequest(),
  33. callbackProgress = null,
  34. scale = metaData.scale !== undefined ? metaData.scale : 1,
  35. offsetX = metaData.offsetX !== undefined ? metaData.offsetX : 0,
  36. offsetY = metaData.offsetY !== undefined ? metaData.offsetY : 0,
  37. offsetZ = metaData.offsetZ !== undefined ? metaData.offsetZ : 0;
  38. var length = 0;
  39. xhr.onreadystatechange = function() {
  40. if ( xhr.readyState == 4 ) {
  41. if ( xhr.status == 200 || xhr.status == 0 ) {
  42. THREE.UTF8Loader.prototype.createModel( xhr.responseText, callback, scale, offsetX, offsetY, offsetZ );
  43. } else {
  44. alert( "Couldn't load [" + url + "] [" + xhr.status + "]" );
  45. }
  46. } else if ( xhr.readyState == 3 ) {
  47. if ( callbackProgress ) {
  48. if ( length == 0 ) {
  49. length = xhr.getResponseHeader( "Content-Length" );
  50. }
  51. callbackProgress( { total: length, loaded: xhr.responseText.length } );
  52. }
  53. } else if ( xhr.readyState == 2 ) {
  54. length = xhr.getResponseHeader( "Content-Length" );
  55. }
  56. }
  57. xhr.open( "GET", url, true );
  58. xhr.send( null );
  59. };
  60. // UTF-8 decoder from webgl-loader
  61. // http://code.google.com/p/webgl-loader/
  62. // Copyright 2011 Google Inc. All Rights Reserved.
  63. //
  64. // Licensed under the Apache License, Version 2.0 (the "License"); you
  65. // may not use this file except in compliance with the License. You
  66. // may obtain a copy of the License at
  67. //
  68. // http://www.apache.org/licenses/LICENSE-2.0
  69. //
  70. // Unless required by applicable law or agreed to in writing, software
  71. // distributed under the License is distributed on an "AS IS" BASIS,
  72. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  73. // implied. See the License for the specific language governing
  74. // permissions and limitations under the License.
  75. THREE.UTF8Loader.prototype.decompressMesh = function ( str ) {
  76. var num_verts = str.charCodeAt( 0 );
  77. if ( num_verts >= 0xE000 ) {
  78. num_verts -= 0x0800;
  79. }
  80. num_verts ++;
  81. var attribs_out = new Float32Array( 8 * num_verts );
  82. var offset = 1;
  83. for ( var i = 0; i < 8; i ++ ) {
  84. var prev_attrib = 0;
  85. for ( var j = 0; j < num_verts; ++ j ) {
  86. var code = str.charCodeAt( j + offset );
  87. prev_attrib += ( code >> 1 ) ^ ( - ( code & 1 ) );
  88. attribs_out[ 8 * j + i ] = prev_attrib;
  89. }
  90. offset += num_verts;
  91. }
  92. var num_indices = str.length - offset;
  93. var indices_out = new Uint16Array( num_indices );
  94. var index_high_water_mark = 0;
  95. for ( var i = 0; i < num_indices; i ++ ) {
  96. var code = str.charCodeAt( i + offset );
  97. indices_out[ i ] = index_high_water_mark - code;
  98. if ( code == 0 ) {
  99. index_high_water_mark ++;
  100. }
  101. }
  102. return [ attribs_out, indices_out ];
  103. };
  104. THREE.UTF8Loader.prototype.createModel = function ( data, callback, scale, offsetX, offsetY, offsetZ ) {
  105. var Model = function ( texture_path ) {
  106. //var s = (new Date).getTime();
  107. var scope = this;
  108. scope.materials = [];
  109. THREE.Geometry.call( this );
  110. var buffers = THREE.UTF8Loader.prototype.decompressMesh( data );
  111. var normals = [],
  112. uvs = [];
  113. init_vertices( buffers[ 0 ], 8, 0 );
  114. init_uvs( buffers[ 0 ], 8, 3 );
  115. init_normals( buffers[ 0 ], 8, 5 );
  116. init_faces( buffers[ 1 ] );
  117. this.computeCentroids();
  118. this.computeFaceNormals();
  119. //this.computeTangents();
  120. //var e = (new Date).getTime();
  121. //console.log( "utf8 data parse time: " + (e-s) + " ms" );
  122. function init_vertices( data, stride, offset ) {
  123. var i, x, y, z,
  124. end = data.length;
  125. for( i = offset; i < end; i += stride ) {
  126. x = data[ i ];
  127. y = data[ i + 1 ];
  128. z = data[ i + 2 ];
  129. // fix scale and offsets
  130. x = ( x / 16383 ) * scale;
  131. y = ( y / 16383 ) * scale;
  132. z = ( z / 16383 ) * scale;
  133. x += offsetX;
  134. y += offsetY;
  135. z += offsetZ;
  136. vertex( scope, x, y, z );
  137. }
  138. };
  139. function init_normals( data, stride, offset ) {
  140. var i, x, y, z,
  141. end = data.length;
  142. for( i = offset; i < end; i += stride ) {
  143. x = data[ i ];
  144. y = data[ i + 1 ];
  145. z = data[ i + 2 ];
  146. // normalize to <-1,1>
  147. x = ( x - 512 ) / 511;
  148. y = ( y - 512 ) / 511;
  149. z = ( z - 512 ) / 511;
  150. normals.push( x, y, z );
  151. }
  152. };
  153. function init_uvs( data, stride, offset ) {
  154. var i, u, v,
  155. end = data.length;
  156. for( i = offset; i < end; i += stride ) {
  157. u = data[ i ];
  158. v = data[ i + 1 ];
  159. // normalize to <0,1>
  160. u /= 1023;
  161. v /= 1023;
  162. uvs.push( u, 1 - v );
  163. }
  164. };
  165. function init_faces( indices ) {
  166. var i,
  167. a, b, c,
  168. u1, v1, u2, v2, u3, v3,
  169. m,
  170. end = indices.length;
  171. m = 0; // all faces defaulting to material 0
  172. for( i = 0; i < end; i += 3 ) {
  173. a = indices[ i ];
  174. b = indices[ i + 1 ];
  175. c = indices[ i + 2 ];
  176. f3n( scope, normals, a, b, c, m, a, b, c );
  177. u1 = uvs[ a * 2 ];
  178. v1 = uvs[ a * 2 + 1 ];
  179. u2 = uvs[ b * 2 ];
  180. v2 = uvs[ b * 2 + 1 ];
  181. u3 = uvs[ c * 2 ];
  182. v3 = uvs[ c * 2 + 1 ];
  183. uv3( scope.faceVertexUvs[ 0 ], u1, v1, u2, v2, u3, v3 );
  184. }
  185. }
  186. };
  187. function vertex ( scope, x, y, z ) {
  188. scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
  189. };
  190. function f3n ( scope, normals, a, b, c, mi, nai, nbi, nci ) {
  191. var nax = normals[ nai * 3 ],
  192. nay = normals[ nai * 3 + 1 ],
  193. naz = normals[ nai * 3 + 2 ],
  194. nbx = normals[ nbi * 3 ],
  195. nby = normals[ nbi * 3 + 1 ],
  196. nbz = normals[ nbi * 3 + 2 ],
  197. ncx = normals[ nci * 3 ],
  198. ncy = normals[ nci * 3 + 1 ],
  199. ncz = normals[ nci * 3 + 2 ];
  200. var na = new THREE.Vector3( nax, nay, naz ),
  201. nb = new THREE.Vector3( nbx, nby, nbz ),
  202. nc = new THREE.Vector3( ncx, ncy, ncz );
  203. scope.faces.push( new THREE.Face3( a, b, c, [ na, nb, nc ], null, mi ) );
  204. };
  205. function uv3 ( where, u1, v1, u2, v2, u3, v3 ) {
  206. var uv = [];
  207. uv.push( new THREE.UV( u1, v1 ) );
  208. uv.push( new THREE.UV( u2, v2 ) );
  209. uv.push( new THREE.UV( u3, v3 ) );
  210. where.push( uv );
  211. };
  212. Model.prototype = new THREE.Geometry();
  213. Model.prototype.constructor = Model;
  214. callback( new Model() );
  215. };