ObjectLoader.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. import {
  2. UVMapping,
  3. CubeReflectionMapping,
  4. CubeRefractionMapping,
  5. EquirectangularReflectionMapping,
  6. EquirectangularRefractionMapping,
  7. SphericalReflectionMapping,
  8. CubeUVReflectionMapping,
  9. CubeUVRefractionMapping,
  10. RepeatWrapping,
  11. ClampToEdgeWrapping,
  12. MirroredRepeatWrapping,
  13. NearestFilter,
  14. NearestMipMapNearestFilter,
  15. NearestMipMapLinearFilter,
  16. LinearFilter,
  17. LinearMipMapNearestFilter,
  18. LinearMipMapLinearFilter
  19. } from '../constants';
  20. import { Color } from '../math/Color';
  21. import { Matrix4 } from '../math/Matrix4';
  22. import { Object3D } from '../core/Object3D';
  23. import { Group } from '../objects/Group';
  24. import { Sprite } from '../objects/Sprite';
  25. import { Points } from '../objects/Points';
  26. import { Line } from '../objects/Line';
  27. import { LineSegments } from '../objects/LineSegments';
  28. import { LOD } from '../objects/LOD';
  29. import { Mesh } from '../objects/Mesh';
  30. import { SkinnedMesh } from '../objects/SkinnedMesh';
  31. import { Fog } from '../scenes/Fog';
  32. import { FogExp2 } from '../scenes/FogExp2';
  33. import { HemisphereLight } from '../lights/HemisphereLight';
  34. import { SpotLight } from '../lights/SpotLight';
  35. import { PointLight } from '../lights/PointLight';
  36. import { DirectionalLight } from '../lights/DirectionalLight';
  37. import { AmbientLight } from '../lights/AmbientLight';
  38. import { OrthographicCamera } from '../cameras/OrthographicCamera';
  39. import { PerspectiveCamera } from '../cameras/PerspectiveCamera';
  40. import { Scene } from '../scenes/Scene';
  41. import { Texture } from '../textures/Texture';
  42. import { ImageLoader } from './ImageLoader';
  43. import { LoadingManager, DefaultLoadingManager } from './LoadingManager';
  44. import { AnimationClip } from '../animation/AnimationClip';
  45. import { MaterialLoader } from './MaterialLoader';
  46. import { BufferGeometryLoader } from './BufferGeometryLoader';
  47. import { JSONLoader } from './JSONLoader';
  48. import { FileLoader } from './FileLoader';
  49. import * as Geometries from '../geometries/Geometries';
  50. /**
  51. * @author mrdoob / http://mrdoob.com/
  52. */
  53. function ObjectLoader( manager ) {
  54. this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
  55. this.texturePath = '';
  56. }
  57. Object.assign( ObjectLoader.prototype, {
  58. load: function ( url, onLoad, onProgress, onError ) {
  59. if ( this.texturePath === '' ) {
  60. this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 );
  61. }
  62. var scope = this;
  63. var loader = new FileLoader( scope.manager );
  64. loader.load( url, function ( text ) {
  65. var json = null;
  66. try {
  67. json = JSON.parse( text );
  68. } catch ( error ) {
  69. console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
  70. return;
  71. }
  72. var metadata = json.metadata;
  73. if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
  74. console.error( 'THREE.ObjectLoader: Can\'t load ' + url + '. Use THREE.JSONLoader instead.' );
  75. return;
  76. }
  77. scope.parse( json, onLoad );
  78. }, onProgress, onError );
  79. },
  80. setTexturePath: function ( value ) {
  81. this.texturePath = value;
  82. },
  83. setCrossOrigin: function ( value ) {
  84. this.crossOrigin = value;
  85. },
  86. parse: function ( json, onLoad ) {
  87. var geometries = this.parseGeometries( json.geometries );
  88. var images = this.parseImages( json.images, function () {
  89. if ( onLoad !== undefined ) onLoad( object );
  90. } );
  91. var textures = this.parseTextures( json.textures, images );
  92. var materials = this.parseMaterials( json.materials, textures );
  93. var object = this.parseObject( json.object, geometries, materials );
  94. if ( json.animations ) {
  95. object.animations = this.parseAnimations( json.animations );
  96. }
  97. if ( json.images === undefined || json.images.length === 0 ) {
  98. if ( onLoad !== undefined ) onLoad( object );
  99. }
  100. return object;
  101. },
  102. parseGeometries: function ( json ) {
  103. var geometries = {};
  104. if ( json !== undefined ) {
  105. var geometryLoader = new JSONLoader();
  106. var bufferGeometryLoader = new BufferGeometryLoader();
  107. for ( var i = 0, l = json.length; i < l; i ++ ) {
  108. var geometry;
  109. var data = json[ i ];
  110. switch ( data.type ) {
  111. case 'PlaneGeometry':
  112. case 'PlaneBufferGeometry':
  113. geometry = new Geometries[ data.type ](
  114. data.width,
  115. data.height,
  116. data.widthSegments,
  117. data.heightSegments
  118. );
  119. break;
  120. case 'BoxGeometry':
  121. case 'BoxBufferGeometry':
  122. case 'CubeGeometry': // backwards compatible
  123. geometry = new Geometries[ data.type ](
  124. data.width,
  125. data.height,
  126. data.depth,
  127. data.widthSegments,
  128. data.heightSegments,
  129. data.depthSegments
  130. );
  131. break;
  132. case 'CircleGeometry':
  133. case 'CircleBufferGeometry':
  134. geometry = new Geometries[ data.type ](
  135. data.radius,
  136. data.segments,
  137. data.thetaStart,
  138. data.thetaLength
  139. );
  140. break;
  141. case 'CylinderGeometry':
  142. case 'CylinderBufferGeometry':
  143. geometry = new Geometries[ data.type ](
  144. data.radiusTop,
  145. data.radiusBottom,
  146. data.height,
  147. data.radialSegments,
  148. data.heightSegments,
  149. data.openEnded,
  150. data.thetaStart,
  151. data.thetaLength
  152. );
  153. break;
  154. case 'ConeGeometry':
  155. case 'ConeBufferGeometry':
  156. geometry = new Geometries[ data.type ](
  157. data.radius,
  158. data.height,
  159. data.radialSegments,
  160. data.heightSegments,
  161. data.openEnded,
  162. data.thetaStart,
  163. data.thetaLength
  164. );
  165. break;
  166. case 'SphereGeometry':
  167. case 'SphereBufferGeometry':
  168. geometry = new Geometries[ data.type ](
  169. data.radius,
  170. data.widthSegments,
  171. data.heightSegments,
  172. data.phiStart,
  173. data.phiLength,
  174. data.thetaStart,
  175. data.thetaLength
  176. );
  177. break;
  178. case 'DodecahedronGeometry':
  179. case 'IcosahedronGeometry':
  180. case 'OctahedronGeometry':
  181. case 'TetrahedronGeometry':
  182. geometry = new Geometries[ data.type ](
  183. data.radius,
  184. data.detail
  185. );
  186. break;
  187. case 'RingGeometry':
  188. case 'RingBufferGeometry':
  189. geometry = new Geometries[ data.type ](
  190. data.innerRadius,
  191. data.outerRadius,
  192. data.thetaSegments,
  193. data.phiSegments,
  194. data.thetaStart,
  195. data.thetaLength
  196. );
  197. break;
  198. case 'TorusGeometry':
  199. case 'TorusBufferGeometry':
  200. geometry = new Geometries[ data.type ](
  201. data.radius,
  202. data.tube,
  203. data.radialSegments,
  204. data.tubularSegments,
  205. data.arc
  206. );
  207. break;
  208. case 'TorusKnotGeometry':
  209. case 'TorusKnotBufferGeometry':
  210. geometry = new Geometries[ data.type ](
  211. data.radius,
  212. data.tube,
  213. data.tubularSegments,
  214. data.radialSegments,
  215. data.p,
  216. data.q
  217. );
  218. break;
  219. case 'LatheGeometry':
  220. case 'LatheBufferGeometry':
  221. geometry = new Geometries[ data.type ](
  222. data.points,
  223. data.segments,
  224. data.phiStart,
  225. data.phiLength
  226. );
  227. break;
  228. case 'BufferGeometry':
  229. geometry = bufferGeometryLoader.parse( data );
  230. break;
  231. case 'Geometry':
  232. geometry = geometryLoader.parse( data.data, this.texturePath ).geometry;
  233. break;
  234. default:
  235. console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' );
  236. continue;
  237. }
  238. geometry.uuid = data.uuid;
  239. if ( data.name !== undefined ) geometry.name = data.name;
  240. geometries[ data.uuid ] = geometry;
  241. }
  242. }
  243. return geometries;
  244. },
  245. parseMaterials: function ( json, textures ) {
  246. var materials = {};
  247. if ( json !== undefined ) {
  248. var loader = new MaterialLoader();
  249. loader.setTextures( textures );
  250. for ( var i = 0, l = json.length; i < l; i ++ ) {
  251. var material = loader.parse( json[ i ] );
  252. materials[ material.uuid ] = material;
  253. }
  254. }
  255. return materials;
  256. },
  257. parseAnimations: function ( json ) {
  258. var animations = [];
  259. for ( var i = 0; i < json.length; i ++ ) {
  260. var clip = AnimationClip.parse( json[ i ] );
  261. animations.push( clip );
  262. }
  263. return animations;
  264. },
  265. parseImages: function ( json, onLoad ) {
  266. var scope = this;
  267. var images = {};
  268. function loadImage( url ) {
  269. scope.manager.itemStart( url );
  270. return loader.load( url, function () {
  271. scope.manager.itemEnd( url );
  272. }, undefined, function () {
  273. scope.manager.itemError( url );
  274. } );
  275. }
  276. if ( json !== undefined && json.length > 0 ) {
  277. var manager = new LoadingManager( onLoad );
  278. var loader = new ImageLoader( manager );
  279. loader.setCrossOrigin( this.crossOrigin );
  280. for ( var i = 0, l = json.length; i < l; i ++ ) {
  281. var image = json[ i ];
  282. var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url;
  283. images[ image.uuid ] = loadImage( path );
  284. }
  285. }
  286. return images;
  287. },
  288. parseTextures: function ( json, images ) {
  289. var TextureMapping = {
  290. UVMapping: UVMapping,
  291. CubeReflectionMapping: CubeReflectionMapping,
  292. CubeRefractionMapping: CubeRefractionMapping,
  293. EquirectangularReflectionMapping: EquirectangularReflectionMapping,
  294. EquirectangularRefractionMapping: EquirectangularRefractionMapping,
  295. SphericalReflectionMapping: SphericalReflectionMapping,
  296. CubeUVReflectionMapping: CubeUVReflectionMapping,
  297. CubeUVRefractionMapping: CubeUVRefractionMapping
  298. };
  299. var TextureWrapping = {
  300. RepeatWrapping: RepeatWrapping,
  301. ClampToEdgeWrapping: ClampToEdgeWrapping,
  302. MirroredRepeatWrapping: MirroredRepeatWrapping
  303. };
  304. var TextureFilter = {
  305. NearestFilter: NearestFilter,
  306. NearestMipMapNearestFilter: NearestMipMapNearestFilter,
  307. NearestMipMapLinearFilter: NearestMipMapLinearFilter,
  308. LinearFilter: LinearFilter,
  309. LinearMipMapNearestFilter: LinearMipMapNearestFilter,
  310. LinearMipMapLinearFilter: LinearMipMapLinearFilter
  311. };
  312. function parseConstant( value, type ) {
  313. if ( typeof( value ) === 'number' ) return value;
  314. console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
  315. return type[ value ];
  316. }
  317. var textures = {};
  318. if ( json !== undefined ) {
  319. for ( var i = 0, l = json.length; i < l; i ++ ) {
  320. var data = json[ i ];
  321. if ( data.image === undefined ) {
  322. console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
  323. }
  324. if ( images[ data.image ] === undefined ) {
  325. console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
  326. }
  327. var texture = new Texture( images[ data.image ] );
  328. texture.needsUpdate = true;
  329. texture.uuid = data.uuid;
  330. if ( data.name !== undefined ) texture.name = data.name;
  331. if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TextureMapping );
  332. if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
  333. if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
  334. if ( data.wrap !== undefined ) {
  335. texture.wrapS = parseConstant( data.wrap[ 0 ], TextureWrapping );
  336. texture.wrapT = parseConstant( data.wrap[ 1 ], TextureWrapping );
  337. }
  338. if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TextureFilter );
  339. if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TextureFilter );
  340. if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
  341. if ( data.flipY !== undefined ) texture.flipY = data.flipY;
  342. textures[ data.uuid ] = texture;
  343. }
  344. }
  345. return textures;
  346. },
  347. parseObject: function () {
  348. var matrix = new Matrix4();
  349. return function parseObject( data, geometries, materials ) {
  350. var object;
  351. function getGeometry( name ) {
  352. if ( geometries[ name ] === undefined ) {
  353. console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
  354. }
  355. return geometries[ name ];
  356. }
  357. function getMaterial( name ) {
  358. if ( name === undefined ) return undefined;
  359. if ( materials[ name ] === undefined ) {
  360. console.warn( 'THREE.ObjectLoader: Undefined material', name );
  361. }
  362. return materials[ name ];
  363. }
  364. switch ( data.type ) {
  365. case 'Scene':
  366. object = new Scene();
  367. if ( data.background !== undefined ) {
  368. if ( Number.isInteger( data.background ) ) {
  369. object.background = new Color( data.background );
  370. }
  371. }
  372. if ( data.fog !== undefined ) {
  373. if ( data.fog.type === 'Fog' ) {
  374. object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
  375. } else if ( data.fog.type === 'FogExp2' ) {
  376. object.fog = new FogExp2( data.fog.color, data.fog.density );
  377. }
  378. }
  379. break;
  380. case 'PerspectiveCamera':
  381. object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
  382. if ( data.focus !== undefined ) object.focus = data.focus;
  383. if ( data.zoom !== undefined ) object.zoom = data.zoom;
  384. if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
  385. if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
  386. if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
  387. break;
  388. case 'OrthographicCamera':
  389. object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
  390. break;
  391. case 'AmbientLight':
  392. object = new AmbientLight( data.color, data.intensity );
  393. break;
  394. case 'DirectionalLight':
  395. object = new DirectionalLight( data.color, data.intensity );
  396. break;
  397. case 'PointLight':
  398. object = new PointLight( data.color, data.intensity, data.distance, data.decay );
  399. break;
  400. case 'SpotLight':
  401. object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
  402. break;
  403. case 'HemisphereLight':
  404. object = new HemisphereLight( data.color, data.groundColor, data.intensity );
  405. break;
  406. case 'Mesh':
  407. var geometry = getGeometry( data.geometry );
  408. var material = getMaterial( data.material );
  409. if ( geometry.bones && geometry.bones.length > 0 ) {
  410. object = new SkinnedMesh( geometry, material );
  411. } else {
  412. object = new Mesh( geometry, material );
  413. }
  414. break;
  415. case 'LOD':
  416. object = new LOD();
  417. break;
  418. case 'Line':
  419. object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );
  420. break;
  421. case 'LineSegments':
  422. object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
  423. break;
  424. case 'PointCloud':
  425. case 'Points':
  426. object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
  427. break;
  428. case 'Sprite':
  429. object = new Sprite( getMaterial( data.material ) );
  430. break;
  431. case 'Group':
  432. object = new Group();
  433. break;
  434. case 'SkinnedMesh':
  435. console.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh type. Instantiates Object3D instead.' );
  436. default:
  437. object = new Object3D();
  438. }
  439. object.uuid = data.uuid;
  440. if ( data.name !== undefined ) object.name = data.name;
  441. if ( data.matrix !== undefined ) {
  442. matrix.fromArray( data.matrix );
  443. matrix.decompose( object.position, object.quaternion, object.scale );
  444. } else {
  445. if ( data.position !== undefined ) object.position.fromArray( data.position );
  446. if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
  447. if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
  448. if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
  449. }
  450. if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
  451. if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
  452. if ( data.shadow ) {
  453. if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
  454. if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
  455. if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
  456. if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
  457. }
  458. if ( data.visible !== undefined ) object.visible = data.visible;
  459. if ( data.userData !== undefined ) object.userData = data.userData;
  460. if ( data.children !== undefined ) {
  461. for ( var child in data.children ) {
  462. object.add( this.parseObject( data.children[ child ], geometries, materials ) );
  463. }
  464. }
  465. if ( data.type === 'LOD' ) {
  466. var levels = data.levels;
  467. for ( var l = 0; l < levels.length; l ++ ) {
  468. var level = levels[ l ];
  469. var child = object.getObjectByProperty( 'uuid', level.object );
  470. if ( child !== undefined ) {
  471. object.addLevel( child, level.distance );
  472. }
  473. }
  474. }
  475. return object;
  476. };
  477. }()
  478. } );
  479. export { ObjectLoader };