SceneUtils.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. var SceneUtils = {
  2. loadScene : function( url, callback_sync, callback_async, callback_progress ) {
  3. var worker = new Worker( url );
  4. worker.postMessage( 0 );
  5. worker.onmessage = function( event ) {
  6. var dg, dm, dd, dl, dc, df, dt,
  7. g, o, m, l, p, c, t, f, tt, pp,
  8. geometry, material, camera, fog,
  9. texture, images,
  10. materials,
  11. data, loader,
  12. counter_models, counter_textures,
  13. total_models, total_textures,
  14. result;
  15. data = event.data;
  16. loader = new THREE.Loader();
  17. counter_models = 0;
  18. counter_textures = 0;
  19. result = {
  20. scene: new THREE.Scene(),
  21. geometries: {},
  22. materials: {},
  23. textures: {},
  24. objects: {},
  25. cameras: {},
  26. lights: {},
  27. fogs: {}
  28. };
  29. function handle_objects() {
  30. for( dd in data.objects ) {
  31. if ( !result.objects[ dd ] ) {
  32. o = data.objects[ dd ];
  33. geometry = result.geometries[ o.geometry ];
  34. if ( geometry ) {
  35. materials = [];
  36. for( i = 0; i < o.materials.length; i++ ) {
  37. materials[ i ] = result.materials[ o.materials[i] ];
  38. }
  39. p = o.position;
  40. r = o.rotation;
  41. s = o.scale;
  42. object = new THREE.Mesh( geometry, materials );
  43. object.position.set( p[0], p[1], p[2] );
  44. object.rotation.set( r[0], r[1], r[2] );
  45. object.scale.set( s[0], s[1], s[2] );
  46. object.visible = o.visible;
  47. result.scene.addObject( object );
  48. result.objects[ dd ] = object;
  49. }
  50. }
  51. }
  52. };
  53. function handle_mesh( geo, id ) {
  54. result.geometries[ id ] = geo;
  55. handle_objects();
  56. };
  57. function create_callback( id ) {
  58. return function( geo ) {
  59. handle_mesh( geo, id );
  60. counter_models -= 1;
  61. async_callback_gate();
  62. }
  63. };
  64. function async_callback_gate() {
  65. var progress = {
  66. total_models: total_models,
  67. total_textures: total_textures,
  68. loaded_models: total_models - counter_models,
  69. loaded_textures: total_textures - counter_textures
  70. };
  71. callback_progress( progress, result );
  72. if( counter_models == 0 && counter_textures == 0 ) {
  73. callback_async( result );
  74. }
  75. };
  76. var callback_texture = function( images ) {
  77. counter_textures -= 1;
  78. async_callback_gate();
  79. };
  80. // first go synchronous elements
  81. // cameras
  82. for( dc in data.cameras ) {
  83. c = data.cameras[ dc ];
  84. if ( c.type == "perspective" ) {
  85. camera = new THREE.Camera( c.fov, c.aspect, c.near, c.far );
  86. } else if ( c.type == "ortho" ) {
  87. camera = new THREE.Camera();
  88. camera.projectionMatrix = THREE.Matrix4.makeOrtho( c.left, c.right, c.top, c.bottom, c.near, c.far );
  89. }
  90. p = c.position;
  91. t = c.target;
  92. camera.position.set( p[0], p[1], p[2] );
  93. camera.target.position.set( t[0], t[1], t[2] );
  94. result.cameras[ dc ] = camera;
  95. }
  96. // lights
  97. for( dl in data.lights ) {
  98. l = data.lights[ dl ];
  99. if ( l.type == "directional" ) {
  100. p = l.direction;
  101. light = new THREE.DirectionalLight();
  102. light.position.set( p[0], p[1], p[2] );
  103. light.position.normalize();
  104. } else if ( l.type == "point" ) {
  105. p = l.position;
  106. light = new THREE.PointLight();
  107. light.position.set( p[0], p[1], p[2] );
  108. }
  109. c = l.color;
  110. i = l.intensity || 1;
  111. light.color.setRGB( c[0] * i, c[1] * i, c[2] * i );
  112. result.scene.addLight( light );
  113. result.lights[ dl ] = light;
  114. }
  115. // fogs
  116. for( df in data.fogs ) {
  117. f = data.fogs[ df ];
  118. if ( f.type == "linear" ) {
  119. fog = new THREE.Fog( 0x000000, f.near, f.far );
  120. } else if ( f.type == "exp2" ) {
  121. fog = new THREE.FogExp2( 0x000000, f.density );
  122. }
  123. c = f.color;
  124. fog.color.setRGB( c[0], c[1], c[2] );
  125. result.fogs[ df ] = fog;
  126. }
  127. // defaults
  128. if ( result.cameras && data.defaults.camera ) {
  129. result.currentCamera = result.cameras[ data.defaults.camera ];
  130. }
  131. if ( result.fogs && data.defaults.fog ) {
  132. result.scene.fog = result.fogs[ data.defaults.fog ];
  133. }
  134. c = data.defaults.bgcolor;
  135. result.bgColor = new THREE.Color();
  136. result.bgColor.setRGB( c[0], c[1], c[2] );
  137. result.bgColorAlpha = data.defaults.bgalpha;
  138. // now come potentially asynchronous elements
  139. // geometries
  140. // count how many models will be loaded asynchronously
  141. for( dg in data.geometries ) {
  142. g = data.geometries[ dg ];
  143. if ( g.type == "bin_mesh" || g.type == "ascii_mesh" ) {
  144. counter_models += 1;
  145. }
  146. }
  147. total_models = counter_models;
  148. for( dg in data.geometries ) {
  149. g = data.geometries[ dg ];
  150. if ( g.type == "cube" ) {
  151. geometry = new Cube( g.width, g.height, g.depth, g.segments_width, g.segments_height, null, g.flipped, g.sides );
  152. result.geometries[ dg ] = geometry;
  153. } else if ( g.type == "plane" ) {
  154. geometry = new Plane( g.width, g.height, g.segments_width, g.segments_height );
  155. result.geometries[ dg ] = geometry;
  156. } else if ( g.type == "sphere" ) {
  157. geometry = new Sphere( g.radius, g.segments_width, g.segments_height );
  158. result.geometries[ dg ] = geometry;
  159. } else if ( g.type == "cylinder" ) {
  160. geometry = new Cylinder( g.numSegs, g.topRad, g.botRad, g.height, g.topOffset, g.botOffset );
  161. result.geometries[ dg ] = geometry;
  162. } else if ( g.type == "torus" ) {
  163. geometry = new Torus( g.radius, g.tube, g.segmentsR, g.segmentsT );
  164. result.geometries[ dg ] = geometry;
  165. } else if ( g.type == "icosahedron" ) {
  166. geometry = new Icosahedron( g.subdivisions );
  167. result.geometries[ dg ] = geometry;
  168. } else if ( g.type == "bin_mesh" ) {
  169. loader.loadBinary( { model: g.url,
  170. callback: create_callback( dg )
  171. } );
  172. } else if ( g.type == "ascii_mesh" ) {
  173. loader.loadAscii( { model: g.url,
  174. callback: create_callback( dg )
  175. } );
  176. }
  177. }
  178. // textures
  179. // count how many textures will be loaded asynchronously
  180. for( dt in data.textures ) {
  181. tt = data.textures[ dt ];
  182. if( tt.url instanceof Array ) {
  183. counter_textures += tt.url.length;
  184. } else {
  185. counter_textures += 1;
  186. }
  187. }
  188. total_textures = counter_textures;
  189. for( dt in data.textures ) {
  190. tt = data.textures[ dt ];
  191. if ( tt.mapping != undefined && THREE[ tt.mapping ] != undefined ) {
  192. tt.mapping = new THREE[ tt.mapping ]();
  193. }
  194. if( tt.url instanceof Array ) {
  195. images = ImageUtils.loadArray( tt.url, callback_texture );
  196. texture = new THREE.Texture( images, tt.mapping );
  197. } else {
  198. texture = ImageUtils.loadTexture( tt.url, tt.mapping, callback_texture );
  199. if ( THREE[ tt.min_filter ] != undefined )
  200. texture.min_filter = THREE[ tt.min_filter ];
  201. if ( THREE[ tt.mag_filter ] != undefined )
  202. texture.mag_filter = THREE[ tt.mag_filter ];
  203. }
  204. result.textures[ dt ] = texture;
  205. }
  206. // materials
  207. for( dm in data.materials ) {
  208. m = data.materials[ dm ];
  209. for( pp in m.parameters ) {
  210. if ( pp == "env_map" || pp == "map" || pp == "light_map" ) {
  211. m.parameters[ pp ] = result.textures[ m.parameters[ pp ] ];
  212. } else if ( pp == "shading" ) {
  213. m.parameters[ pp ] = ( m.parameters[ pp ] == "flat" ) ? THREE.FlatShading : THREE.SmoothShading;
  214. } else if ( pp == "blending" ) {
  215. m.parameters[ pp ] = THREE[ m.parameters[ pp ] ] ? THREE[ m.parameters[ pp ] ] : THREE.NormalBlending;
  216. } else if ( pp == "combine" ) {
  217. m.parameters[ pp ] = ( m.parameters[ pp ] == "MixOperation" ) ? THREE.MixOperation : THREE.MultiplyOperation;
  218. }
  219. }
  220. material = new THREE[ m.type ]( m.parameters );
  221. result.materials[ dm ] = material;
  222. }
  223. // objects ( synchronous init of procedural primitives )
  224. handle_objects();
  225. // synchronous callback
  226. callback_sync( result );
  227. };
  228. },
  229. addMesh: function ( scene, geometry, scale, x, y, z, rx, ry, rz, material ) {
  230. var mesh = new THREE.Mesh( geometry, material );
  231. mesh.scale.x = mesh.scale.y = mesh.scale.z = scale;
  232. mesh.position.x = x;
  233. mesh.position.y = y;
  234. mesh.position.z = z;
  235. mesh.rotation.x = rx;
  236. mesh.rotation.y = ry;
  237. mesh.rotation.z = rz;
  238. scene.addObject( mesh );
  239. return mesh;
  240. },
  241. addPanoramaCubeWebGL: function ( scene, size, textureCube ) {
  242. var shader = ShaderUtils.lib["cube"];
  243. shader.uniforms["tCube"].texture = textureCube;
  244. var material = new THREE.MeshShaderMaterial( { fragment_shader: shader.fragment_shader,
  245. vertex_shader: shader.vertex_shader,
  246. uniforms: shader.uniforms
  247. } ),
  248. mesh = new THREE.Mesh( new Cube( size, size, size, 1, 1, null, true ), material );
  249. scene.addObject( mesh );
  250. return mesh;
  251. },
  252. addPanoramaCube: function( scene, size, images ) {
  253. var materials = [], mesh;
  254. materials.push( new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[0] ) } ) );
  255. materials.push( new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[1] ) } ) );
  256. materials.push( new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[2] ) } ) );
  257. materials.push( new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[3] ) } ) );
  258. materials.push( new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[4] ) } ) );
  259. materials.push( new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[5] ) } ) );
  260. mesh = new THREE.Mesh( new Cube( size, size, size, 1, 1, materials, true ), new THREE.MeshFaceMaterial() );
  261. scene.addObject( mesh );
  262. return mesh;
  263. },
  264. addPanoramaCubePlanes: function ( scene, size, images ) {
  265. var hsize = size/2, plane = new Plane( size, size ), pi2 = Math.PI/2, pi = Math.PI;
  266. SceneUtils.addMesh( scene, plane, 1, 0, 0, -hsize, 0, 0, 0, new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[5] ) } ) );
  267. SceneUtils.addMesh( scene, plane, 1, -hsize, 0, 0, 0, pi2, 0, new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[0] ) } ) );
  268. SceneUtils.addMesh( scene, plane, 1, hsize, 0, 0, 0, -pi2, 0, new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[1] ) } ) );
  269. SceneUtils.addMesh( scene, plane, 1, 0, hsize, 0, pi2, 0, pi, new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[2] ) } ) );
  270. SceneUtils.addMesh( scene, plane, 1, 0, -hsize, 0, -pi2, 0, pi, new THREE.MeshBasicMaterial( { map: new THREE.Texture( images[3] ) } ) );
  271. }
  272. };