initial commit
This commit is contained in:
57
lib/loaders/AnimationLoader.js
Normal file
57
lib/loaders/AnimationLoader.js
Normal file
@ -0,0 +1,57 @@
|
||||
import { AnimationClip } from '../animation/AnimationClip.js';
|
||||
import { FileLoader } from './FileLoader.js';
|
||||
import { DefaultLoadingManager } from './LoadingManager.js';
|
||||
|
||||
/**
|
||||
* @author bhouston / http://clara.io/
|
||||
*/
|
||||
|
||||
function AnimationLoader( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
|
||||
|
||||
}
|
||||
|
||||
Object.assign( AnimationLoader.prototype, {
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var loader = new FileLoader( scope.manager );
|
||||
loader.setPath( scope.path );
|
||||
loader.load( url, function ( text ) {
|
||||
|
||||
onLoad( scope.parse( JSON.parse( text ) ) );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
},
|
||||
|
||||
parse: function ( json, onLoad ) {
|
||||
|
||||
var animations = [];
|
||||
|
||||
for ( var i = 0; i < json.length; i ++ ) {
|
||||
|
||||
var clip = AnimationClip.parse( json[ i ] );
|
||||
|
||||
animations.push( clip );
|
||||
|
||||
}
|
||||
|
||||
onLoad( animations );
|
||||
|
||||
},
|
||||
|
||||
setPath: function ( value ) {
|
||||
|
||||
this.path = value;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
|
||||
export { AnimationLoader };
|
49
lib/loaders/AudioLoader.js
Normal file
49
lib/loaders/AudioLoader.js
Normal file
@ -0,0 +1,49 @@
|
||||
import { AudioContext } from '../audio/AudioContext.js';
|
||||
import { FileLoader } from './FileLoader.js';
|
||||
import { DefaultLoadingManager } from './LoadingManager.js';
|
||||
|
||||
/**
|
||||
* @author Reece Aaron Lecrivain / http://reecenotes.com/
|
||||
*/
|
||||
|
||||
function AudioLoader( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
|
||||
|
||||
}
|
||||
|
||||
Object.assign( AudioLoader.prototype, {
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var loader = new FileLoader( this.manager );
|
||||
loader.setResponseType( 'arraybuffer' );
|
||||
loader.setPath( this.path );
|
||||
loader.load( url, function ( buffer ) {
|
||||
|
||||
// Create a copy of the buffer. The `decodeAudioData` method
|
||||
// detaches the buffer when complete, preventing reuse.
|
||||
var bufferCopy = buffer.slice( 0 );
|
||||
|
||||
var context = AudioContext.getContext();
|
||||
context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
|
||||
|
||||
onLoad( audioBuffer );
|
||||
|
||||
} );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
},
|
||||
|
||||
setPath: function ( value ) {
|
||||
|
||||
this.path = value;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
|
||||
export { AudioLoader };
|
114
lib/loaders/BufferGeometryLoader.js
Normal file
114
lib/loaders/BufferGeometryLoader.js
Normal file
@ -0,0 +1,114 @@
|
||||
import { Sphere } from '../math/Sphere.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
import { BufferAttribute } from '../core/BufferAttribute.js';
|
||||
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||||
import { FileLoader } from './FileLoader.js';
|
||||
import { DefaultLoadingManager } from './LoadingManager.js';
|
||||
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
function BufferGeometryLoader( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
|
||||
|
||||
}
|
||||
|
||||
Object.assign( BufferGeometryLoader.prototype, {
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var loader = new FileLoader( scope.manager );
|
||||
loader.setPath( scope.path );
|
||||
loader.load( url, function ( text ) {
|
||||
|
||||
onLoad( scope.parse( JSON.parse( text ) ) );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
},
|
||||
|
||||
parse: function ( json ) {
|
||||
|
||||
var geometry = new BufferGeometry();
|
||||
|
||||
var index = json.data.index;
|
||||
|
||||
if ( index !== undefined ) {
|
||||
|
||||
var typedArray = new TYPED_ARRAYS[ index.type ]( index.array );
|
||||
geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
|
||||
|
||||
}
|
||||
|
||||
var attributes = json.data.attributes;
|
||||
|
||||
for ( var key in attributes ) {
|
||||
|
||||
var attribute = attributes[ key ];
|
||||
var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
|
||||
|
||||
geometry.addAttribute( key, new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ) );
|
||||
|
||||
}
|
||||
|
||||
var groups = json.data.groups || json.data.drawcalls || json.data.offsets;
|
||||
|
||||
if ( groups !== undefined ) {
|
||||
|
||||
for ( var i = 0, n = groups.length; i !== n; ++ i ) {
|
||||
|
||||
var group = groups[ i ];
|
||||
|
||||
geometry.addGroup( group.start, group.count, group.materialIndex );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var boundingSphere = json.data.boundingSphere;
|
||||
|
||||
if ( boundingSphere !== undefined ) {
|
||||
|
||||
var center = new Vector3();
|
||||
|
||||
if ( boundingSphere.center !== undefined ) {
|
||||
|
||||
center.fromArray( boundingSphere.center );
|
||||
|
||||
}
|
||||
|
||||
geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
|
||||
|
||||
}
|
||||
|
||||
return geometry;
|
||||
|
||||
},
|
||||
|
||||
setPath: function ( value ) {
|
||||
|
||||
this.path = value;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
var TYPED_ARRAYS = {
|
||||
Int8Array: Int8Array,
|
||||
Uint8Array: Uint8Array,
|
||||
// Workaround for IE11 pre KB2929437. See #11440
|
||||
Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array,
|
||||
Int16Array: Int16Array,
|
||||
Uint16Array: Uint16Array,
|
||||
Int32Array: Int32Array,
|
||||
Uint32Array: Uint32Array,
|
||||
Float32Array: Float32Array,
|
||||
Float64Array: Float64Array
|
||||
};
|
||||
|
||||
export { BufferGeometryLoader };
|
46
lib/loaders/Cache.js
Normal file
46
lib/loaders/Cache.js
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
var Cache = {
|
||||
|
||||
enabled: false,
|
||||
|
||||
files: {},
|
||||
|
||||
add: function ( key, file ) {
|
||||
|
||||
if ( this.enabled === false ) return;
|
||||
|
||||
// console.log( 'THREE.Cache', 'Adding key:', key );
|
||||
|
||||
this.files[ key ] = file;
|
||||
|
||||
},
|
||||
|
||||
get: function ( key ) {
|
||||
|
||||
if ( this.enabled === false ) return;
|
||||
|
||||
// console.log( 'THREE.Cache', 'Checking key:', key );
|
||||
|
||||
return this.files[ key ];
|
||||
|
||||
},
|
||||
|
||||
remove: function ( key ) {
|
||||
|
||||
delete this.files[ key ];
|
||||
|
||||
},
|
||||
|
||||
clear: function () {
|
||||
|
||||
this.files = {};
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
export { Cache };
|
141
lib/loaders/CompressedTextureLoader.js
Normal file
141
lib/loaders/CompressedTextureLoader.js
Normal file
@ -0,0 +1,141 @@
|
||||
import { LinearFilter } from '../constants.js';
|
||||
import { FileLoader } from './FileLoader.js';
|
||||
import { CompressedTexture } from '../textures/CompressedTexture.js';
|
||||
import { DefaultLoadingManager } from './LoadingManager.js';
|
||||
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*
|
||||
* Abstract Base class to block based textures loader (dds, pvr, ...)
|
||||
*/
|
||||
|
||||
function CompressedTextureLoader( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
|
||||
|
||||
// override in sub classes
|
||||
this._parser = null;
|
||||
|
||||
}
|
||||
|
||||
Object.assign( CompressedTextureLoader.prototype, {
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var images = [];
|
||||
|
||||
var texture = new CompressedTexture();
|
||||
texture.image = images;
|
||||
|
||||
var loader = new FileLoader( this.manager );
|
||||
loader.setPath( this.path );
|
||||
loader.setResponseType( 'arraybuffer' );
|
||||
|
||||
function loadTexture( i ) {
|
||||
|
||||
loader.load( url[ i ], function ( buffer ) {
|
||||
|
||||
var texDatas = scope._parser( buffer, true );
|
||||
|
||||
images[ i ] = {
|
||||
width: texDatas.width,
|
||||
height: texDatas.height,
|
||||
format: texDatas.format,
|
||||
mipmaps: texDatas.mipmaps
|
||||
};
|
||||
|
||||
loaded += 1;
|
||||
|
||||
if ( loaded === 6 ) {
|
||||
|
||||
if ( texDatas.mipmapCount === 1 )
|
||||
texture.minFilter = LinearFilter;
|
||||
|
||||
texture.format = texDatas.format;
|
||||
texture.needsUpdate = true;
|
||||
|
||||
if ( onLoad ) onLoad( texture );
|
||||
|
||||
}
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
}
|
||||
|
||||
if ( Array.isArray( url ) ) {
|
||||
|
||||
var loaded = 0;
|
||||
|
||||
for ( var i = 0, il = url.length; i < il; ++ i ) {
|
||||
|
||||
loadTexture( i );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// compressed cubemap texture stored in a single DDS file
|
||||
|
||||
loader.load( url, function ( buffer ) {
|
||||
|
||||
var texDatas = scope._parser( buffer, true );
|
||||
|
||||
if ( texDatas.isCubemap ) {
|
||||
|
||||
var faces = texDatas.mipmaps.length / texDatas.mipmapCount;
|
||||
|
||||
for ( var f = 0; f < faces; f ++ ) {
|
||||
|
||||
images[ f ] = { mipmaps: [] };
|
||||
|
||||
for ( var i = 0; i < texDatas.mipmapCount; i ++ ) {
|
||||
|
||||
images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
|
||||
images[ f ].format = texDatas.format;
|
||||
images[ f ].width = texDatas.width;
|
||||
images[ f ].height = texDatas.height;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
texture.image.width = texDatas.width;
|
||||
texture.image.height = texDatas.height;
|
||||
texture.mipmaps = texDatas.mipmaps;
|
||||
|
||||
}
|
||||
|
||||
if ( texDatas.mipmapCount === 1 ) {
|
||||
|
||||
texture.minFilter = LinearFilter;
|
||||
|
||||
}
|
||||
|
||||
texture.format = texDatas.format;
|
||||
texture.needsUpdate = true;
|
||||
|
||||
if ( onLoad ) onLoad( texture );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
}
|
||||
|
||||
return texture;
|
||||
|
||||
},
|
||||
|
||||
setPath: function ( value ) {
|
||||
|
||||
this.path = value;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
|
||||
export { CompressedTextureLoader };
|
77
lib/loaders/CubeTextureLoader.js
Normal file
77
lib/loaders/CubeTextureLoader.js
Normal file
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
import { ImageLoader } from './ImageLoader.js';
|
||||
import { CubeTexture } from '../textures/CubeTexture.js';
|
||||
import { DefaultLoadingManager } from './LoadingManager.js';
|
||||
|
||||
|
||||
function CubeTextureLoader( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
|
||||
|
||||
}
|
||||
|
||||
Object.assign( CubeTextureLoader.prototype, {
|
||||
|
||||
crossOrigin: 'anonymous',
|
||||
|
||||
load: function ( urls, onLoad, onProgress, onError ) {
|
||||
|
||||
var texture = new CubeTexture();
|
||||
|
||||
var loader = new ImageLoader( this.manager );
|
||||
loader.setCrossOrigin( this.crossOrigin );
|
||||
loader.setPath( this.path );
|
||||
|
||||
var loaded = 0;
|
||||
|
||||
function loadTexture( i ) {
|
||||
|
||||
loader.load( urls[ i ], function ( image ) {
|
||||
|
||||
texture.images[ i ] = image;
|
||||
|
||||
loaded ++;
|
||||
|
||||
if ( loaded === 6 ) {
|
||||
|
||||
texture.needsUpdate = true;
|
||||
|
||||
if ( onLoad ) onLoad( texture );
|
||||
|
||||
}
|
||||
|
||||
}, undefined, onError );
|
||||
|
||||
}
|
||||
|
||||
for ( var i = 0; i < urls.length; ++ i ) {
|
||||
|
||||
loadTexture( i );
|
||||
|
||||
}
|
||||
|
||||
return texture;
|
||||
|
||||
},
|
||||
|
||||
setCrossOrigin: function ( value ) {
|
||||
|
||||
this.crossOrigin = value;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setPath: function ( value ) {
|
||||
|
||||
this.path = value;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
|
||||
export { CubeTextureLoader };
|
102
lib/loaders/DataTextureLoader.js
Normal file
102
lib/loaders/DataTextureLoader.js
Normal file
@ -0,0 +1,102 @@
|
||||
import { LinearFilter, LinearMipMapLinearFilter, ClampToEdgeWrapping } from '../constants.js';
|
||||
import { FileLoader } from './FileLoader.js';
|
||||
import { DataTexture } from '../textures/DataTexture.js';
|
||||
import { DefaultLoadingManager } from './LoadingManager.js';
|
||||
|
||||
/**
|
||||
* @author Nikos M. / https://github.com/foo123/
|
||||
*
|
||||
* Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
|
||||
*/
|
||||
|
||||
function DataTextureLoader( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
|
||||
|
||||
// override in sub classes
|
||||
this._parser = null;
|
||||
|
||||
}
|
||||
|
||||
Object.assign( DataTextureLoader.prototype, {
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var texture = new DataTexture();
|
||||
|
||||
var loader = new FileLoader( this.manager );
|
||||
loader.setResponseType( 'arraybuffer' );
|
||||
loader.setPath( this.path );
|
||||
loader.load( url, function ( buffer ) {
|
||||
|
||||
var texData = scope._parser( buffer );
|
||||
|
||||
if ( ! texData ) return;
|
||||
|
||||
if ( undefined !== texData.image ) {
|
||||
|
||||
texture.image = texData.image;
|
||||
|
||||
} else if ( undefined !== texData.data ) {
|
||||
|
||||
texture.image.width = texData.width;
|
||||
texture.image.height = texData.height;
|
||||
texture.image.data = texData.data;
|
||||
|
||||
}
|
||||
|
||||
texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : ClampToEdgeWrapping;
|
||||
texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : ClampToEdgeWrapping;
|
||||
|
||||
texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : LinearFilter;
|
||||
texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : LinearMipMapLinearFilter;
|
||||
|
||||
texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1;
|
||||
|
||||
if ( undefined !== texData.format ) {
|
||||
|
||||
texture.format = texData.format;
|
||||
|
||||
}
|
||||
if ( undefined !== texData.type ) {
|
||||
|
||||
texture.type = texData.type;
|
||||
|
||||
}
|
||||
|
||||
if ( undefined !== texData.mipmaps ) {
|
||||
|
||||
texture.mipmaps = texData.mipmaps;
|
||||
|
||||
}
|
||||
|
||||
if ( 1 === texData.mipmapCount ) {
|
||||
|
||||
texture.minFilter = LinearFilter;
|
||||
|
||||
}
|
||||
|
||||
texture.needsUpdate = true;
|
||||
|
||||
if ( onLoad ) onLoad( texture, texData );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
|
||||
return texture;
|
||||
|
||||
},
|
||||
|
||||
setPath: function ( value ) {
|
||||
|
||||
this.path = value;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
|
||||
export { DataTextureLoader };
|
319
lib/loaders/FileLoader.js
Normal file
319
lib/loaders/FileLoader.js
Normal file
@ -0,0 +1,319 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
import { Cache } from './Cache.js';
|
||||
import { DefaultLoadingManager } from './LoadingManager.js';
|
||||
|
||||
var loading = {};
|
||||
|
||||
function FileLoader( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
|
||||
|
||||
}
|
||||
|
||||
Object.assign( FileLoader.prototype, {
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
if ( url === undefined ) url = '';
|
||||
|
||||
if ( this.path !== undefined ) url = this.path + url;
|
||||
|
||||
url = this.manager.resolveURL( url );
|
||||
|
||||
var scope = this;
|
||||
|
||||
var cached = Cache.get( url );
|
||||
|
||||
if ( cached !== undefined ) {
|
||||
|
||||
scope.manager.itemStart( url );
|
||||
|
||||
setTimeout( function () {
|
||||
|
||||
if ( onLoad ) onLoad( cached );
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
|
||||
}, 0 );
|
||||
|
||||
return cached;
|
||||
|
||||
}
|
||||
|
||||
// Check if request is duplicate
|
||||
|
||||
if ( loading[ url ] !== undefined ) {
|
||||
|
||||
loading[ url ].push( {
|
||||
|
||||
onLoad: onLoad,
|
||||
onProgress: onProgress,
|
||||
onError: onError
|
||||
|
||||
} );
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Check for data: URI
|
||||
var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
|
||||
var dataUriRegexResult = url.match( dataUriRegex );
|
||||
|
||||
// Safari can not handle Data URIs through XMLHttpRequest so process manually
|
||||
if ( dataUriRegexResult ) {
|
||||
|
||||
var mimeType = dataUriRegexResult[ 1 ];
|
||||
var isBase64 = !! dataUriRegexResult[ 2 ];
|
||||
var data = dataUriRegexResult[ 3 ];
|
||||
|
||||
data = decodeURIComponent( data );
|
||||
|
||||
if ( isBase64 ) data = atob( data );
|
||||
|
||||
try {
|
||||
|
||||
var response;
|
||||
var responseType = ( this.responseType || '' ).toLowerCase();
|
||||
|
||||
switch ( responseType ) {
|
||||
|
||||
case 'arraybuffer':
|
||||
case 'blob':
|
||||
|
||||
var view = new Uint8Array( data.length );
|
||||
|
||||
for ( var i = 0; i < data.length; i ++ ) {
|
||||
|
||||
view[ i ] = data.charCodeAt( i );
|
||||
|
||||
}
|
||||
|
||||
if ( responseType === 'blob' ) {
|
||||
|
||||
response = new Blob( [ view.buffer ], { type: mimeType } );
|
||||
|
||||
} else {
|
||||
|
||||
response = view.buffer;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'document':
|
||||
|
||||
var parser = new DOMParser();
|
||||
response = parser.parseFromString( data, mimeType );
|
||||
|
||||
break;
|
||||
|
||||
case 'json':
|
||||
|
||||
response = JSON.parse( data );
|
||||
|
||||
break;
|
||||
|
||||
default: // 'text' or other
|
||||
|
||||
response = data;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Wait for next browser tick like standard XMLHttpRequest event dispatching does
|
||||
setTimeout( function () {
|
||||
|
||||
if ( onLoad ) onLoad( response );
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
|
||||
}, 0 );
|
||||
|
||||
} catch ( error ) {
|
||||
|
||||
// Wait for next browser tick like standard XMLHttpRequest event dispatching does
|
||||
setTimeout( function () {
|
||||
|
||||
if ( onError ) onError( error );
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
scope.manager.itemError( url );
|
||||
|
||||
}, 0 );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Initialise array for duplicate requests
|
||||
|
||||
loading[ url ] = [];
|
||||
|
||||
loading[ url ].push( {
|
||||
|
||||
onLoad: onLoad,
|
||||
onProgress: onProgress,
|
||||
onError: onError
|
||||
|
||||
} );
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
|
||||
request.open( 'GET', url, true );
|
||||
|
||||
request.addEventListener( 'load', function ( event ) {
|
||||
|
||||
var response = this.response;
|
||||
|
||||
Cache.add( url, response );
|
||||
|
||||
var callbacks = loading[ url ];
|
||||
|
||||
delete loading[ url ];
|
||||
|
||||
if ( this.status === 200 || this.status === 0 ) {
|
||||
|
||||
// Some browsers return HTTP Status 0 when using non-http protocol
|
||||
// e.g. 'file://' or 'data://'. Handle as success.
|
||||
|
||||
if ( this.status === 0 ) console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
|
||||
|
||||
for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
|
||||
|
||||
var callback = callbacks[ i ];
|
||||
if ( callback.onLoad ) callback.onLoad( response );
|
||||
|
||||
}
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
|
||||
} else {
|
||||
|
||||
for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
|
||||
|
||||
var callback = callbacks[ i ];
|
||||
if ( callback.onError ) callback.onError( event );
|
||||
|
||||
}
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
scope.manager.itemError( url );
|
||||
|
||||
}
|
||||
|
||||
}, false );
|
||||
|
||||
request.addEventListener( 'progress', function ( event ) {
|
||||
|
||||
var callbacks = loading[ url ];
|
||||
|
||||
for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
|
||||
|
||||
var callback = callbacks[ i ];
|
||||
if ( callback.onProgress ) callback.onProgress( event );
|
||||
|
||||
}
|
||||
|
||||
}, false );
|
||||
|
||||
request.addEventListener( 'error', function ( event ) {
|
||||
|
||||
var callbacks = loading[ url ];
|
||||
|
||||
delete loading[ url ];
|
||||
|
||||
for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
|
||||
|
||||
var callback = callbacks[ i ];
|
||||
if ( callback.onError ) callback.onError( event );
|
||||
|
||||
}
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
scope.manager.itemError( url );
|
||||
|
||||
}, false );
|
||||
|
||||
request.addEventListener( 'abort', function ( event ) {
|
||||
|
||||
var callbacks = loading[ url ];
|
||||
|
||||
delete loading[ url ];
|
||||
|
||||
for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
|
||||
|
||||
var callback = callbacks[ i ];
|
||||
if ( callback.onError ) callback.onError( event );
|
||||
|
||||
}
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
scope.manager.itemError( url );
|
||||
|
||||
}, false );
|
||||
|
||||
if ( this.responseType !== undefined ) request.responseType = this.responseType;
|
||||
if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
|
||||
|
||||
if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' );
|
||||
|
||||
for ( var header in this.requestHeader ) {
|
||||
|
||||
request.setRequestHeader( header, this.requestHeader[ header ] );
|
||||
|
||||
}
|
||||
|
||||
request.send( null );
|
||||
|
||||
}
|
||||
|
||||
scope.manager.itemStart( url );
|
||||
|
||||
return request;
|
||||
|
||||
},
|
||||
|
||||
setPath: function ( value ) {
|
||||
|
||||
this.path = value;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setResponseType: function ( value ) {
|
||||
|
||||
this.responseType = value;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setWithCredentials: function ( value ) {
|
||||
|
||||
this.withCredentials = value;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setMimeType: function ( value ) {
|
||||
|
||||
this.mimeType = value;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setRequestHeader: function ( value ) {
|
||||
|
||||
this.requestHeader = value;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
|
||||
export { FileLoader };
|
62
lib/loaders/FontLoader.js
Normal file
62
lib/loaders/FontLoader.js
Normal file
@ -0,0 +1,62 @@
|
||||
import { Font } from '../extras/core/Font.js';
|
||||
import { FileLoader } from './FileLoader.js';
|
||||
import { DefaultLoadingManager } from './LoadingManager.js';
|
||||
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
function FontLoader( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
|
||||
|
||||
}
|
||||
|
||||
Object.assign( FontLoader.prototype, {
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var loader = new FileLoader( this.manager );
|
||||
loader.setPath( this.path );
|
||||
loader.load( url, function ( text ) {
|
||||
|
||||
var json;
|
||||
|
||||
try {
|
||||
|
||||
json = JSON.parse( text );
|
||||
|
||||
} catch ( e ) {
|
||||
|
||||
console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );
|
||||
json = JSON.parse( text.substring( 65, text.length - 2 ) );
|
||||
|
||||
}
|
||||
|
||||
var font = scope.parse( json );
|
||||
|
||||
if ( onLoad ) onLoad( font );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
},
|
||||
|
||||
parse: function ( json ) {
|
||||
|
||||
return new Font( json );
|
||||
|
||||
},
|
||||
|
||||
setPath: function ( value ) {
|
||||
|
||||
this.path = value;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
|
||||
export { FontLoader };
|
110
lib/loaders/ImageBitmapLoader.js
Normal file
110
lib/loaders/ImageBitmapLoader.js
Normal file
@ -0,0 +1,110 @@
|
||||
/**
|
||||
* @author thespite / http://clicktorelease.com/
|
||||
*/
|
||||
|
||||
import { Cache } from './Cache.js';
|
||||
import { DefaultLoadingManager } from './LoadingManager.js';
|
||||
|
||||
|
||||
function ImageBitmapLoader( manager ) {
|
||||
|
||||
if ( typeof createImageBitmap === 'undefined' ) {
|
||||
|
||||
console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );
|
||||
|
||||
}
|
||||
|
||||
if ( typeof fetch === 'undefined' ) {
|
||||
|
||||
console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );
|
||||
|
||||
}
|
||||
|
||||
this.manager = manager !== undefined ? manager : DefaultLoadingManager;
|
||||
this.options = undefined;
|
||||
|
||||
}
|
||||
|
||||
ImageBitmapLoader.prototype = {
|
||||
|
||||
constructor: ImageBitmapLoader,
|
||||
|
||||
setOptions: function setOptions( options ) {
|
||||
|
||||
this.options = options;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
if ( url === undefined ) url = '';
|
||||
|
||||
if ( this.path !== undefined ) url = this.path + url;
|
||||
|
||||
url = this.manager.resolveURL( url );
|
||||
|
||||
var scope = this;
|
||||
|
||||
var cached = Cache.get( url );
|
||||
|
||||
if ( cached !== undefined ) {
|
||||
|
||||
scope.manager.itemStart( url );
|
||||
|
||||
setTimeout( function () {
|
||||
|
||||
if ( onLoad ) onLoad( cached );
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
|
||||
}, 0 );
|
||||
|
||||
return cached;
|
||||
|
||||
}
|
||||
|
||||
fetch( url ).then( function ( res ) {
|
||||
|
||||
return res.blob();
|
||||
|
||||
} ).then( function ( blob ) {
|
||||
|
||||
return createImageBitmap( blob, scope.options );
|
||||
|
||||
} ).then( function ( imageBitmap ) {
|
||||
|
||||
Cache.add( url, imageBitmap );
|
||||
|
||||
if ( onLoad ) onLoad( imageBitmap );
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
|
||||
} ).catch( function ( e ) {
|
||||
|
||||
if ( onError ) onError( e );
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
scope.manager.itemError( url );
|
||||
|
||||
} );
|
||||
|
||||
},
|
||||
|
||||
setCrossOrigin: function ( /* value */ ) {
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setPath: function ( value ) {
|
||||
|
||||
this.path = value;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export { ImageBitmapLoader };
|
108
lib/loaders/ImageLoader.js
Normal file
108
lib/loaders/ImageLoader.js
Normal file
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
import { Cache } from './Cache.js';
|
||||
import { DefaultLoadingManager } from './LoadingManager.js';
|
||||
|
||||
|
||||
function ImageLoader( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
|
||||
|
||||
}
|
||||
|
||||
Object.assign( ImageLoader.prototype, {
|
||||
|
||||
crossOrigin: 'anonymous',
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
if ( url === undefined ) url = '';
|
||||
|
||||
if ( this.path !== undefined ) url = this.path + url;
|
||||
|
||||
url = this.manager.resolveURL( url );
|
||||
|
||||
var scope = this;
|
||||
|
||||
var cached = Cache.get( url );
|
||||
|
||||
if ( cached !== undefined ) {
|
||||
|
||||
scope.manager.itemStart( url );
|
||||
|
||||
setTimeout( function () {
|
||||
|
||||
if ( onLoad ) onLoad( cached );
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
|
||||
}, 0 );
|
||||
|
||||
return cached;
|
||||
|
||||
}
|
||||
|
||||
var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );
|
||||
|
||||
function onImageLoad() {
|
||||
|
||||
image.removeEventListener( 'load', onImageLoad, false );
|
||||
image.removeEventListener( 'error', onImageError, false );
|
||||
|
||||
Cache.add( url, this );
|
||||
|
||||
if ( onLoad ) onLoad( this );
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
|
||||
}
|
||||
|
||||
function onImageError( event ) {
|
||||
|
||||
image.removeEventListener( 'load', onImageLoad, false );
|
||||
image.removeEventListener( 'error', onImageError, false );
|
||||
|
||||
if ( onError ) onError( event );
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
scope.manager.itemError( url );
|
||||
|
||||
}
|
||||
|
||||
image.addEventListener( 'load', onImageLoad, false );
|
||||
image.addEventListener( 'error', onImageError, false );
|
||||
|
||||
if ( url.substr( 0, 5 ) !== 'data:' ) {
|
||||
|
||||
if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
|
||||
|
||||
}
|
||||
|
||||
scope.manager.itemStart( url );
|
||||
|
||||
image.src = url;
|
||||
|
||||
return image;
|
||||
|
||||
},
|
||||
|
||||
setCrossOrigin: function ( value ) {
|
||||
|
||||
this.crossOrigin = value;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setPath: function ( value ) {
|
||||
|
||||
this.path = value;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
|
||||
export { ImageLoader };
|
587
lib/loaders/JSONLoader.js
Normal file
587
lib/loaders/JSONLoader.js
Normal file
@ -0,0 +1,587 @@
|
||||
import { Loader } from './Loader.js';
|
||||
import { LoaderUtils } from './LoaderUtils.js';
|
||||
import { AnimationClip } from '../animation/AnimationClip.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
import { Vector4 } from '../math/Vector4.js';
|
||||
import { Color } from '../math/Color.js';
|
||||
import { Vector2 } from '../math/Vector2.js';
|
||||
import { Face3 } from '../core/Face3.js';
|
||||
import { Geometry } from '../core/Geometry.js';
|
||||
import { FileLoader } from './FileLoader.js';
|
||||
import { DefaultLoadingManager } from './LoadingManager.js';
|
||||
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
function JSONLoader( manager ) {
|
||||
|
||||
if ( typeof manager === 'boolean' ) {
|
||||
|
||||
console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' );
|
||||
manager = undefined;
|
||||
|
||||
}
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
|
||||
|
||||
this.withCredentials = false;
|
||||
|
||||
}
|
||||
|
||||
Object.assign( JSONLoader.prototype, {
|
||||
|
||||
crossOrigin: 'anonymous',
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var path = ( this.path === undefined ) ? LoaderUtils.extractUrlBase( url ) : this.path;
|
||||
|
||||
var loader = new FileLoader( this.manager );
|
||||
loader.setPath( this.path );
|
||||
loader.setWithCredentials( this.withCredentials );
|
||||
loader.load( url, function ( text ) {
|
||||
|
||||
var json = JSON.parse( text );
|
||||
var metadata = json.metadata;
|
||||
|
||||
if ( metadata !== undefined ) {
|
||||
|
||||
var type = metadata.type;
|
||||
|
||||
if ( type !== undefined ) {
|
||||
|
||||
if ( type.toLowerCase() === 'object' ) {
|
||||
|
||||
console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' );
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var object = scope.parse( json, path );
|
||||
onLoad( object.geometry, object.materials );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
},
|
||||
|
||||
setPath: function ( value ) {
|
||||
|
||||
this.path = value;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setResourcePath: function ( value ) {
|
||||
|
||||
this.resourcePath = value;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setCrossOrigin: function ( value ) {
|
||||
|
||||
this.crossOrigin = value;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
parse: ( function () {
|
||||
|
||||
function parseModel( json, geometry ) {
|
||||
|
||||
function isBitSet( value, position ) {
|
||||
|
||||
return value & ( 1 << position );
|
||||
|
||||
}
|
||||
|
||||
var i, j, fi,
|
||||
|
||||
offset, zLength,
|
||||
|
||||
colorIndex, normalIndex, uvIndex, materialIndex,
|
||||
|
||||
type,
|
||||
isQuad,
|
||||
hasMaterial,
|
||||
hasFaceVertexUv,
|
||||
hasFaceNormal, hasFaceVertexNormal,
|
||||
hasFaceColor, hasFaceVertexColor,
|
||||
|
||||
vertex, face, faceA, faceB, hex, normal,
|
||||
|
||||
uvLayer, uv, u, v,
|
||||
|
||||
faces = json.faces,
|
||||
vertices = json.vertices,
|
||||
normals = json.normals,
|
||||
colors = json.colors,
|
||||
|
||||
scale = json.scale,
|
||||
|
||||
nUvLayers = 0;
|
||||
|
||||
|
||||
if ( json.uvs !== undefined ) {
|
||||
|
||||
// disregard empty arrays
|
||||
|
||||
for ( i = 0; i < json.uvs.length; i ++ ) {
|
||||
|
||||
if ( json.uvs[ i ].length ) nUvLayers ++;
|
||||
|
||||
}
|
||||
|
||||
for ( i = 0; i < nUvLayers; i ++ ) {
|
||||
|
||||
geometry.faceVertexUvs[ i ] = [];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
zLength = vertices.length;
|
||||
|
||||
while ( offset < zLength ) {
|
||||
|
||||
vertex = new Vector3();
|
||||
|
||||
vertex.x = vertices[ offset ++ ] * scale;
|
||||
vertex.y = vertices[ offset ++ ] * scale;
|
||||
vertex.z = vertices[ offset ++ ] * scale;
|
||||
|
||||
geometry.vertices.push( vertex );
|
||||
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
zLength = faces.length;
|
||||
|
||||
while ( offset < zLength ) {
|
||||
|
||||
type = faces[ offset ++ ];
|
||||
|
||||
isQuad = isBitSet( type, 0 );
|
||||
hasMaterial = isBitSet( type, 1 );
|
||||
hasFaceVertexUv = isBitSet( type, 3 );
|
||||
hasFaceNormal = isBitSet( type, 4 );
|
||||
hasFaceVertexNormal = isBitSet( type, 5 );
|
||||
hasFaceColor = isBitSet( type, 6 );
|
||||
hasFaceVertexColor = isBitSet( type, 7 );
|
||||
|
||||
// console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
|
||||
|
||||
if ( isQuad ) {
|
||||
|
||||
faceA = new Face3();
|
||||
faceA.a = faces[ offset ];
|
||||
faceA.b = faces[ offset + 1 ];
|
||||
faceA.c = faces[ offset + 3 ];
|
||||
|
||||
faceB = new Face3();
|
||||
faceB.a = faces[ offset + 1 ];
|
||||
faceB.b = faces[ offset + 2 ];
|
||||
faceB.c = faces[ offset + 3 ];
|
||||
|
||||
offset += 4;
|
||||
|
||||
if ( hasMaterial ) {
|
||||
|
||||
materialIndex = faces[ offset ++ ];
|
||||
faceA.materialIndex = materialIndex;
|
||||
faceB.materialIndex = materialIndex;
|
||||
|
||||
}
|
||||
|
||||
// to get face <=> uv index correspondence
|
||||
|
||||
fi = geometry.faces.length;
|
||||
|
||||
if ( hasFaceVertexUv ) {
|
||||
|
||||
for ( i = 0; i < nUvLayers; i ++ ) {
|
||||
|
||||
uvLayer = json.uvs[ i ];
|
||||
|
||||
geometry.faceVertexUvs[ i ][ fi ] = [];
|
||||
geometry.faceVertexUvs[ i ][ fi + 1 ] = [];
|
||||
|
||||
for ( j = 0; j < 4; j ++ ) {
|
||||
|
||||
uvIndex = faces[ offset ++ ];
|
||||
|
||||
u = uvLayer[ uvIndex * 2 ];
|
||||
v = uvLayer[ uvIndex * 2 + 1 ];
|
||||
|
||||
uv = new Vector2( u, v );
|
||||
|
||||
if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
|
||||
if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( hasFaceNormal ) {
|
||||
|
||||
normalIndex = faces[ offset ++ ] * 3;
|
||||
|
||||
faceA.normal.set(
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ]
|
||||
);
|
||||
|
||||
faceB.normal.copy( faceA.normal );
|
||||
|
||||
}
|
||||
|
||||
if ( hasFaceVertexNormal ) {
|
||||
|
||||
for ( i = 0; i < 4; i ++ ) {
|
||||
|
||||
normalIndex = faces[ offset ++ ] * 3;
|
||||
|
||||
normal = new Vector3(
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ]
|
||||
);
|
||||
|
||||
|
||||
if ( i !== 2 ) faceA.vertexNormals.push( normal );
|
||||
if ( i !== 0 ) faceB.vertexNormals.push( normal );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ( hasFaceColor ) {
|
||||
|
||||
colorIndex = faces[ offset ++ ];
|
||||
hex = colors[ colorIndex ];
|
||||
|
||||
faceA.color.setHex( hex );
|
||||
faceB.color.setHex( hex );
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ( hasFaceVertexColor ) {
|
||||
|
||||
for ( i = 0; i < 4; i ++ ) {
|
||||
|
||||
colorIndex = faces[ offset ++ ];
|
||||
hex = colors[ colorIndex ];
|
||||
|
||||
if ( i !== 2 ) faceA.vertexColors.push( new Color( hex ) );
|
||||
if ( i !== 0 ) faceB.vertexColors.push( new Color( hex ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
geometry.faces.push( faceA );
|
||||
geometry.faces.push( faceB );
|
||||
|
||||
} else {
|
||||
|
||||
face = new Face3();
|
||||
face.a = faces[ offset ++ ];
|
||||
face.b = faces[ offset ++ ];
|
||||
face.c = faces[ offset ++ ];
|
||||
|
||||
if ( hasMaterial ) {
|
||||
|
||||
materialIndex = faces[ offset ++ ];
|
||||
face.materialIndex = materialIndex;
|
||||
|
||||
}
|
||||
|
||||
// to get face <=> uv index correspondence
|
||||
|
||||
fi = geometry.faces.length;
|
||||
|
||||
if ( hasFaceVertexUv ) {
|
||||
|
||||
for ( i = 0; i < nUvLayers; i ++ ) {
|
||||
|
||||
uvLayer = json.uvs[ i ];
|
||||
|
||||
geometry.faceVertexUvs[ i ][ fi ] = [];
|
||||
|
||||
for ( j = 0; j < 3; j ++ ) {
|
||||
|
||||
uvIndex = faces[ offset ++ ];
|
||||
|
||||
u = uvLayer[ uvIndex * 2 ];
|
||||
v = uvLayer[ uvIndex * 2 + 1 ];
|
||||
|
||||
uv = new Vector2( u, v );
|
||||
|
||||
geometry.faceVertexUvs[ i ][ fi ].push( uv );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( hasFaceNormal ) {
|
||||
|
||||
normalIndex = faces[ offset ++ ] * 3;
|
||||
|
||||
face.normal.set(
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
if ( hasFaceVertexNormal ) {
|
||||
|
||||
for ( i = 0; i < 3; i ++ ) {
|
||||
|
||||
normalIndex = faces[ offset ++ ] * 3;
|
||||
|
||||
normal = new Vector3(
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ++ ],
|
||||
normals[ normalIndex ]
|
||||
);
|
||||
|
||||
face.vertexNormals.push( normal );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ( hasFaceColor ) {
|
||||
|
||||
colorIndex = faces[ offset ++ ];
|
||||
face.color.setHex( colors[ colorIndex ] );
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ( hasFaceVertexColor ) {
|
||||
|
||||
for ( i = 0; i < 3; i ++ ) {
|
||||
|
||||
colorIndex = faces[ offset ++ ];
|
||||
face.vertexColors.push( new Color( colors[ colorIndex ] ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
geometry.faces.push( face );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function parseSkin( json, geometry ) {
|
||||
|
||||
var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2;
|
||||
|
||||
if ( json.skinWeights ) {
|
||||
|
||||
for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) {
|
||||
|
||||
var x = json.skinWeights[ i ];
|
||||
var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0;
|
||||
var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0;
|
||||
var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0;
|
||||
|
||||
geometry.skinWeights.push( new Vector4( x, y, z, w ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( json.skinIndices ) {
|
||||
|
||||
for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) {
|
||||
|
||||
var a = json.skinIndices[ i ];
|
||||
var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0;
|
||||
var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0;
|
||||
var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0;
|
||||
|
||||
geometry.skinIndices.push( new Vector4( a, b, c, d ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
geometry.bones = json.bones;
|
||||
|
||||
if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) {
|
||||
|
||||
console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' +
|
||||
geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function parseMorphing( json, geometry ) {
|
||||
|
||||
var scale = json.scale;
|
||||
|
||||
if ( json.morphTargets !== undefined ) {
|
||||
|
||||
for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) {
|
||||
|
||||
geometry.morphTargets[ i ] = {};
|
||||
geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
|
||||
geometry.morphTargets[ i ].vertices = [];
|
||||
|
||||
var dstVertices = geometry.morphTargets[ i ].vertices;
|
||||
var srcVertices = json.morphTargets[ i ].vertices;
|
||||
|
||||
for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
|
||||
|
||||
var vertex = new Vector3();
|
||||
vertex.x = srcVertices[ v ] * scale;
|
||||
vertex.y = srcVertices[ v + 1 ] * scale;
|
||||
vertex.z = srcVertices[ v + 2 ] * scale;
|
||||
|
||||
dstVertices.push( vertex );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( json.morphColors !== undefined && json.morphColors.length > 0 ) {
|
||||
|
||||
console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' );
|
||||
|
||||
var faces = geometry.faces;
|
||||
var morphColors = json.morphColors[ 0 ].colors;
|
||||
|
||||
for ( var i = 0, l = faces.length; i < l; i ++ ) {
|
||||
|
||||
faces[ i ].color.fromArray( morphColors, i * 3 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function parseAnimations( json, geometry ) {
|
||||
|
||||
var outputAnimations = [];
|
||||
|
||||
// parse old style Bone/Hierarchy animations
|
||||
var animations = [];
|
||||
|
||||
if ( json.animation !== undefined ) {
|
||||
|
||||
animations.push( json.animation );
|
||||
|
||||
}
|
||||
|
||||
if ( json.animations !== undefined ) {
|
||||
|
||||
if ( json.animations.length ) {
|
||||
|
||||
animations = animations.concat( json.animations );
|
||||
|
||||
} else {
|
||||
|
||||
animations.push( json.animations );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for ( var i = 0; i < animations.length; i ++ ) {
|
||||
|
||||
var clip = AnimationClip.parseAnimation( animations[ i ], geometry.bones );
|
||||
if ( clip ) outputAnimations.push( clip );
|
||||
|
||||
}
|
||||
|
||||
// parse implicit morph animations
|
||||
if ( geometry.morphTargets ) {
|
||||
|
||||
// TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary.
|
||||
var morphAnimationClips = AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 );
|
||||
outputAnimations = outputAnimations.concat( morphAnimationClips );
|
||||
|
||||
}
|
||||
|
||||
if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations;
|
||||
|
||||
}
|
||||
|
||||
return function parse( json, path ) {
|
||||
|
||||
if ( json.data !== undefined ) {
|
||||
|
||||
// Geometry 4.0 spec
|
||||
json = json.data;
|
||||
|
||||
}
|
||||
|
||||
if ( json.scale !== undefined ) {
|
||||
|
||||
json.scale = 1.0 / json.scale;
|
||||
|
||||
} else {
|
||||
|
||||
json.scale = 1.0;
|
||||
|
||||
}
|
||||
|
||||
var geometry = new Geometry();
|
||||
|
||||
parseModel( json, geometry );
|
||||
parseSkin( json, geometry );
|
||||
parseMorphing( json, geometry );
|
||||
parseAnimations( json, geometry );
|
||||
|
||||
geometry.computeFaceNormals();
|
||||
geometry.computeBoundingSphere();
|
||||
|
||||
if ( json.materials === undefined || json.materials.length === 0 ) {
|
||||
|
||||
return { geometry: geometry };
|
||||
|
||||
} else {
|
||||
|
||||
var materials = Loader.prototype.initMaterials( json.materials, this.resourcePath || path, this.crossOrigin );
|
||||
|
||||
return { geometry: geometry, materials: materials };
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} )()
|
||||
|
||||
} );
|
||||
|
||||
|
||||
export { JSONLoader };
|
342
lib/loaders/Loader.js
Normal file
342
lib/loaders/Loader.js
Normal file
@ -0,0 +1,342 @@
|
||||
import {
|
||||
NoBlending,
|
||||
NormalBlending,
|
||||
AdditiveBlending,
|
||||
SubtractiveBlending,
|
||||
MultiplyBlending,
|
||||
CustomBlending,
|
||||
|
||||
FaceColors,
|
||||
VertexColors,
|
||||
|
||||
DoubleSide,
|
||||
BackSide,
|
||||
|
||||
MirroredRepeatWrapping,
|
||||
RepeatWrapping
|
||||
} from '../constants.js';
|
||||
import { _Math } from '../math/Math.js';
|
||||
import { MaterialLoader } from './MaterialLoader.js';
|
||||
import { TextureLoader } from './TextureLoader.js';
|
||||
import { Color } from '../math/Color.js';
|
||||
|
||||
/**
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
*/
|
||||
|
||||
function Loader() {}
|
||||
|
||||
Loader.Handlers = {
|
||||
|
||||
handlers: [],
|
||||
|
||||
add: function ( regex, loader ) {
|
||||
|
||||
this.handlers.push( regex, loader );
|
||||
|
||||
},
|
||||
|
||||
get: function ( file ) {
|
||||
|
||||
var handlers = this.handlers;
|
||||
|
||||
for ( var i = 0, l = handlers.length; i < l; i += 2 ) {
|
||||
|
||||
var regex = handlers[ i ];
|
||||
var loader = handlers[ i + 1 ];
|
||||
|
||||
if ( regex.test( file ) ) {
|
||||
|
||||
return loader;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Object.assign( Loader.prototype, {
|
||||
|
||||
crossOrigin: 'anonymous',
|
||||
|
||||
onLoadStart: function () {},
|
||||
|
||||
onLoadProgress: function () {},
|
||||
|
||||
onLoadComplete: function () {},
|
||||
|
||||
initMaterials: function ( materials, texturePath, crossOrigin ) {
|
||||
|
||||
var array = [];
|
||||
|
||||
for ( var i = 0; i < materials.length; ++ i ) {
|
||||
|
||||
array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin );
|
||||
|
||||
}
|
||||
|
||||
return array;
|
||||
|
||||
},
|
||||
|
||||
createMaterial: ( function () {
|
||||
|
||||
var BlendingMode = {
|
||||
NoBlending: NoBlending,
|
||||
NormalBlending: NormalBlending,
|
||||
AdditiveBlending: AdditiveBlending,
|
||||
SubtractiveBlending: SubtractiveBlending,
|
||||
MultiplyBlending: MultiplyBlending,
|
||||
CustomBlending: CustomBlending
|
||||
};
|
||||
|
||||
var color = new Color();
|
||||
var textureLoader = new TextureLoader();
|
||||
var materialLoader = new MaterialLoader();
|
||||
|
||||
return function createMaterial( m, texturePath, crossOrigin ) {
|
||||
|
||||
// convert from old material format
|
||||
|
||||
var textures = {};
|
||||
|
||||
function loadTexture( path, repeat, offset, wrap, anisotropy ) {
|
||||
|
||||
var fullPath = texturePath + path;
|
||||
var loader = Loader.Handlers.get( fullPath );
|
||||
|
||||
var texture;
|
||||
|
||||
if ( loader !== null ) {
|
||||
|
||||
texture = loader.load( fullPath );
|
||||
|
||||
} else {
|
||||
|
||||
textureLoader.setCrossOrigin( crossOrigin );
|
||||
texture = textureLoader.load( fullPath );
|
||||
|
||||
}
|
||||
|
||||
if ( repeat !== undefined ) {
|
||||
|
||||
texture.repeat.fromArray( repeat );
|
||||
|
||||
if ( repeat[ 0 ] !== 1 ) texture.wrapS = RepeatWrapping;
|
||||
if ( repeat[ 1 ] !== 1 ) texture.wrapT = RepeatWrapping;
|
||||
|
||||
}
|
||||
|
||||
if ( offset !== undefined ) {
|
||||
|
||||
texture.offset.fromArray( offset );
|
||||
|
||||
}
|
||||
|
||||
if ( wrap !== undefined ) {
|
||||
|
||||
if ( wrap[ 0 ] === 'repeat' ) texture.wrapS = RepeatWrapping;
|
||||
if ( wrap[ 0 ] === 'mirror' ) texture.wrapS = MirroredRepeatWrapping;
|
||||
|
||||
if ( wrap[ 1 ] === 'repeat' ) texture.wrapT = RepeatWrapping;
|
||||
if ( wrap[ 1 ] === 'mirror' ) texture.wrapT = MirroredRepeatWrapping;
|
||||
|
||||
}
|
||||
|
||||
if ( anisotropy !== undefined ) {
|
||||
|
||||
texture.anisotropy = anisotropy;
|
||||
|
||||
}
|
||||
|
||||
var uuid = _Math.generateUUID();
|
||||
|
||||
textures[ uuid ] = texture;
|
||||
|
||||
return uuid;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var json = {
|
||||
uuid: _Math.generateUUID(),
|
||||
type: 'MeshLambertMaterial'
|
||||
};
|
||||
|
||||
for ( var name in m ) {
|
||||
|
||||
var value = m[ name ];
|
||||
|
||||
switch ( name ) {
|
||||
|
||||
case 'DbgColor':
|
||||
case 'DbgIndex':
|
||||
case 'opticalDensity':
|
||||
case 'illumination':
|
||||
break;
|
||||
case 'DbgName':
|
||||
json.name = value;
|
||||
break;
|
||||
case 'blending':
|
||||
json.blending = BlendingMode[ value ];
|
||||
break;
|
||||
case 'colorAmbient':
|
||||
case 'mapAmbient':
|
||||
console.warn( 'THREE.Loader.createMaterial:', name, 'is no longer supported.' );
|
||||
break;
|
||||
case 'colorDiffuse':
|
||||
json.color = color.fromArray( value ).getHex();
|
||||
break;
|
||||
case 'colorSpecular':
|
||||
json.specular = color.fromArray( value ).getHex();
|
||||
break;
|
||||
case 'colorEmissive':
|
||||
json.emissive = color.fromArray( value ).getHex();
|
||||
break;
|
||||
case 'specularCoef':
|
||||
json.shininess = value;
|
||||
break;
|
||||
case 'shading':
|
||||
if ( value.toLowerCase() === 'basic' ) json.type = 'MeshBasicMaterial';
|
||||
if ( value.toLowerCase() === 'phong' ) json.type = 'MeshPhongMaterial';
|
||||
if ( value.toLowerCase() === 'standard' ) json.type = 'MeshStandardMaterial';
|
||||
break;
|
||||
case 'mapDiffuse':
|
||||
json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy );
|
||||
break;
|
||||
case 'mapDiffuseRepeat':
|
||||
case 'mapDiffuseOffset':
|
||||
case 'mapDiffuseWrap':
|
||||
case 'mapDiffuseAnisotropy':
|
||||
break;
|
||||
case 'mapEmissive':
|
||||
json.emissiveMap = loadTexture( value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy );
|
||||
break;
|
||||
case 'mapEmissiveRepeat':
|
||||
case 'mapEmissiveOffset':
|
||||
case 'mapEmissiveWrap':
|
||||
case 'mapEmissiveAnisotropy':
|
||||
break;
|
||||
case 'mapLight':
|
||||
json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy );
|
||||
break;
|
||||
case 'mapLightRepeat':
|
||||
case 'mapLightOffset':
|
||||
case 'mapLightWrap':
|
||||
case 'mapLightAnisotropy':
|
||||
break;
|
||||
case 'mapAO':
|
||||
json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy );
|
||||
break;
|
||||
case 'mapAORepeat':
|
||||
case 'mapAOOffset':
|
||||
case 'mapAOWrap':
|
||||
case 'mapAOAnisotropy':
|
||||
break;
|
||||
case 'mapBump':
|
||||
json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy );
|
||||
break;
|
||||
case 'mapBumpScale':
|
||||
json.bumpScale = value;
|
||||
break;
|
||||
case 'mapBumpRepeat':
|
||||
case 'mapBumpOffset':
|
||||
case 'mapBumpWrap':
|
||||
case 'mapBumpAnisotropy':
|
||||
break;
|
||||
case 'mapNormal':
|
||||
json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy );
|
||||
break;
|
||||
case 'mapNormalFactor':
|
||||
json.normalScale = value;
|
||||
break;
|
||||
case 'mapNormalRepeat':
|
||||
case 'mapNormalOffset':
|
||||
case 'mapNormalWrap':
|
||||
case 'mapNormalAnisotropy':
|
||||
break;
|
||||
case 'mapSpecular':
|
||||
json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy );
|
||||
break;
|
||||
case 'mapSpecularRepeat':
|
||||
case 'mapSpecularOffset':
|
||||
case 'mapSpecularWrap':
|
||||
case 'mapSpecularAnisotropy':
|
||||
break;
|
||||
case 'mapMetalness':
|
||||
json.metalnessMap = loadTexture( value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy );
|
||||
break;
|
||||
case 'mapMetalnessRepeat':
|
||||
case 'mapMetalnessOffset':
|
||||
case 'mapMetalnessWrap':
|
||||
case 'mapMetalnessAnisotropy':
|
||||
break;
|
||||
case 'mapRoughness':
|
||||
json.roughnessMap = loadTexture( value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy );
|
||||
break;
|
||||
case 'mapRoughnessRepeat':
|
||||
case 'mapRoughnessOffset':
|
||||
case 'mapRoughnessWrap':
|
||||
case 'mapRoughnessAnisotropy':
|
||||
break;
|
||||
case 'mapAlpha':
|
||||
json.alphaMap = loadTexture( value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy );
|
||||
break;
|
||||
case 'mapAlphaRepeat':
|
||||
case 'mapAlphaOffset':
|
||||
case 'mapAlphaWrap':
|
||||
case 'mapAlphaAnisotropy':
|
||||
break;
|
||||
case 'flipSided':
|
||||
json.side = BackSide;
|
||||
break;
|
||||
case 'doubleSided':
|
||||
json.side = DoubleSide;
|
||||
break;
|
||||
case 'transparency':
|
||||
console.warn( 'THREE.Loader.createMaterial: transparency has been renamed to opacity' );
|
||||
json.opacity = value;
|
||||
break;
|
||||
case 'depthTest':
|
||||
case 'depthWrite':
|
||||
case 'colorWrite':
|
||||
case 'opacity':
|
||||
case 'reflectivity':
|
||||
case 'transparent':
|
||||
case 'visible':
|
||||
case 'wireframe':
|
||||
json[ name ] = value;
|
||||
break;
|
||||
case 'vertexColors':
|
||||
if ( value === true ) json.vertexColors = VertexColors;
|
||||
if ( value === 'face' ) json.vertexColors = FaceColors;
|
||||
break;
|
||||
default:
|
||||
console.error( 'THREE.Loader.createMaterial: Unsupported', name, value );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( json.type === 'MeshBasicMaterial' ) delete json.emissive;
|
||||
if ( json.type !== 'MeshPhongMaterial' ) delete json.specular;
|
||||
|
||||
if ( json.opacity < 1 ) json.transparent = true;
|
||||
|
||||
materialLoader.setTextures( textures );
|
||||
|
||||
return materialLoader.parse( json );
|
||||
|
||||
};
|
||||
|
||||
} )()
|
||||
|
||||
} );
|
||||
|
||||
export { Loader };
|
44
lib/loaders/LoaderUtils.js
Normal file
44
lib/loaders/LoaderUtils.js
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @author Don McCurdy / https://www.donmccurdy.com
|
||||
*/
|
||||
|
||||
var LoaderUtils = {
|
||||
|
||||
decodeText: function ( array ) {
|
||||
|
||||
if ( typeof TextDecoder !== 'undefined' ) {
|
||||
|
||||
return new TextDecoder().decode( array );
|
||||
|
||||
}
|
||||
|
||||
// Avoid the String.fromCharCode.apply(null, array) shortcut, which
|
||||
// throws a "maximum call stack size exceeded" error for large arrays.
|
||||
|
||||
var s = '';
|
||||
|
||||
for ( var i = 0, il = array.length; i < il; i ++ ) {
|
||||
|
||||
// Implicitly assumes little-endian.
|
||||
s += String.fromCharCode( array[ i ] );
|
||||
|
||||
}
|
||||
|
||||
// Merges multi-byte utf-8 characters.
|
||||
return decodeURIComponent( escape( s ) );
|
||||
|
||||
},
|
||||
|
||||
extractUrlBase: function ( url ) {
|
||||
|
||||
var index = url.lastIndexOf( '/' );
|
||||
|
||||
if ( index === - 1 ) return './';
|
||||
|
||||
return url.substr( 0, index + 1 );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export { LoaderUtils };
|
98
lib/loaders/LoadingManager.js
Normal file
98
lib/loaders/LoadingManager.js
Normal file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
function LoadingManager( onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var isLoading = false;
|
||||
var itemsLoaded = 0;
|
||||
var itemsTotal = 0;
|
||||
var urlModifier = undefined;
|
||||
|
||||
// Refer to #5689 for the reason why we don't set .onStart
|
||||
// in the constructor
|
||||
|
||||
this.onStart = undefined;
|
||||
this.onLoad = onLoad;
|
||||
this.onProgress = onProgress;
|
||||
this.onError = onError;
|
||||
|
||||
this.itemStart = function ( url ) {
|
||||
|
||||
itemsTotal ++;
|
||||
|
||||
if ( isLoading === false ) {
|
||||
|
||||
if ( scope.onStart !== undefined ) {
|
||||
|
||||
scope.onStart( url, itemsLoaded, itemsTotal );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
isLoading = true;
|
||||
|
||||
};
|
||||
|
||||
this.itemEnd = function ( url ) {
|
||||
|
||||
itemsLoaded ++;
|
||||
|
||||
if ( scope.onProgress !== undefined ) {
|
||||
|
||||
scope.onProgress( url, itemsLoaded, itemsTotal );
|
||||
|
||||
}
|
||||
|
||||
if ( itemsLoaded === itemsTotal ) {
|
||||
|
||||
isLoading = false;
|
||||
|
||||
if ( scope.onLoad !== undefined ) {
|
||||
|
||||
scope.onLoad();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.itemError = function ( url ) {
|
||||
|
||||
if ( scope.onError !== undefined ) {
|
||||
|
||||
scope.onError( url );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.resolveURL = function ( url ) {
|
||||
|
||||
if ( urlModifier ) {
|
||||
|
||||
return urlModifier( url );
|
||||
|
||||
}
|
||||
|
||||
return url;
|
||||
|
||||
};
|
||||
|
||||
this.setURLModifier = function ( transform ) {
|
||||
|
||||
urlModifier = transform;
|
||||
return this;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
var DefaultLoadingManager = new LoadingManager();
|
||||
|
||||
|
||||
export { DefaultLoadingManager, LoadingManager };
|
236
lib/loaders/MaterialLoader.js
Normal file
236
lib/loaders/MaterialLoader.js
Normal file
@ -0,0 +1,236 @@
|
||||
import { Color } from '../math/Color.js';
|
||||
import { Vector2 } from '../math/Vector2.js';
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
import { Vector4 } from '../math/Vector4.js';
|
||||
import { Matrix4 } from '../math/Matrix4.js';
|
||||
import { FileLoader } from './FileLoader.js';
|
||||
import { DefaultLoadingManager } from './LoadingManager.js';
|
||||
import * as Materials from '../materials/Materials.js';
|
||||
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
function MaterialLoader( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
|
||||
this.textures = {};
|
||||
|
||||
}
|
||||
|
||||
Object.assign( MaterialLoader.prototype, {
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var loader = new FileLoader( scope.manager );
|
||||
loader.setPath( scope.path );
|
||||
loader.load( url, function ( text ) {
|
||||
|
||||
onLoad( scope.parse( JSON.parse( text ) ) );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
},
|
||||
|
||||
parse: function ( json ) {
|
||||
|
||||
var textures = this.textures;
|
||||
|
||||
function getTexture( name ) {
|
||||
|
||||
if ( textures[ name ] === undefined ) {
|
||||
|
||||
console.warn( 'THREE.MaterialLoader: Undefined texture', name );
|
||||
|
||||
}
|
||||
|
||||
return textures[ name ];
|
||||
|
||||
}
|
||||
|
||||
var material = new Materials[ json.type ]();
|
||||
|
||||
if ( json.uuid !== undefined ) material.uuid = json.uuid;
|
||||
if ( json.name !== undefined ) material.name = json.name;
|
||||
if ( json.color !== undefined ) material.color.setHex( json.color );
|
||||
if ( json.roughness !== undefined ) material.roughness = json.roughness;
|
||||
if ( json.metalness !== undefined ) material.metalness = json.metalness;
|
||||
if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive );
|
||||
if ( json.specular !== undefined ) material.specular.setHex( json.specular );
|
||||
if ( json.shininess !== undefined ) material.shininess = json.shininess;
|
||||
if ( json.clearCoat !== undefined ) material.clearCoat = json.clearCoat;
|
||||
if ( json.clearCoatRoughness !== undefined ) material.clearCoatRoughness = json.clearCoatRoughness;
|
||||
if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors;
|
||||
if ( json.fog !== undefined ) material.fog = json.fog;
|
||||
if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
|
||||
if ( json.blending !== undefined ) material.blending = json.blending;
|
||||
if ( json.combine !== undefined ) material.combine = json.combine;
|
||||
if ( json.side !== undefined ) material.side = json.side;
|
||||
if ( json.opacity !== undefined ) material.opacity = json.opacity;
|
||||
if ( json.transparent !== undefined ) material.transparent = json.transparent;
|
||||
if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
|
||||
if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
|
||||
if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
|
||||
if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
|
||||
if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
|
||||
if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
|
||||
if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
|
||||
if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
|
||||
|
||||
if ( json.rotation !== undefined ) material.rotation = json.rotation;
|
||||
|
||||
if ( json.linewidth !== 1 ) material.linewidth = json.linewidth;
|
||||
if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
|
||||
if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
|
||||
if ( json.scale !== undefined ) material.scale = json.scale;
|
||||
|
||||
if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
|
||||
if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
|
||||
if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
|
||||
|
||||
if ( json.skinning !== undefined ) material.skinning = json.skinning;
|
||||
if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets;
|
||||
if ( json.dithering !== undefined ) material.dithering = json.dithering;
|
||||
|
||||
if ( json.visible !== undefined ) material.visible = json.visible;
|
||||
if ( json.userData !== undefined ) material.userData = json.userData;
|
||||
|
||||
// Shader Material
|
||||
|
||||
if ( json.uniforms !== undefined ) {
|
||||
|
||||
for ( var name in json.uniforms ) {
|
||||
|
||||
var uniform = json.uniforms[ name ];
|
||||
|
||||
material.uniforms[ name ] = {};
|
||||
|
||||
switch ( uniform.type ) {
|
||||
|
||||
case 't':
|
||||
material.uniforms[ name ].value = getTexture( uniform.value );
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
material.uniforms[ name ].value = new Color().setHex( uniform.value );
|
||||
break;
|
||||
|
||||
case 'v2':
|
||||
material.uniforms[ name ].value = new Vector2().fromArray( uniform.value );
|
||||
break;
|
||||
|
||||
case 'v3':
|
||||
material.uniforms[ name ].value = new Vector3().fromArray( uniform.value );
|
||||
break;
|
||||
|
||||
case 'v4':
|
||||
material.uniforms[ name ].value = new Vector4().fromArray( uniform.value );
|
||||
break;
|
||||
|
||||
case 'm4':
|
||||
material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );
|
||||
break;
|
||||
|
||||
default:
|
||||
material.uniforms[ name ].value = uniform.value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( json.defines !== undefined ) material.defines = json.defines;
|
||||
if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
|
||||
if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
|
||||
|
||||
// Deprecated
|
||||
|
||||
if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading
|
||||
|
||||
// for PointsMaterial
|
||||
|
||||
if ( json.size !== undefined ) material.size = json.size;
|
||||
if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
|
||||
|
||||
// maps
|
||||
|
||||
if ( json.map !== undefined ) material.map = getTexture( json.map );
|
||||
|
||||
if ( json.alphaMap !== undefined ) {
|
||||
|
||||
material.alphaMap = getTexture( json.alphaMap );
|
||||
material.transparent = true;
|
||||
|
||||
}
|
||||
|
||||
if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
|
||||
if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
|
||||
|
||||
if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
|
||||
if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType;
|
||||
if ( json.normalScale !== undefined ) {
|
||||
|
||||
var normalScale = json.normalScale;
|
||||
|
||||
if ( Array.isArray( normalScale ) === false ) {
|
||||
|
||||
// Blender exporter used to export a scalar. See #7459
|
||||
|
||||
normalScale = [ normalScale, normalScale ];
|
||||
|
||||
}
|
||||
|
||||
material.normalScale = new Vector2().fromArray( normalScale );
|
||||
|
||||
}
|
||||
|
||||
if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
|
||||
if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
|
||||
if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
|
||||
|
||||
if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
|
||||
if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
|
||||
|
||||
if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
|
||||
if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
|
||||
|
||||
if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
|
||||
|
||||
if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
|
||||
if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity;
|
||||
|
||||
if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
|
||||
|
||||
if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
|
||||
if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
|
||||
|
||||
if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
|
||||
if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
|
||||
|
||||
if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
|
||||
|
||||
return material;
|
||||
|
||||
},
|
||||
|
||||
setPath: function ( value ) {
|
||||
|
||||
this.path = value;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setTextures: function ( value ) {
|
||||
|
||||
this.textures = value;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
|
||||
export { MaterialLoader };
|
978
lib/loaders/ObjectLoader.js
Normal file
978
lib/loaders/ObjectLoader.js
Normal file
@ -0,0 +1,978 @@
|
||||
import {
|
||||
UVMapping,
|
||||
CubeReflectionMapping,
|
||||
CubeRefractionMapping,
|
||||
EquirectangularReflectionMapping,
|
||||
EquirectangularRefractionMapping,
|
||||
SphericalReflectionMapping,
|
||||
CubeUVReflectionMapping,
|
||||
CubeUVRefractionMapping,
|
||||
|
||||
RepeatWrapping,
|
||||
ClampToEdgeWrapping,
|
||||
MirroredRepeatWrapping,
|
||||
|
||||
NearestFilter,
|
||||
NearestMipMapNearestFilter,
|
||||
NearestMipMapLinearFilter,
|
||||
LinearFilter,
|
||||
LinearMipMapNearestFilter,
|
||||
LinearMipMapLinearFilter
|
||||
} from '../constants.js';
|
||||
import { Color } from '../math/Color.js';
|
||||
import { Object3D } from '../core/Object3D.js';
|
||||
import { Group } from '../objects/Group.js';
|
||||
import { Sprite } from '../objects/Sprite.js';
|
||||
import { Points } from '../objects/Points.js';
|
||||
import { Line } from '../objects/Line.js';
|
||||
import { LineLoop } from '../objects/LineLoop.js';
|
||||
import { LineSegments } from '../objects/LineSegments.js';
|
||||
import { LOD } from '../objects/LOD.js';
|
||||
import { Mesh } from '../objects/Mesh.js';
|
||||
import { SkinnedMesh } from '../objects/SkinnedMesh.js';
|
||||
import { Shape } from '../extras/core/Shape.js';
|
||||
import { Fog } from '../scenes/Fog.js';
|
||||
import { FogExp2 } from '../scenes/FogExp2.js';
|
||||
import { HemisphereLight } from '../lights/HemisphereLight.js';
|
||||
import { SpotLight } from '../lights/SpotLight.js';
|
||||
import { PointLight } from '../lights/PointLight.js';
|
||||
import { DirectionalLight } from '../lights/DirectionalLight.js';
|
||||
import { AmbientLight } from '../lights/AmbientLight.js';
|
||||
import { RectAreaLight } from '../lights/RectAreaLight.js';
|
||||
import { OrthographicCamera } from '../cameras/OrthographicCamera.js';
|
||||
import { PerspectiveCamera } from '../cameras/PerspectiveCamera.js';
|
||||
import { Scene } from '../scenes/Scene.js';
|
||||
import { CubeTexture } from '../textures/CubeTexture.js';
|
||||
import { Texture } from '../textures/Texture.js';
|
||||
import { ImageLoader } from './ImageLoader.js';
|
||||
import { LoadingManager, DefaultLoadingManager } from './LoadingManager.js';
|
||||
import { AnimationClip } from '../animation/AnimationClip.js';
|
||||
import { MaterialLoader } from './MaterialLoader.js';
|
||||
import { LoaderUtils } from './LoaderUtils.js';
|
||||
import { BufferGeometryLoader } from './BufferGeometryLoader.js';
|
||||
import { JSONLoader } from './JSONLoader.js';
|
||||
import { FileLoader } from './FileLoader.js';
|
||||
import * as Geometries from '../geometries/Geometries.js';
|
||||
import * as Curves from '../extras/curves/Curves.js';
|
||||
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
function ObjectLoader( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
|
||||
this.resourcePath = '';
|
||||
|
||||
}
|
||||
|
||||
Object.assign( ObjectLoader.prototype, {
|
||||
|
||||
crossOrigin: 'anonymous',
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var scope = this;
|
||||
|
||||
var path = ( this.path === undefined ) ? LoaderUtils.extractUrlBase( url ) : this.path;
|
||||
this.resourcePath = this.resourcePath || path;
|
||||
|
||||
var loader = new FileLoader( scope.manager );
|
||||
loader.setPath( this.path );
|
||||
loader.load( url, function ( text ) {
|
||||
|
||||
var json = null;
|
||||
|
||||
try {
|
||||
|
||||
json = JSON.parse( text );
|
||||
|
||||
} catch ( error ) {
|
||||
|
||||
if ( onError !== undefined ) onError( error );
|
||||
|
||||
console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
var metadata = json.metadata;
|
||||
|
||||
if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
|
||||
|
||||
console.error( 'THREE.ObjectLoader: Can\'t load ' + url + '. Use THREE.JSONLoader instead.' );
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
scope.parse( json, onLoad );
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
},
|
||||
|
||||
setPath: function ( value ) {
|
||||
|
||||
this.path = value;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setResourcePath: function ( value ) {
|
||||
|
||||
this.resourcePath = value;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setCrossOrigin: function ( value ) {
|
||||
|
||||
this.crossOrigin = value;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
parse: function ( json, onLoad ) {
|
||||
|
||||
var shapes = this.parseShape( json.shapes );
|
||||
var geometries = this.parseGeometries( json.geometries, shapes );
|
||||
|
||||
var images = this.parseImages( json.images, function () {
|
||||
|
||||
if ( onLoad !== undefined ) onLoad( object );
|
||||
|
||||
} );
|
||||
|
||||
var textures = this.parseTextures( json.textures, images );
|
||||
var materials = this.parseMaterials( json.materials, textures );
|
||||
|
||||
var object = this.parseObject( json.object, geometries, materials );
|
||||
|
||||
if ( json.animations ) {
|
||||
|
||||
object.animations = this.parseAnimations( json.animations );
|
||||
|
||||
}
|
||||
|
||||
if ( json.images === undefined || json.images.length === 0 ) {
|
||||
|
||||
if ( onLoad !== undefined ) onLoad( object );
|
||||
|
||||
}
|
||||
|
||||
return object;
|
||||
|
||||
},
|
||||
|
||||
parseShape: function ( json ) {
|
||||
|
||||
var shapes = {};
|
||||
|
||||
if ( json !== undefined ) {
|
||||
|
||||
for ( var i = 0, l = json.length; i < l; i ++ ) {
|
||||
|
||||
var shape = new Shape().fromJSON( json[ i ] );
|
||||
|
||||
shapes[ shape.uuid ] = shape;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return shapes;
|
||||
|
||||
},
|
||||
|
||||
parseGeometries: function ( json, shapes ) {
|
||||
|
||||
var geometries = {};
|
||||
|
||||
if ( json !== undefined ) {
|
||||
|
||||
var geometryLoader = new JSONLoader();
|
||||
var bufferGeometryLoader = new BufferGeometryLoader();
|
||||
|
||||
for ( var i = 0, l = json.length; i < l; i ++ ) {
|
||||
|
||||
var geometry;
|
||||
var data = json[ i ];
|
||||
|
||||
switch ( data.type ) {
|
||||
|
||||
case 'PlaneGeometry':
|
||||
case 'PlaneBufferGeometry':
|
||||
|
||||
geometry = new Geometries[ data.type ](
|
||||
data.width,
|
||||
data.height,
|
||||
data.widthSegments,
|
||||
data.heightSegments
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'BoxGeometry':
|
||||
case 'BoxBufferGeometry':
|
||||
case 'CubeGeometry': // backwards compatible
|
||||
|
||||
geometry = new Geometries[ data.type ](
|
||||
data.width,
|
||||
data.height,
|
||||
data.depth,
|
||||
data.widthSegments,
|
||||
data.heightSegments,
|
||||
data.depthSegments
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'CircleGeometry':
|
||||
case 'CircleBufferGeometry':
|
||||
|
||||
geometry = new Geometries[ data.type ](
|
||||
data.radius,
|
||||
data.segments,
|
||||
data.thetaStart,
|
||||
data.thetaLength
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'CylinderGeometry':
|
||||
case 'CylinderBufferGeometry':
|
||||
|
||||
geometry = new Geometries[ data.type ](
|
||||
data.radiusTop,
|
||||
data.radiusBottom,
|
||||
data.height,
|
||||
data.radialSegments,
|
||||
data.heightSegments,
|
||||
data.openEnded,
|
||||
data.thetaStart,
|
||||
data.thetaLength
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'ConeGeometry':
|
||||
case 'ConeBufferGeometry':
|
||||
|
||||
geometry = new Geometries[ data.type ](
|
||||
data.radius,
|
||||
data.height,
|
||||
data.radialSegments,
|
||||
data.heightSegments,
|
||||
data.openEnded,
|
||||
data.thetaStart,
|
||||
data.thetaLength
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'SphereGeometry':
|
||||
case 'SphereBufferGeometry':
|
||||
|
||||
geometry = new Geometries[ data.type ](
|
||||
data.radius,
|
||||
data.widthSegments,
|
||||
data.heightSegments,
|
||||
data.phiStart,
|
||||
data.phiLength,
|
||||
data.thetaStart,
|
||||
data.thetaLength
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'DodecahedronGeometry':
|
||||
case 'DodecahedronBufferGeometry':
|
||||
case 'IcosahedronGeometry':
|
||||
case 'IcosahedronBufferGeometry':
|
||||
case 'OctahedronGeometry':
|
||||
case 'OctahedronBufferGeometry':
|
||||
case 'TetrahedronGeometry':
|
||||
case 'TetrahedronBufferGeometry':
|
||||
|
||||
geometry = new Geometries[ data.type ](
|
||||
data.radius,
|
||||
data.detail
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'RingGeometry':
|
||||
case 'RingBufferGeometry':
|
||||
|
||||
geometry = new Geometries[ data.type ](
|
||||
data.innerRadius,
|
||||
data.outerRadius,
|
||||
data.thetaSegments,
|
||||
data.phiSegments,
|
||||
data.thetaStart,
|
||||
data.thetaLength
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'TorusGeometry':
|
||||
case 'TorusBufferGeometry':
|
||||
|
||||
geometry = new Geometries[ data.type ](
|
||||
data.radius,
|
||||
data.tube,
|
||||
data.radialSegments,
|
||||
data.tubularSegments,
|
||||
data.arc
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'TorusKnotGeometry':
|
||||
case 'TorusKnotBufferGeometry':
|
||||
|
||||
geometry = new Geometries[ data.type ](
|
||||
data.radius,
|
||||
data.tube,
|
||||
data.tubularSegments,
|
||||
data.radialSegments,
|
||||
data.p,
|
||||
data.q
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'LatheGeometry':
|
||||
case 'LatheBufferGeometry':
|
||||
|
||||
geometry = new Geometries[ data.type ](
|
||||
data.points,
|
||||
data.segments,
|
||||
data.phiStart,
|
||||
data.phiLength
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'PolyhedronGeometry':
|
||||
case 'PolyhedronBufferGeometry':
|
||||
|
||||
geometry = new Geometries[ data.type ](
|
||||
data.vertices,
|
||||
data.indices,
|
||||
data.radius,
|
||||
data.details
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'ShapeGeometry':
|
||||
case 'ShapeBufferGeometry':
|
||||
|
||||
var geometryShapes = [];
|
||||
|
||||
for ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) {
|
||||
|
||||
var shape = shapes[ data.shapes[ j ] ];
|
||||
|
||||
geometryShapes.push( shape );
|
||||
|
||||
}
|
||||
|
||||
geometry = new Geometries[ data.type ](
|
||||
geometryShapes,
|
||||
data.curveSegments
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'ExtrudeGeometry':
|
||||
case 'ExtrudeBufferGeometry':
|
||||
|
||||
var geometryShapes = [];
|
||||
|
||||
for ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) {
|
||||
|
||||
var shape = shapes[ data.shapes[ j ] ];
|
||||
|
||||
geometryShapes.push( shape );
|
||||
|
||||
}
|
||||
|
||||
var extrudePath = data.options.extrudePath;
|
||||
|
||||
if ( extrudePath !== undefined ) {
|
||||
|
||||
data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );
|
||||
|
||||
}
|
||||
|
||||
geometry = new Geometries[ data.type ](
|
||||
geometryShapes,
|
||||
data.options
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'BufferGeometry':
|
||||
|
||||
geometry = bufferGeometryLoader.parse( data );
|
||||
|
||||
break;
|
||||
|
||||
case 'Geometry':
|
||||
|
||||
geometry = geometryLoader.parse( data, this.resourcePath ).geometry;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' );
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
geometry.uuid = data.uuid;
|
||||
|
||||
if ( data.name !== undefined ) geometry.name = data.name;
|
||||
if ( geometry.isBufferGeometry === true && data.userData !== undefined ) geometry.userData = data.userData;
|
||||
|
||||
geometries[ data.uuid ] = geometry;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return geometries;
|
||||
|
||||
},
|
||||
|
||||
parseMaterials: function ( json, textures ) {
|
||||
|
||||
var materials = {};
|
||||
|
||||
if ( json !== undefined ) {
|
||||
|
||||
var loader = new MaterialLoader();
|
||||
loader.setTextures( textures );
|
||||
|
||||
for ( var i = 0, l = json.length; i < l; i ++ ) {
|
||||
|
||||
var data = json[ i ];
|
||||
|
||||
if ( data.type === 'MultiMaterial' ) {
|
||||
|
||||
// Deprecated
|
||||
|
||||
var array = [];
|
||||
|
||||
for ( var j = 0; j < data.materials.length; j ++ ) {
|
||||
|
||||
array.push( loader.parse( data.materials[ j ] ) );
|
||||
|
||||
}
|
||||
|
||||
materials[ data.uuid ] = array;
|
||||
|
||||
} else {
|
||||
|
||||
materials[ data.uuid ] = loader.parse( data );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return materials;
|
||||
|
||||
},
|
||||
|
||||
parseAnimations: function ( json ) {
|
||||
|
||||
var animations = [];
|
||||
|
||||
for ( var i = 0; i < json.length; i ++ ) {
|
||||
|
||||
var data = json[ i ];
|
||||
|
||||
var clip = AnimationClip.parse( data );
|
||||
|
||||
if ( data.uuid !== undefined ) clip.uuid = data.uuid;
|
||||
|
||||
animations.push( clip );
|
||||
|
||||
}
|
||||
|
||||
return animations;
|
||||
|
||||
},
|
||||
|
||||
parseImages: function ( json, onLoad ) {
|
||||
|
||||
var scope = this;
|
||||
var images = {};
|
||||
|
||||
function loadImage( url ) {
|
||||
|
||||
scope.manager.itemStart( url );
|
||||
|
||||
return loader.load( url, function () {
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
|
||||
}, undefined, function () {
|
||||
|
||||
scope.manager.itemEnd( url );
|
||||
scope.manager.itemError( url );
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
if ( json !== undefined && json.length > 0 ) {
|
||||
|
||||
var manager = new LoadingManager( onLoad );
|
||||
|
||||
var loader = new ImageLoader( manager );
|
||||
loader.setCrossOrigin( this.crossOrigin );
|
||||
|
||||
for ( var i = 0, il = json.length; i < il; i ++ ) {
|
||||
|
||||
var image = json[ i ];
|
||||
var url = image.url;
|
||||
|
||||
if ( Array.isArray( url ) ) {
|
||||
|
||||
// load array of images e.g CubeTexture
|
||||
|
||||
images[ image.uuid ] = [];
|
||||
|
||||
for ( var j = 0, jl = url.length; j < jl; j ++ ) {
|
||||
|
||||
var currentUrl = url[ j ];
|
||||
|
||||
var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( currentUrl ) ? currentUrl : scope.resourcePath + currentUrl;
|
||||
|
||||
images[ image.uuid ].push( loadImage( path ) );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// load single image
|
||||
|
||||
var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.resourcePath + image.url;
|
||||
|
||||
images[ image.uuid ] = loadImage( path );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return images;
|
||||
|
||||
},
|
||||
|
||||
parseTextures: function ( json, images ) {
|
||||
|
||||
function parseConstant( value, type ) {
|
||||
|
||||
if ( typeof value === 'number' ) return value;
|
||||
|
||||
console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
|
||||
|
||||
return type[ value ];
|
||||
|
||||
}
|
||||
|
||||
var textures = {};
|
||||
|
||||
if ( json !== undefined ) {
|
||||
|
||||
for ( var i = 0, l = json.length; i < l; i ++ ) {
|
||||
|
||||
var data = json[ i ];
|
||||
|
||||
if ( data.image === undefined ) {
|
||||
|
||||
console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
|
||||
|
||||
}
|
||||
|
||||
if ( images[ data.image ] === undefined ) {
|
||||
|
||||
console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
|
||||
|
||||
}
|
||||
|
||||
var texture;
|
||||
|
||||
if ( Array.isArray( images[ data.image ] ) ) {
|
||||
|
||||
texture = new CubeTexture( images[ data.image ] );
|
||||
|
||||
} else {
|
||||
|
||||
texture = new Texture( images[ data.image ] );
|
||||
|
||||
}
|
||||
|
||||
texture.needsUpdate = true;
|
||||
|
||||
texture.uuid = data.uuid;
|
||||
|
||||
if ( data.name !== undefined ) texture.name = data.name;
|
||||
|
||||
if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
|
||||
|
||||
if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
|
||||
if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
|
||||
if ( data.center !== undefined ) texture.center.fromArray( data.center );
|
||||
if ( data.rotation !== undefined ) texture.rotation = data.rotation;
|
||||
|
||||
if ( data.wrap !== undefined ) {
|
||||
|
||||
texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
|
||||
texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
|
||||
|
||||
}
|
||||
|
||||
if ( data.format !== undefined ) texture.format = data.format;
|
||||
|
||||
if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
|
||||
if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
|
||||
if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
|
||||
|
||||
if ( data.flipY !== undefined ) texture.flipY = data.flipY;
|
||||
|
||||
textures[ data.uuid ] = texture;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return textures;
|
||||
|
||||
},
|
||||
|
||||
parseObject: function ( data, geometries, materials ) {
|
||||
|
||||
var object;
|
||||
|
||||
function getGeometry( name ) {
|
||||
|
||||
if ( geometries[ name ] === undefined ) {
|
||||
|
||||
console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
|
||||
|
||||
}
|
||||
|
||||
return geometries[ name ];
|
||||
|
||||
}
|
||||
|
||||
function getMaterial( name ) {
|
||||
|
||||
if ( name === undefined ) return undefined;
|
||||
|
||||
if ( Array.isArray( name ) ) {
|
||||
|
||||
var array = [];
|
||||
|
||||
for ( var i = 0, l = name.length; i < l; i ++ ) {
|
||||
|
||||
var uuid = name[ i ];
|
||||
|
||||
if ( materials[ uuid ] === undefined ) {
|
||||
|
||||
console.warn( 'THREE.ObjectLoader: Undefined material', uuid );
|
||||
|
||||
}
|
||||
|
||||
array.push( materials[ uuid ] );
|
||||
|
||||
}
|
||||
|
||||
return array;
|
||||
|
||||
}
|
||||
|
||||
if ( materials[ name ] === undefined ) {
|
||||
|
||||
console.warn( 'THREE.ObjectLoader: Undefined material', name );
|
||||
|
||||
}
|
||||
|
||||
return materials[ name ];
|
||||
|
||||
}
|
||||
|
||||
switch ( data.type ) {
|
||||
|
||||
case 'Scene':
|
||||
|
||||
object = new Scene();
|
||||
|
||||
if ( data.background !== undefined ) {
|
||||
|
||||
if ( Number.isInteger( data.background ) ) {
|
||||
|
||||
object.background = new Color( data.background );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( data.fog !== undefined ) {
|
||||
|
||||
if ( data.fog.type === 'Fog' ) {
|
||||
|
||||
object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
|
||||
|
||||
} else if ( data.fog.type === 'FogExp2' ) {
|
||||
|
||||
object.fog = new FogExp2( data.fog.color, data.fog.density );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'PerspectiveCamera':
|
||||
|
||||
object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
|
||||
|
||||
if ( data.focus !== undefined ) object.focus = data.focus;
|
||||
if ( data.zoom !== undefined ) object.zoom = data.zoom;
|
||||
if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
|
||||
if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
|
||||
if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
|
||||
|
||||
break;
|
||||
|
||||
case 'OrthographicCamera':
|
||||
|
||||
object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
|
||||
|
||||
if ( data.zoom !== undefined ) object.zoom = data.zoom;
|
||||
if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
|
||||
|
||||
break;
|
||||
|
||||
case 'AmbientLight':
|
||||
|
||||
object = new AmbientLight( data.color, data.intensity );
|
||||
|
||||
break;
|
||||
|
||||
case 'DirectionalLight':
|
||||
|
||||
object = new DirectionalLight( data.color, data.intensity );
|
||||
|
||||
break;
|
||||
|
||||
case 'PointLight':
|
||||
|
||||
object = new PointLight( data.color, data.intensity, data.distance, data.decay );
|
||||
|
||||
break;
|
||||
|
||||
case 'RectAreaLight':
|
||||
|
||||
object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
|
||||
|
||||
break;
|
||||
|
||||
case 'SpotLight':
|
||||
|
||||
object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
|
||||
|
||||
break;
|
||||
|
||||
case 'HemisphereLight':
|
||||
|
||||
object = new HemisphereLight( data.color, data.groundColor, data.intensity );
|
||||
|
||||
break;
|
||||
|
||||
case 'SkinnedMesh':
|
||||
|
||||
console.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' );
|
||||
|
||||
case 'Mesh':
|
||||
|
||||
var geometry = getGeometry( data.geometry );
|
||||
var material = getMaterial( data.material );
|
||||
|
||||
if ( geometry.bones && geometry.bones.length > 0 ) {
|
||||
|
||||
object = new SkinnedMesh( geometry, material );
|
||||
|
||||
} else {
|
||||
|
||||
object = new Mesh( geometry, material );
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'LOD':
|
||||
|
||||
object = new LOD();
|
||||
|
||||
break;
|
||||
|
||||
case 'Line':
|
||||
|
||||
object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );
|
||||
|
||||
break;
|
||||
|
||||
case 'LineLoop':
|
||||
|
||||
object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
|
||||
|
||||
break;
|
||||
|
||||
case 'LineSegments':
|
||||
|
||||
object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
|
||||
|
||||
break;
|
||||
|
||||
case 'PointCloud':
|
||||
case 'Points':
|
||||
|
||||
object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
|
||||
|
||||
break;
|
||||
|
||||
case 'Sprite':
|
||||
|
||||
object = new Sprite( getMaterial( data.material ) );
|
||||
|
||||
break;
|
||||
|
||||
case 'Group':
|
||||
|
||||
object = new Group();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
object = new Object3D();
|
||||
|
||||
}
|
||||
|
||||
object.uuid = data.uuid;
|
||||
|
||||
if ( data.name !== undefined ) object.name = data.name;
|
||||
|
||||
if ( data.matrix !== undefined ) {
|
||||
|
||||
object.matrix.fromArray( data.matrix );
|
||||
|
||||
if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
|
||||
if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
|
||||
|
||||
} else {
|
||||
|
||||
if ( data.position !== undefined ) object.position.fromArray( data.position );
|
||||
if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
|
||||
if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
|
||||
if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
|
||||
|
||||
}
|
||||
|
||||
if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
|
||||
if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
|
||||
|
||||
if ( data.shadow ) {
|
||||
|
||||
if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
|
||||
if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
|
||||
if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
|
||||
if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
|
||||
|
||||
}
|
||||
|
||||
if ( data.visible !== undefined ) object.visible = data.visible;
|
||||
if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
|
||||
if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
|
||||
if ( data.userData !== undefined ) object.userData = data.userData;
|
||||
if ( data.layers !== undefined ) object.layers.mask = data.layers;
|
||||
|
||||
if ( data.children !== undefined ) {
|
||||
|
||||
var children = data.children;
|
||||
|
||||
for ( var i = 0; i < children.length; i ++ ) {
|
||||
|
||||
object.add( this.parseObject( children[ i ], geometries, materials ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( data.type === 'LOD' ) {
|
||||
|
||||
var levels = data.levels;
|
||||
|
||||
for ( var l = 0; l < levels.length; l ++ ) {
|
||||
|
||||
var level = levels[ l ];
|
||||
var child = object.getObjectByProperty( 'uuid', level.object );
|
||||
|
||||
if ( child !== undefined ) {
|
||||
|
||||
object.addLevel( child, level.distance );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return object;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
var TEXTURE_MAPPING = {
|
||||
UVMapping: UVMapping,
|
||||
CubeReflectionMapping: CubeReflectionMapping,
|
||||
CubeRefractionMapping: CubeRefractionMapping,
|
||||
EquirectangularReflectionMapping: EquirectangularReflectionMapping,
|
||||
EquirectangularRefractionMapping: EquirectangularRefractionMapping,
|
||||
SphericalReflectionMapping: SphericalReflectionMapping,
|
||||
CubeUVReflectionMapping: CubeUVReflectionMapping,
|
||||
CubeUVRefractionMapping: CubeUVRefractionMapping
|
||||
};
|
||||
|
||||
var TEXTURE_WRAPPING = {
|
||||
RepeatWrapping: RepeatWrapping,
|
||||
ClampToEdgeWrapping: ClampToEdgeWrapping,
|
||||
MirroredRepeatWrapping: MirroredRepeatWrapping
|
||||
};
|
||||
|
||||
var TEXTURE_FILTER = {
|
||||
NearestFilter: NearestFilter,
|
||||
NearestMipMapNearestFilter: NearestMipMapNearestFilter,
|
||||
NearestMipMapLinearFilter: NearestMipMapLinearFilter,
|
||||
LinearFilter: LinearFilter,
|
||||
LinearMipMapNearestFilter: LinearMipMapNearestFilter,
|
||||
LinearMipMapLinearFilter: LinearMipMapLinearFilter
|
||||
};
|
||||
|
||||
|
||||
export { ObjectLoader };
|
68
lib/loaders/TextureLoader.js
Normal file
68
lib/loaders/TextureLoader.js
Normal file
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
import { RGBAFormat, RGBFormat } from '../constants.js';
|
||||
import { ImageLoader } from './ImageLoader.js';
|
||||
import { Texture } from '../textures/Texture.js';
|
||||
import { DefaultLoadingManager } from './LoadingManager.js';
|
||||
|
||||
|
||||
function TextureLoader( manager ) {
|
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
|
||||
|
||||
}
|
||||
|
||||
Object.assign( TextureLoader.prototype, {
|
||||
|
||||
crossOrigin: 'anonymous',
|
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) {
|
||||
|
||||
var texture = new Texture();
|
||||
|
||||
var loader = new ImageLoader( this.manager );
|
||||
loader.setCrossOrigin( this.crossOrigin );
|
||||
loader.setPath( this.path );
|
||||
|
||||
loader.load( url, function ( image ) {
|
||||
|
||||
texture.image = image;
|
||||
|
||||
// JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
|
||||
var isJPEG = url.search( /\.jpe?g$/i ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0;
|
||||
|
||||
texture.format = isJPEG ? RGBFormat : RGBAFormat;
|
||||
texture.needsUpdate = true;
|
||||
|
||||
if ( onLoad !== undefined ) {
|
||||
|
||||
onLoad( texture );
|
||||
|
||||
}
|
||||
|
||||
}, onProgress, onError );
|
||||
|
||||
return texture;
|
||||
|
||||
},
|
||||
|
||||
setCrossOrigin: function ( value ) {
|
||||
|
||||
this.crossOrigin = value;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setPath: function ( value ) {
|
||||
|
||||
this.path = value;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
|
||||
export { TextureLoader };
|
Reference in New Issue
Block a user