SceneLoader.js 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141
  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. this.geometryHandlerMap = {};
  11. this.hierarchyHandlerMap = {};
  12. this.addGeometryHandler( "ascii", THREE.JSONLoader );
  13. this.addGeometryHandler( "binary", THREE.BinaryLoader );
  14. };
  15. THREE.SceneLoader.prototype.constructor = THREE.SceneLoader;
  16. THREE.SceneLoader.prototype.load = function ( url, callbackFinished ) {
  17. var scope = this;
  18. var xhr = new XMLHttpRequest();
  19. xhr.onreadystatechange = function () {
  20. if ( xhr.readyState === 4 ) {
  21. if ( xhr.status === 200 || xhr.status === 0 ) {
  22. var json = JSON.parse( xhr.responseText );
  23. scope.parse( json, callbackFinished, url );
  24. } else {
  25. console.error( "THREE.SceneLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
  26. }
  27. }
  28. };
  29. xhr.open( "GET", url, true );
  30. xhr.send( null );
  31. };
  32. THREE.SceneLoader.prototype.addGeometryHandler = function ( typeID, loaderClass ) {
  33. this.geometryHandlerMap[ typeID ] = { "loaderClass": loaderClass };
  34. };
  35. THREE.SceneLoader.prototype.addHierarchyHandler = function ( typeID, loaderClass ) {
  36. this.hierarchyHandlerMap[ typeID ] = { "loaderClass": loaderClass };
  37. };
  38. THREE.SceneLoader.prototype.parse = function ( json, callbackFinished, url ) {
  39. var scope = this;
  40. var urlBase = THREE.Loader.prototype.extractUrlBase( url );
  41. var dg, dm, dc, df, dt,
  42. g, m, l, d, p, r, q, s, c, t, f, tt, pp, u,
  43. geometry, material, camera, fog,
  44. texture, images,
  45. light, hex, intensity,
  46. counter_models, counter_textures,
  47. total_models, total_textures,
  48. result;
  49. var target_array = [];
  50. var data = json;
  51. // async geometry loaders
  52. for ( var typeID in this.geometryHandlerMap ) {
  53. var loaderClass = this.geometryHandlerMap[ typeID ][ "loaderClass" ];
  54. this.geometryHandlerMap[ typeID ][ "loaderObject" ] = new loaderClass();
  55. }
  56. // async hierachy loaders
  57. for ( var typeID in this.hierarchyHandlerMap ) {
  58. var loaderClass = this.hierarchyHandlerMap[ typeID ][ "loaderClass" ];
  59. this.hierarchyHandlerMap[ typeID ][ "loaderObject" ] = new loaderClass();
  60. }
  61. counter_models = 0;
  62. counter_textures = 0;
  63. result = {
  64. scene: new THREE.Scene(),
  65. geometries: {},
  66. face_materials: {},
  67. materials: {},
  68. textures: {},
  69. objects: {},
  70. cameras: {},
  71. lights: {},
  72. fogs: {},
  73. empties: {}
  74. };
  75. if ( data.transform ) {
  76. var position = data.transform.position,
  77. rotation = data.transform.rotation,
  78. scale = data.transform.scale;
  79. if ( position )
  80. result.scene.position.set( position[ 0 ], position[ 1 ], position [ 2 ] );
  81. if ( rotation )
  82. result.scene.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation [ 2 ] );
  83. if ( scale )
  84. result.scene.scale.set( scale[ 0 ], scale[ 1 ], scale [ 2 ] );
  85. if ( position || rotation || scale ) {
  86. result.scene.updateMatrix();
  87. result.scene.updateMatrixWorld();
  88. }
  89. }
  90. function get_url( source_url, url_type ) {
  91. if ( url_type == "relativeToHTML" ) {
  92. return source_url;
  93. } else {
  94. return urlBase + "/" + source_url;
  95. }
  96. };
  97. // toplevel loader function, delegates to handle_children
  98. function handle_objects() {
  99. handle_children( result.scene, data.objects );
  100. }
  101. // handle all the children from the loaded json and attach them to given parent
  102. function handle_children( parent, children ) {
  103. for ( var dd in children ) {
  104. // check by id if child has already been handled,
  105. // if not, create new object
  106. if ( result.objects[ dd ] === undefined ) {
  107. var o = children[ dd ];
  108. var object = null;
  109. // meshes
  110. if ( o.type && ( o.type in scope.hierarchyHandlerMap ) && o.loading === undefined ) {
  111. var loaderParameters = {};
  112. for ( var parType in g ) {
  113. if ( parType !== "type" && parType !== "url" ) {
  114. loaderParameters[ parType ] = g[ parType ];
  115. }
  116. }
  117. material = result.materials[ o.material ];
  118. o.loading = true;
  119. var loader = scope.hierarchyHandlerMap[ o.type ][ "loaderObject" ];
  120. // OBJLoader
  121. if ( loader.addEventListener ) {
  122. loader.addEventListener( 'load', create_callback_hierachy( dd, parent, material, o ) );
  123. loader.load( get_url( o.url, data.urlBaseType ) );
  124. } else {
  125. // ColladaLoader
  126. if ( loader.options ) {
  127. loader.load( get_url( o.url, data.urlBaseType ), create_callback_hierachy( dd, parent, material, o ) );
  128. // UTF8Loader
  129. } else {
  130. loader.load( get_url( o.url, data.urlBaseType ), create_callback_hierachy( dd, parent, material, o ), loaderParameters );
  131. }
  132. }
  133. } else if ( o.geometry !== undefined ) {
  134. geometry = result.geometries[ o.geometry ];
  135. // geometry already loaded
  136. if ( geometry ) {
  137. var hasNormals = false;
  138. material = result.materials[ o.material ];
  139. hasNormals = material instanceof THREE.ShaderMaterial;
  140. if ( hasNormals ) {
  141. geometry.computeTangents();
  142. }
  143. p = o.position;
  144. r = o.rotation;
  145. q = o.quaternion;
  146. s = o.scale;
  147. m = o.matrix;
  148. // turn off quaternions, for the moment
  149. q = 0;
  150. // use materials from the model file
  151. // if there is no material specified in the object
  152. if ( ! o.material ) {
  153. material = new THREE.MeshFaceMaterial( result.face_materials[ o.geometry ] );
  154. }
  155. // use materials from the model file
  156. // if there is just empty face material
  157. // (must create new material as each model has its own face material)
  158. if ( ( material instanceof THREE.MeshFaceMaterial ) && material.materials.length === 0 ) {
  159. material = new THREE.MeshFaceMaterial( result.face_materials[ o.geometry ] );
  160. }
  161. if ( o.skin ) {
  162. object = new THREE.SkinnedMesh( geometry, material );
  163. } else if ( o.morph ) {
  164. object = new THREE.MorphAnimMesh( geometry, material );
  165. if ( o.duration !== undefined ) {
  166. object.duration = o.duration;
  167. }
  168. if ( o.time !== undefined ) {
  169. object.time = o.time;
  170. }
  171. if ( o.mirroredLoop !== undefined ) {
  172. object.mirroredLoop = o.mirroredLoop;
  173. }
  174. if ( material.morphNormals ) {
  175. geometry.computeMorphNormals();
  176. }
  177. } else {
  178. object = new THREE.Mesh( geometry, material );
  179. }
  180. object.name = dd;
  181. if ( m ) {
  182. object.matrixAutoUpdate = false;
  183. object.matrix.set(
  184. m[0], m[1], m[2], m[3],
  185. m[4], m[5], m[6], m[7],
  186. m[8], m[9], m[10], m[11],
  187. m[12], m[13], m[14], m[15]
  188. );
  189. } else {
  190. object.position.set( p[0], p[1], p[2] );
  191. if ( q ) {
  192. object.quaternion.set( q[0], q[1], q[2], q[3] );
  193. object.useQuaternion = true;
  194. } else {
  195. object.rotation.set( r[0], r[1], r[2] );
  196. }
  197. object.scale.set( s[0], s[1], s[2] );
  198. }
  199. object.visible = o.visible;
  200. object.castShadow = o.castShadow;
  201. object.receiveShadow = o.receiveShadow;
  202. parent.add( object );
  203. result.objects[ dd ] = object;
  204. }
  205. // lights
  206. } else if ( o.type === "DirectionalLight" || o.type === "PointLight" || o.type === "AmbientLight" ) {
  207. hex = ( o.color !== undefined ) ? o.color : 0xffffff;
  208. intensity = ( o.intensity !== undefined ) ? o.intensity : 1;
  209. if ( o.type === "DirectionalLight" ) {
  210. p = o.direction;
  211. light = new THREE.DirectionalLight( hex, intensity );
  212. light.position.set( p[0], p[1], p[2] );
  213. if ( o.target ) {
  214. target_array.push( { "object": light, "targetName" : o.target } );
  215. // kill existing default target
  216. // otherwise it gets added to scene when parent gets added
  217. light.target = null;
  218. }
  219. } else if ( o.type === "PointLight" ) {
  220. p = o.position;
  221. d = o.distance;
  222. light = new THREE.PointLight( hex, intensity, d );
  223. light.position.set( p[0], p[1], p[2] );
  224. } else if ( o.type === "AmbientLight" ) {
  225. light = new THREE.AmbientLight( hex );
  226. }
  227. parent.add( light );
  228. light.name = dd;
  229. result.lights[ dd ] = light;
  230. result.objects[ dd ] = light;
  231. // cameras
  232. } else if ( o.type === "PerspectiveCamera" || o.type === "OrthographicCamera" ) {
  233. if ( o.type === "PerspectiveCamera" ) {
  234. camera = new THREE.PerspectiveCamera( o.fov, o.aspect, o.near, o.far );
  235. } else if ( o.type === "OrthographicCamera" ) {
  236. camera = new THREE.OrthographicCamera( c.left, c.right, c.top, c.bottom, c.near, c.far );
  237. }
  238. p = o.position;
  239. camera.position.set( p[0], p[1], p[2] );
  240. parent.add( camera );
  241. camera.name = dd;
  242. result.cameras[ dd ] = camera;
  243. result.objects[ dd ] = camera;
  244. // pure Object3D
  245. } else {
  246. p = o.position;
  247. r = o.rotation;
  248. q = o.quaternion;
  249. s = o.scale;
  250. // turn off quaternions, for the moment
  251. q = 0;
  252. object = new THREE.Object3D();
  253. object.name = dd;
  254. object.position.set( p[0], p[1], p[2] );
  255. if ( q ) {
  256. object.quaternion.set( q[0], q[1], q[2], q[3] );
  257. object.useQuaternion = true;
  258. } else {
  259. object.rotation.set( r[0], r[1], r[2] );
  260. }
  261. object.scale.set( s[0], s[1], s[2] );
  262. object.visible = ( o.visible !== undefined ) ? o.visible : false;
  263. parent.add( object );
  264. result.objects[ dd ] = object;
  265. result.empties[ dd ] = object;
  266. }
  267. if ( object ) {
  268. if ( o.properties !== undefined ) {
  269. for ( var key in o.properties ) {
  270. var value = o.properties[ key ];
  271. object.properties[ key ] = value;
  272. }
  273. }
  274. if ( o.children !== undefined ) {
  275. handle_children( object, o.children );
  276. }
  277. }
  278. }
  279. }
  280. };
  281. function handle_mesh( geo, mat, id ) {
  282. result.geometries[ id ] = geo;
  283. result.face_materials[ id ] = mat;
  284. handle_objects();
  285. };
  286. function handle_hierarchy( node, id, parent, material, o ) {
  287. var p = o.position;
  288. var r = o.rotation;
  289. var q = o.quaternion;
  290. var s = o.scale;
  291. node.position.set( p[0], p[1], p[2] );
  292. if ( q ) {
  293. node.quaternion.set( q[0], q[1], q[2], q[3] );
  294. node.useQuaternion = true;
  295. } else {
  296. node.rotation.set( r[0], r[1], r[2] );
  297. }
  298. node.scale.set( s[0], s[1], s[2] );
  299. if ( material ) {
  300. node.traverse( function ( child ) {
  301. child.material = material;
  302. } );
  303. }
  304. parent.add( node );
  305. result.objects[ id ] = node;
  306. handle_objects();
  307. };
  308. function create_callback_geometry( id ) {
  309. return function( geo, mat ) {
  310. handle_mesh( geo, mat, id );
  311. counter_models -= 1;
  312. scope.onLoadComplete();
  313. async_callback_gate();
  314. }
  315. };
  316. function create_callback_hierachy( id, parent, material, obj ) {
  317. return function( event ) {
  318. var result;
  319. // loaders which use EventTarget
  320. if ( event.content ) {
  321. result = event.content;
  322. // ColladaLoader
  323. } else if ( event.dae ) {
  324. result = event.scene;
  325. // UTF8Loader
  326. } else {
  327. result = event;
  328. }
  329. handle_hierarchy( result, id, parent, material, obj );
  330. counter_models -= 1;
  331. scope.onLoadComplete();
  332. async_callback_gate();
  333. }
  334. };
  335. function create_callback_embed( id ) {
  336. return function( geo, mat ) {
  337. result.geometries[ id ] = geo;
  338. result.face_materials[ id ] = mat;
  339. }
  340. };
  341. function async_callback_gate() {
  342. var progress = {
  343. totalModels : total_models,
  344. totalTextures : total_textures,
  345. loadedModels : total_models - counter_models,
  346. loadedTextures : total_textures - counter_textures
  347. };
  348. scope.callbackProgress( progress, result );
  349. scope.onLoadProgress();
  350. if ( counter_models === 0 && counter_textures === 0 ) {
  351. finalize();
  352. callbackFinished( result );
  353. }
  354. };
  355. function finalize() {
  356. // take care of targets which could be asynchronously loaded objects
  357. for ( var i = 0; i < target_array.length; i ++ ) {
  358. var ta = target_array[ i ];
  359. var target = result.objects[ ta.targetName ];
  360. if ( target ) {
  361. ta.object.target = target;
  362. } else {
  363. // if there was error and target of specified name doesn't exist in the scene file
  364. // create instead dummy target
  365. // (target must be added to scene explicitly as parent is already added)
  366. ta.object.target = new THREE.Object3D();
  367. result.scene.add( ta.object.target );
  368. }
  369. ta.object.target.properties.targetInverse = ta.object;
  370. }
  371. };
  372. var callbackTexture = function ( count ) {
  373. counter_textures -= count;
  374. async_callback_gate();
  375. scope.onLoadComplete();
  376. };
  377. // must use this instead of just directly calling callbackTexture
  378. // because of closure in the calling context loop
  379. var generateTextureCallback = function ( count ) {
  380. return function() {
  381. callbackTexture( count );
  382. };
  383. };
  384. // first go synchronous elements
  385. // fogs
  386. for ( df in data.fogs ) {
  387. f = data.fogs[ df ];
  388. if ( f.type === "linear" ) {
  389. fog = new THREE.Fog( 0x000000, f.near, f.far );
  390. } else if ( f.type === "exp2" ) {
  391. fog = new THREE.FogExp2( 0x000000, f.density );
  392. }
  393. c = f.color;
  394. fog.color.setRGB( c[0], c[1], c[2] );
  395. result.fogs[ df ] = fog;
  396. }
  397. // now come potentially asynchronous elements
  398. // geometries
  399. // count how many geometries will be loaded asynchronously
  400. for ( dg in data.geometries ) {
  401. g = data.geometries[ dg ];
  402. if ( g.type in this.geometryHandlerMap ) {
  403. counter_models += 1;
  404. scope.onLoadStart();
  405. }
  406. }
  407. // count how many hierarchies will be loaded asynchronously
  408. for ( var dd in data.objects ) {
  409. var o = data.objects[ dd ];
  410. if ( o.type && ( o.type in this.hierarchyHandlerMap ) ) {
  411. counter_models += 1;
  412. scope.onLoadStart();
  413. }
  414. }
  415. total_models = counter_models;
  416. for ( dg in data.geometries ) {
  417. g = data.geometries[ dg ];
  418. if ( g.type === "cube" ) {
  419. geometry = new THREE.CubeGeometry( g.width, g.height, g.depth, g.widthSegments, g.heightSegments, g.depthSegments );
  420. result.geometries[ dg ] = geometry;
  421. } else if ( g.type === "plane" ) {
  422. geometry = new THREE.PlaneGeometry( g.width, g.height, g.widthSegments, g.heightSegments );
  423. result.geometries[ dg ] = geometry;
  424. } else if ( g.type === "sphere" ) {
  425. geometry = new THREE.SphereGeometry( g.radius, g.widthSegments, g.heightSegments );
  426. result.geometries[ dg ] = geometry;
  427. } else if ( g.type === "cylinder" ) {
  428. geometry = new THREE.CylinderGeometry( g.topRad, g.botRad, g.height, g.radSegs, g.heightSegs );
  429. result.geometries[ dg ] = geometry;
  430. } else if ( g.type === "torus" ) {
  431. geometry = new THREE.TorusGeometry( g.radius, g.tube, g.segmentsR, g.segmentsT );
  432. result.geometries[ dg ] = geometry;
  433. } else if ( g.type === "icosahedron" ) {
  434. geometry = new THREE.IcosahedronGeometry( g.radius, g.subdivisions );
  435. result.geometries[ dg ] = geometry;
  436. } else if ( g.type in this.geometryHandlerMap ) {
  437. var loaderParameters = {};
  438. for ( var parType in g ) {
  439. if ( parType !== "type" && parType !== "url" ) {
  440. loaderParameters[ parType ] = g[ parType ];
  441. }
  442. }
  443. var loader = this.geometryHandlerMap[ g.type ][ "loaderObject" ];
  444. loader.load( get_url( g.url, data.urlBaseType ), create_callback_geometry( dg ), loaderParameters );
  445. } else if ( g.type === "embedded" ) {
  446. var modelJson = data.embeds[ g.id ],
  447. texture_path = "";
  448. // pass metadata along to jsonLoader so it knows the format version
  449. modelJson.metadata = data.metadata;
  450. if ( modelJson ) {
  451. var jsonLoader = this.geometryHandlerMap[ "ascii" ][ "loaderObject" ];
  452. jsonLoader.createModel( modelJson, create_callback_embed( dg ), texture_path );
  453. }
  454. }
  455. }
  456. // textures
  457. // count how many textures will be loaded asynchronously
  458. for ( dt in data.textures ) {
  459. tt = data.textures[ dt ];
  460. if ( tt.url instanceof Array ) {
  461. counter_textures += tt.url.length;
  462. for( var n = 0; n < tt.url.length; n ++ ) {
  463. scope.onLoadStart();
  464. }
  465. } else {
  466. counter_textures += 1;
  467. scope.onLoadStart();
  468. }
  469. }
  470. total_textures = counter_textures;
  471. for ( dt in data.textures ) {
  472. tt = data.textures[ dt ];
  473. if ( tt.mapping !== undefined && THREE[ tt.mapping ] !== undefined ) {
  474. tt.mapping = new THREE[ tt.mapping ]();
  475. }
  476. if ( tt.url instanceof Array ) {
  477. var count = tt.url.length;
  478. var url_array = [];
  479. for( var i = 0; i < count; i ++ ) {
  480. url_array[ i ] = get_url( tt.url[ i ], data.urlBaseType );
  481. }
  482. var isCompressed = url_array[ 0 ].endsWith( ".dds" );
  483. if ( isCompressed ) {
  484. texture = THREE.ImageUtils.loadCompressedTextureCube( url_array, tt.mapping, generateTextureCallback( count ) );
  485. } else {
  486. texture = THREE.ImageUtils.loadTextureCube( url_array, tt.mapping, generateTextureCallback( count ) );
  487. }
  488. } else {
  489. var isCompressed = tt.url.toLowerCase().endsWith( ".dds" );
  490. var fullUrl = get_url( tt.url, data.urlBaseType );
  491. var textureCallback = generateTextureCallback( 1 );
  492. if ( isCompressed ) {
  493. texture = THREE.ImageUtils.loadCompressedTexture( fullUrl, tt.mapping, textureCallback );
  494. } else {
  495. texture = THREE.ImageUtils.loadTexture( fullUrl, tt.mapping, textureCallback );
  496. }
  497. if ( THREE[ tt.minFilter ] !== undefined )
  498. texture.minFilter = THREE[ tt.minFilter ];
  499. if ( THREE[ tt.magFilter ] !== undefined )
  500. texture.magFilter = THREE[ tt.magFilter ];
  501. if ( tt.anisotropy ) texture.anisotropy = tt.anisotropy;
  502. if ( tt.repeat ) {
  503. texture.repeat.set( tt.repeat[ 0 ], tt.repeat[ 1 ] );
  504. if ( tt.repeat[ 0 ] !== 1 ) texture.wrapS = THREE.RepeatWrapping;
  505. if ( tt.repeat[ 1 ] !== 1 ) texture.wrapT = THREE.RepeatWrapping;
  506. }
  507. if ( tt.offset ) {
  508. texture.offset.set( tt.offset[ 0 ], tt.offset[ 1 ] );
  509. }
  510. // handle wrap after repeat so that default repeat can be overriden
  511. if ( tt.wrap ) {
  512. var wrapMap = {
  513. "repeat" : THREE.RepeatWrapping,
  514. "mirror" : THREE.MirroredRepeatWrapping
  515. }
  516. if ( wrapMap[ tt.wrap[ 0 ] ] !== undefined ) texture.wrapS = wrapMap[ tt.wrap[ 0 ] ];
  517. if ( wrapMap[ tt.wrap[ 1 ] ] !== undefined ) texture.wrapT = wrapMap[ tt.wrap[ 1 ] ];
  518. }
  519. }
  520. result.textures[ dt ] = texture;
  521. }
  522. // materials
  523. for ( dm in data.materials ) {
  524. m = data.materials[ dm ];
  525. for ( pp in m.parameters ) {
  526. if ( pp === "envMap" || pp === "map" || pp === "lightMap" || pp === "bumpMap" ) {
  527. m.parameters[ pp ] = result.textures[ m.parameters[ pp ] ];
  528. } else if ( pp === "shading" ) {
  529. m.parameters[ pp ] = ( m.parameters[ pp ] === "flat" ) ? THREE.FlatShading : THREE.SmoothShading;
  530. } else if ( pp === "side" ) {
  531. if ( m.parameters[ pp ] == "double" ) {
  532. m.parameters[ pp ] = THREE.DoubleSide;
  533. } else if ( m.parameters[ pp ] == "back" ) {
  534. m.parameters[ pp ] = THREE.BackSide;
  535. } else {
  536. m.parameters[ pp ] = THREE.FrontSide;
  537. }
  538. } else if ( pp === "blending" ) {
  539. m.parameters[ pp ] = m.parameters[ pp ] in THREE ? THREE[ m.parameters[ pp ] ] : THREE.NormalBlending;
  540. } else if ( pp === "combine" ) {
  541. m.parameters[ pp ] = ( m.parameters[ pp ] == "MixOperation" ) ? THREE.MixOperation : THREE.MultiplyOperation;
  542. } else if ( pp === "vertexColors" ) {
  543. if ( m.parameters[ pp ] == "face" ) {
  544. m.parameters[ pp ] = THREE.FaceColors;
  545. // default to vertex colors if "vertexColors" is anything else face colors or 0 / null / false
  546. } else if ( m.parameters[ pp ] ) {
  547. m.parameters[ pp ] = THREE.VertexColors;
  548. }
  549. } else if ( pp === "wrapRGB" ) {
  550. var v3 = m.parameters[ pp ];
  551. m.parameters[ pp ] = new THREE.Vector3( v3[ 0 ], v3[ 1 ], v3[ 2 ] );
  552. }
  553. }
  554. if ( m.parameters.opacity !== undefined && m.parameters.opacity < 1.0 ) {
  555. m.parameters.transparent = true;
  556. }
  557. if ( m.parameters.normalMap ) {
  558. var shader = THREE.ShaderUtils.lib[ "normal" ];
  559. var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
  560. var diffuse = m.parameters.color;
  561. var specular = m.parameters.specular;
  562. var ambient = m.parameters.ambient;
  563. var shininess = m.parameters.shininess;
  564. uniforms[ "tNormal" ].value = result.textures[ m.parameters.normalMap ];
  565. if ( m.parameters.normalScale ) {
  566. uniforms[ "uNormalScale" ].value.set( m.parameters.normalScale[ 0 ], m.parameters.normalScale[ 1 ] );
  567. }
  568. if ( m.parameters.map ) {
  569. uniforms[ "tDiffuse" ].value = m.parameters.map;
  570. uniforms[ "enableDiffuse" ].value = true;
  571. }
  572. if ( m.parameters.envMap ) {
  573. uniforms[ "tCube" ].value = m.parameters.envMap;
  574. uniforms[ "enableReflection" ].value = true;
  575. uniforms[ "uReflectivity" ].value = m.parameters.reflectivity;
  576. }
  577. if ( m.parameters.lightMap ) {
  578. uniforms[ "tAO" ].value = m.parameters.lightMap;
  579. uniforms[ "enableAO" ].value = true;
  580. }
  581. if ( m.parameters.specularMap ) {
  582. uniforms[ "tSpecular" ].value = result.textures[ m.parameters.specularMap ];
  583. uniforms[ "enableSpecular" ].value = true;
  584. }
  585. if ( m.parameters.displacementMap ) {
  586. uniforms[ "tDisplacement" ].value = result.textures[ m.parameters.displacementMap ];
  587. uniforms[ "enableDisplacement" ].value = true;
  588. uniforms[ "uDisplacementBias" ].value = m.parameters.displacementBias;
  589. uniforms[ "uDisplacementScale" ].value = m.parameters.displacementScale;
  590. }
  591. uniforms[ "uDiffuseColor" ].value.setHex( diffuse );
  592. uniforms[ "uSpecularColor" ].value.setHex( specular );
  593. uniforms[ "uAmbientColor" ].value.setHex( ambient );
  594. uniforms[ "uShininess" ].value = shininess;
  595. if ( m.parameters.opacity ) {
  596. uniforms[ "uOpacity" ].value = m.parameters.opacity;
  597. }
  598. var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: true };
  599. material = new THREE.ShaderMaterial( parameters );
  600. } else {
  601. material = new THREE[ m.type ]( m.parameters );
  602. }
  603. result.materials[ dm ] = material;
  604. }
  605. // second pass through all materials to initialize MeshFaceMaterials
  606. // that could be referring to other materials out of order
  607. for ( dm in data.materials ) {
  608. m = data.materials[ dm ];
  609. if ( m.parameters.materials ) {
  610. var materialArray = [];
  611. for ( var i = 0; i < m.parameters.materials.length; i ++ ) {
  612. var label = m.parameters.materials[ i ];
  613. materialArray.push( result.materials[ label ] );
  614. }
  615. result.materials[ dm ].materials = materialArray;
  616. }
  617. }
  618. // objects ( synchronous init of procedural primitives )
  619. handle_objects();
  620. // defaults
  621. if ( result.cameras && data.defaults.camera ) {
  622. result.currentCamera = result.cameras[ data.defaults.camera ];
  623. }
  624. if ( result.fogs && data.defaults.fog ) {
  625. result.scene.fog = result.fogs[ data.defaults.fog ];
  626. }
  627. c = data.defaults.bgcolor;
  628. result.bgColor = new THREE.Color();
  629. result.bgColor.setRGB( c[0], c[1], c[2] );
  630. result.bgColorAlpha = data.defaults.bgalpha;
  631. // synchronous callback
  632. scope.callbackSync( result );
  633. // just in case there are no async elements
  634. async_callback_gate();
  635. };