SceneLoader.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. /**
  2. * @author alteredq / http://alteredqualia.com/
  3. */
  4. THREE.SceneLoader = function () {
  5. this.onLoadStart = function () {};
  6. this.onLoadProgress = function() {};
  7. this.onLoadComplete = function () {};
  8. this.callbackSync = function () {};
  9. this.callbackProgress = function () {};
  10. };
  11. THREE.SceneLoader.prototype.constructor = THREE.SceneLoader;
  12. THREE.SceneLoader.prototype.load = function( url, callbackFinished ) {
  13. var context = this;
  14. var xhr = new XMLHttpRequest();
  15. xhr.onreadystatechange = function () {
  16. if ( xhr.readyState == 4 ) {
  17. if ( xhr.status == 200 || xhr.status == 0 ) {
  18. var json = JSON.parse( xhr.responseText );
  19. context.createScene( json, callbackFinished, url );
  20. } else {
  21. console.error( "THREE.SceneLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
  22. }
  23. }
  24. };
  25. xhr.open( "GET", url, true );
  26. if ( xhr.overrideMimeType ) xhr.overrideMimeType( "text/plain; charset=x-user-defined" );
  27. xhr.setRequestHeader( "Content-Type", "text/plain" );
  28. xhr.send( null );
  29. };
  30. THREE.SceneLoader.prototype.createScene = function ( json, callbackFinished, url ) {
  31. var scope = this;
  32. var urlBase = THREE.Loader.prototype.extractUrlBase( url );
  33. var dg, dm, dd, dl, dc, df, dt,
  34. g, o, m, l, d, p, r, q, s, c, t, f, tt, pp, u,
  35. geometry, material, camera, fog,
  36. texture, images,
  37. light,
  38. data, binLoader, jsonLoader,
  39. counter_models, counter_textures,
  40. total_models, total_textures,
  41. result;
  42. data = json;
  43. binLoader = new THREE.BinaryLoader();
  44. jsonLoader = new THREE.JSONLoader();
  45. counter_models = 0;
  46. counter_textures = 0;
  47. result = {
  48. scene: new THREE.Scene(),
  49. geometries: {},
  50. materials: {},
  51. textures: {},
  52. objects: {},
  53. cameras: {},
  54. lights: {},
  55. fogs: {},
  56. empties: {}
  57. };
  58. if ( data.transform ) {
  59. var position = data.transform.position,
  60. rotation = data.transform.rotation,
  61. scale = data.transform.scale;
  62. if ( position )
  63. result.scene.position.set( position[ 0 ], position[ 1 ], position [ 2 ] );
  64. if ( rotation )
  65. result.scene.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation [ 2 ] );
  66. if ( scale )
  67. result.scene.scale.set( scale[ 0 ], scale[ 1 ], scale [ 2 ] );
  68. if ( position || rotation || scale ) {
  69. result.scene.updateMatrix();
  70. result.scene.updateMatrixWorld();
  71. }
  72. }
  73. function get_url( source_url, url_type ) {
  74. if ( url_type == "relativeToHTML" ) {
  75. return source_url;
  76. } else {
  77. return urlBase + "/" + source_url;
  78. }
  79. };
  80. function handle_objects() {
  81. var object;
  82. for( dd in data.objects ) {
  83. if ( !result.objects[ dd ] ) {
  84. o = data.objects[ dd ];
  85. if ( o.geometry !== undefined ) {
  86. geometry = result.geometries[ o.geometry ];
  87. // geometry already loaded
  88. if ( geometry ) {
  89. var hasNormals = false;
  90. // not anymore support for multiple materials
  91. // shouldn't really be array
  92. material = result.materials[ o.materials[ 0 ] ];
  93. hasNormals = material instanceof THREE.ShaderMaterial;
  94. if ( hasNormals ) {
  95. geometry.computeTangents();
  96. }
  97. p = o.position;
  98. r = o.rotation;
  99. q = o.quaternion;
  100. s = o.scale;
  101. m = o.matrix;
  102. // turn off quaternions, for the moment
  103. q = 0;
  104. if ( o.materials.length == 0 ) {
  105. material = new THREE.MeshFaceMaterial();
  106. }
  107. // dirty hack to handle meshes with multiple materials
  108. // just use face materials defined in model
  109. if ( o.materials.length > 1 ) {
  110. material = new THREE.MeshFaceMaterial();
  111. }
  112. object = new THREE.Mesh( geometry, material );
  113. object.name = dd;
  114. if ( m ) {
  115. object.matrixAutoUpdate = false;
  116. object.matrix.set( m[0], m[1], m[2], m[3],
  117. m[4], m[5], m[6], m[7],
  118. m[8], m[9], m[10], m[11],
  119. m[12], m[13], m[14], m[15]);
  120. } else {
  121. object.position.set( p[0], p[1], p[2] );
  122. if ( q ) {
  123. object.quaternion.set( q[0], q[1], q[2], q[3] );
  124. object.useQuaternion = true;
  125. } else {
  126. object.rotation.set( r[0], r[1], r[2] );
  127. }
  128. object.scale.set( s[0], s[1], s[2] );
  129. }
  130. object.visible = o.visible;
  131. object.doubleSided = o.doubleSided;
  132. object.castShadow = o.castShadow;
  133. object.receiveShadow = o.receiveShadow;
  134. result.scene.add( object );
  135. result.objects[ dd ] = object;
  136. }
  137. // pure Object3D
  138. } else {
  139. p = o.position;
  140. r = o.rotation;
  141. q = o.quaternion;
  142. s = o.scale;
  143. // turn off quaternions, for the moment
  144. q = 0;
  145. object = new THREE.Object3D();
  146. object.name = dd;
  147. object.position.set( p[0], p[1], p[2] );
  148. if ( q ) {
  149. object.quaternion.set( q[0], q[1], q[2], q[3] );
  150. object.useQuaternion = true;
  151. } else {
  152. object.rotation.set( r[0], r[1], r[2] );
  153. }
  154. object.scale.set( s[0], s[1], s[2] );
  155. object.visible = ( o.visible !== undefined ) ? o.visible : false;
  156. result.scene.add( object );
  157. result.objects[ dd ] = object;
  158. result.empties[ dd ] = object;
  159. }
  160. }
  161. }
  162. };
  163. function handle_mesh( geo, id ) {
  164. result.geometries[ id ] = geo;
  165. handle_objects();
  166. };
  167. function create_callback( id ) {
  168. return function( geo ) {
  169. handle_mesh( geo, id );
  170. counter_models -= 1;
  171. scope.onLoadComplete();
  172. async_callback_gate();
  173. }
  174. };
  175. function create_callback_embed( id ) {
  176. return function( geo ) {
  177. result.geometries[ id ] = geo;
  178. }
  179. };
  180. function async_callback_gate() {
  181. var progress = {
  182. totalModels : total_models,
  183. totalTextures : total_textures,
  184. loadedModels : total_models - counter_models,
  185. loadedTextures : total_textures - counter_textures
  186. };
  187. scope.callbackProgress( progress, result );
  188. scope.onLoadProgress();
  189. if( counter_models == 0 && counter_textures == 0 ) {
  190. callbackFinished( result );
  191. }
  192. };
  193. var callbackTexture = function( images ) {
  194. counter_textures -= 1;
  195. async_callback_gate();
  196. scope.onLoadComplete();
  197. };
  198. // first go synchronous elements
  199. // cameras
  200. for( dc in data.cameras ) {
  201. c = data.cameras[ dc ];
  202. if ( c.type == "perspective" ) {
  203. camera = new THREE.PerspectiveCamera( c.fov, c.aspect, c.near, c.far );
  204. } else if ( c.type == "ortho" ) {
  205. camera = new THREE.OrthographicCamera( c.left, c.right, c.top, c.bottom, c.near, c.far );
  206. }
  207. p = c.position;
  208. t = c.target;
  209. u = c.up;
  210. camera.position.set( p[0], p[1], p[2] );
  211. camera.target = new THREE.Vector3( t[0], t[1], t[2] );
  212. if ( u ) camera.up.set( u[0], u[1], u[2] );
  213. result.cameras[ dc ] = camera;
  214. }
  215. // lights
  216. var hex, intensity;
  217. for ( dl in data.lights ) {
  218. l = data.lights[ dl ];
  219. hex = ( l.color !== undefined ) ? l.color : 0xffffff;
  220. intensity = ( l.intensity !== undefined ) ? l.intensity : 1;
  221. if ( l.type == "directional" ) {
  222. p = l.direction;
  223. light = new THREE.DirectionalLight( hex, intensity );
  224. light.position.set( p[0], p[1], p[2] );
  225. light.position.normalize();
  226. } else if ( l.type == "point" ) {
  227. p = l.position;
  228. d = l.distance;
  229. light = new THREE.PointLight( hex, intensity, d );
  230. light.position.set( p[0], p[1], p[2] );
  231. } else if ( l.type == "ambient" ) {
  232. light = new THREE.AmbientLight( hex );
  233. }
  234. result.scene.add( light );
  235. result.lights[ dl ] = light;
  236. }
  237. // fogs
  238. for( df in data.fogs ) {
  239. f = data.fogs[ df ];
  240. if ( f.type == "linear" ) {
  241. fog = new THREE.Fog( 0x000000, f.near, f.far );
  242. } else if ( f.type == "exp2" ) {
  243. fog = new THREE.FogExp2( 0x000000, f.density );
  244. }
  245. c = f.color;
  246. fog.color.setRGB( c[0], c[1], c[2] );
  247. result.fogs[ df ] = fog;
  248. }
  249. // defaults
  250. if ( result.cameras && data.defaults.camera ) {
  251. result.currentCamera = result.cameras[ data.defaults.camera ];
  252. }
  253. if ( result.fogs && data.defaults.fog ) {
  254. result.scene.fog = result.fogs[ data.defaults.fog ];
  255. }
  256. c = data.defaults.bgcolor;
  257. result.bgColor = new THREE.Color();
  258. result.bgColor.setRGB( c[0], c[1], c[2] );
  259. result.bgColorAlpha = data.defaults.bgalpha;
  260. // now come potentially asynchronous elements
  261. // geometries
  262. // count how many models will be loaded asynchronously
  263. for( dg in data.geometries ) {
  264. g = data.geometries[ dg ];
  265. if ( g.type == "bin_mesh" || g.type == "ascii_mesh" ) {
  266. counter_models += 1;
  267. scope.onLoadStart();
  268. }
  269. }
  270. total_models = counter_models;
  271. for ( dg in data.geometries ) {
  272. g = data.geometries[ dg ];
  273. if ( g.type == "cube" ) {
  274. geometry = new THREE.CubeGeometry( g.width, g.height, g.depth, g.segmentsWidth, g.segmentsHeight, g.segmentsDepth, null, g.flipped, g.sides );
  275. result.geometries[ dg ] = geometry;
  276. } else if ( g.type == "plane" ) {
  277. geometry = new THREE.PlaneGeometry( g.width, g.height, g.segmentsWidth, g.segmentsHeight );
  278. result.geometries[ dg ] = geometry;
  279. } else if ( g.type == "sphere" ) {
  280. geometry = new THREE.SphereGeometry( g.radius, g.segmentsWidth, g.segmentsHeight );
  281. result.geometries[ dg ] = geometry;
  282. } else if ( g.type == "cylinder" ) {
  283. geometry = new THREE.CylinderGeometry( g.topRad, g.botRad, g.height, g.radSegs, g.heightSegs );
  284. result.geometries[ dg ] = geometry;
  285. } else if ( g.type == "torus" ) {
  286. geometry = new THREE.TorusGeometry( g.radius, g.tube, g.segmentsR, g.segmentsT );
  287. result.geometries[ dg ] = geometry;
  288. } else if ( g.type == "icosahedron" ) {
  289. geometry = new THREE.IcosahedronGeometry( g.radius, g.subdivisions );
  290. result.geometries[ dg ] = geometry;
  291. } else if ( g.type == "bin_mesh" ) {
  292. binLoader.load( get_url( g.url, data.urlBaseType ), create_callback( dg ) );
  293. } else if ( g.type == "ascii_mesh" ) {
  294. jsonLoader.load( get_url( g.url, data.urlBaseType ), create_callback( dg ) );
  295. } else if ( g.type == "embedded_mesh" ) {
  296. var modelJson = data.embeds[ g.id ],
  297. texture_path = "";
  298. // Pass metadata along to jsonLoader so it knows the format version.
  299. modelJson.metadata = data.metadata;
  300. if ( modelJson ) {
  301. jsonLoader.createModel( modelJson, create_callback_embed( dg ), texture_path );
  302. }
  303. }
  304. }
  305. // textures
  306. // count how many textures will be loaded asynchronously
  307. for( dt in data.textures ) {
  308. tt = data.textures[ dt ];
  309. if( tt.url instanceof Array ) {
  310. counter_textures += tt.url.length;
  311. for( var n = 0; n < tt.url.length; n ++ ) {
  312. scope.onLoadStart();
  313. }
  314. } else {
  315. counter_textures += 1;
  316. scope.onLoadStart();
  317. }
  318. }
  319. total_textures = counter_textures;
  320. for( dt in data.textures ) {
  321. tt = data.textures[ dt ];
  322. if ( tt.mapping != undefined && THREE[ tt.mapping ] != undefined ) {
  323. tt.mapping = new THREE[ tt.mapping ]();
  324. }
  325. if( tt.url instanceof Array ) {
  326. var url_array = [];
  327. for( var i = 0; i < tt.url.length; i ++ ) {
  328. url_array[ i ] = get_url( tt.url[ i ], data.urlBaseType );
  329. }
  330. texture = THREE.ImageUtils.loadTextureCube( url_array, tt.mapping, callbackTexture );
  331. } else {
  332. texture = THREE.ImageUtils.loadTexture( get_url( tt.url, data.urlBaseType ), tt.mapping, callbackTexture );
  333. if ( THREE[ tt.minFilter ] != undefined )
  334. texture.minFilter = THREE[ tt.minFilter ];
  335. if ( THREE[ tt.magFilter ] != undefined )
  336. texture.magFilter = THREE[ tt.magFilter ];
  337. if ( tt.repeat ) {
  338. texture.repeat.set( tt.repeat[ 0 ], tt.repeat[ 1 ] );
  339. if ( tt.repeat[ 0 ] != 1 ) texture.wrapS = THREE.RepeatWrapping;
  340. if ( tt.repeat[ 1 ] != 1 ) texture.wrapT = THREE.RepeatWrapping;
  341. }
  342. if ( tt.offset ) {
  343. texture.offset.set( tt.offset[ 0 ], tt.offset[ 1 ] );
  344. }
  345. // handle wrap after repeat so that default repeat can be overriden
  346. if ( tt.wrap ) {
  347. var wrapMap = {
  348. "repeat" : THREE.RepeatWrapping,
  349. "mirror" : THREE.MirroredRepeatWrapping
  350. }
  351. if ( wrapMap[ tt.wrap[ 0 ] ] !== undefined ) texture.wrapS = wrapMap[ tt.wrap[ 0 ] ];
  352. if ( wrapMap[ tt.wrap[ 1 ] ] !== undefined ) texture.wrapT = wrapMap[ tt.wrap[ 1 ] ];
  353. }
  354. }
  355. result.textures[ dt ] = texture;
  356. }
  357. // materials
  358. for ( dm in data.materials ) {
  359. m = data.materials[ dm ];
  360. for ( pp in m.parameters ) {
  361. if ( pp == "envMap" || pp == "map" || pp == "lightMap" ) {
  362. m.parameters[ pp ] = result.textures[ m.parameters[ pp ] ];
  363. } else if ( pp == "shading" ) {
  364. m.parameters[ pp ] = ( m.parameters[ pp ] == "flat" ) ? THREE.FlatShading : THREE.SmoothShading;
  365. } else if ( pp == "blending" ) {
  366. m.parameters[ pp ] = THREE[ m.parameters[ pp ] ] ? THREE[ m.parameters[ pp ] ] : THREE.NormalBlending;
  367. } else if ( pp == "combine" ) {
  368. m.parameters[ pp ] = ( m.parameters[ pp ] == "MixOperation" ) ? THREE.MixOperation : THREE.MultiplyOperation;
  369. } else if ( pp == "vertexColors" ) {
  370. if ( m.parameters[ pp ] == "face" ) {
  371. m.parameters[ pp ] = THREE.FaceColors;
  372. // default to vertex colors if "vertexColors" is anything else face colors or 0 / null / false
  373. } else if ( m.parameters[ pp ] ) {
  374. m.parameters[ pp ] = THREE.VertexColors;
  375. }
  376. }
  377. }
  378. if ( m.parameters.opacity !== undefined && m.parameters.opacity < 1.0 ) {
  379. m.parameters.transparent = true;
  380. }
  381. if ( m.parameters.normalMap ) {
  382. var shader = THREE.ShaderUtils.lib[ "normal" ];
  383. var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
  384. var diffuse = m.parameters.color;
  385. var specular = m.parameters.specular;
  386. var ambient = m.parameters.ambient;
  387. var shininess = m.parameters.shininess;
  388. uniforms[ "tNormal" ].texture = result.textures[ m.parameters.normalMap ];
  389. if ( m.parameters.normalMapFactor ) {
  390. uniforms[ "uNormalScale" ].value = m.parameters.normalMapFactor;
  391. }
  392. if ( m.parameters.map ) {
  393. uniforms[ "tDiffuse" ].texture = m.parameters.map;
  394. uniforms[ "enableDiffuse" ].value = true;
  395. }
  396. if ( m.parameters.lightMap ) {
  397. uniforms[ "tAO" ].texture = m.parameters.lightMap;
  398. uniforms[ "enableAO" ].value = true;
  399. }
  400. if ( m.parameters.specularMap ) {
  401. uniforms[ "tSpecular" ].texture = result.textures[ m.parameters.specularMap ];
  402. uniforms[ "enableSpecular" ].value = true;
  403. }
  404. uniforms[ "uDiffuseColor" ].value.setHex( diffuse );
  405. uniforms[ "uSpecularColor" ].value.setHex( specular );
  406. uniforms[ "uAmbientColor" ].value.setHex( ambient );
  407. uniforms[ "uShininess" ].value = shininess;
  408. if ( m.parameters.opacity ) {
  409. uniforms[ "uOpacity" ].value = m.parameters.opacity;
  410. }
  411. var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: true };
  412. material = new THREE.ShaderMaterial( parameters );
  413. } else {
  414. material = new THREE[ m.type ]( m.parameters );
  415. }
  416. result.materials[ dm ] = material;
  417. }
  418. // objects ( synchronous init of procedural primitives )
  419. handle_objects();
  420. // synchronous callback
  421. scope.callbackSync( result );
  422. // just in case there are no async elements:
  423. async_callback_gate();
  424. };
粤ICP备19079148号