diff --git a/examples/js/loaders/FBXLoader.js b/examples/js/loaders/FBXLoader.js index d754fd9e8b77549da5803ae03355143f8bfa92c2..5e946cddbc6fc55a8566d07e1653dc028472e5b6 100644 --- a/examples/js/loaders/FBXLoader.js +++ b/examples/js/loaders/FBXLoader.js @@ -51,7 +51,7 @@ } catch ( error ) { - window.setTimeout( function () { + setTimeout( function () { if ( onError ) onError( error ); @@ -3448,7 +3448,7 @@ } - if ( window.Zlib === undefined ) { + if ( typeof Zlib === 'undefined' ) { console.error( 'THREE.FBXLoader: External library Inflate.min.js required, obtain or import from https://github.com/imaya/zlib.js' ); diff --git a/src/Three.Legacy.js b/src/Three.Legacy.js index 69bd7e30a58c6b095130ea51e0bcd5aad50db58f..d9e5f7d29ee08bd8f9bdf466bfa41aa42741686b 100644 --- a/src/Three.Legacy.js +++ b/src/Three.Legacy.js @@ -73,6 +73,7 @@ import { WebGLRenderer } from './renderers/WebGLRenderer.js'; import { WebGLRenderTarget } from './renderers/WebGLRenderTarget.js'; import { WebGLShadowMap } from './renderers/webgl/WebGLShadowMap.js'; import { WebVRManager } from './renderers/webvr/WebVRManager.js'; +import { ImageUtils } from './extras/ImageUtils.js'; import { Shape } from './extras/core/Shape.js'; import { CubeCamera } from './cameras/CubeCamera.js'; @@ -1757,51 +1758,47 @@ export var GeometryUtils = { }; -export var ImageUtils = { +ImageUtils.crossOrigin = undefined; - crossOrigin: undefined, +ImageUtils.loadTexture = function ( url, mapping, onLoad, onError ) { - loadTexture: function ( url, mapping, onLoad, onError ) { + console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' ); - console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' ); + var loader = new TextureLoader(); + loader.setCrossOrigin( this.crossOrigin ); - var loader = new TextureLoader(); - loader.setCrossOrigin( this.crossOrigin ); + var texture = loader.load( url, onLoad, undefined, onError ); - var texture = loader.load( url, onLoad, undefined, onError ); + if ( mapping ) texture.mapping = mapping; - if ( mapping ) texture.mapping = mapping; + return texture; - return texture; - - }, - - loadTextureCube: function ( urls, mapping, onLoad, onError ) { +}; - console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' ); +ImageUtils.loadTextureCube = function ( urls, mapping, onLoad, onError ) { - var loader = new CubeTextureLoader(); - loader.setCrossOrigin( this.crossOrigin ); + console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' ); - var texture = loader.load( urls, onLoad, undefined, onError ); + var loader = new CubeTextureLoader(); + loader.setCrossOrigin( this.crossOrigin ); - if ( mapping ) texture.mapping = mapping; + var texture = loader.load( urls, onLoad, undefined, onError ); - return texture; + if ( mapping ) texture.mapping = mapping; - }, + return texture; - loadCompressedTexture: function () { +}; - console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' ); +ImageUtils.loadCompressedTexture = function () { - }, + console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' ); - loadCompressedTextureCube: function () { +}; - console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' ); +ImageUtils.loadCompressedTextureCube = function () { - } + console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' ); }; diff --git a/src/Three.js b/src/Three.js index f4e620c68107caacd422ae602935cc482e275493..4f38ef146fc6f85ced89e32932abe6b8121a2b4f 100644 --- a/src/Three.js +++ b/src/Three.js @@ -145,6 +145,7 @@ export { ShapePath } from './extras/core/ShapePath.js'; export { Font } from './extras/core/Font.js'; export { CurvePath } from './extras/core/CurvePath.js'; export { Curve } from './extras/core/Curve.js'; +export { ImageUtils } from './extras/ImageUtils.js'; export { ShapeUtils } from './extras/ShapeUtils.js'; export { WebGLUtils } from './renderers/webgl/WebGLUtils.js'; export * from './constants.js'; diff --git a/src/extras/ImageUtils.js b/src/extras/ImageUtils.js new file mode 100644 index 0000000000000000000000000000000000000000..dfb56756fae58565bd1a165ac101bdb6a3200569 --- /dev/null +++ b/src/extras/ImageUtils.js @@ -0,0 +1,59 @@ +/** + * @author mrdoob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + * @author szimek / https://github.com/szimek/ + */ + +var ImageUtils = { + + getDataURL: function ( image ) { + + var canvas; + + if ( image instanceof HTMLCanvasElement ) { + + canvas = image; + + } else { + + if ( typeof OffscreenCanvas !== 'undefined' ) { + + canvas = new OffscreenCanvas( image.width, image.height ); + + } else { + + canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); + canvas.width = image.width; + canvas.height = image.height; + + } + + var context = canvas.getContext( '2d' ); + + if ( image instanceof ImageData ) { + + context.putImageData( image, 0, 0 ); + + } else { + + context.drawImage( image, 0, 0, image.width, image.height ); + + } + + } + + if ( canvas.width > 2048 || canvas.height > 2048 ) { + + return canvas.toDataURL( 'image/jpeg', 0.6 ); + + } else { + + return canvas.toDataURL( 'image/png' ); + + } + + } + +}; + +export { ImageUtils }; diff --git a/src/textures/Texture.js b/src/textures/Texture.js index ca6992171195a175dfd23b825553e21761343301..9bc48577e1e338b280d072be199f7bfca4a32533 100644 --- a/src/textures/Texture.js +++ b/src/textures/Texture.js @@ -10,6 +10,7 @@ import { MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, LinearEnco import { _Math } from '../math/Math.js'; import { Vector2 } from '../math/Vector2.js'; import { Matrix3 } from '../math/Matrix3.js'; +import { ImageUtils } from '../extras/ImageUtils.js'; var textureId = 0; @@ -130,46 +131,6 @@ Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { } - function getDataURL( image ) { - - var canvas; - - if ( image instanceof HTMLCanvasElement ) { - - canvas = image; - - } else { - - canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = image.width; - canvas.height = image.height; - - var context = canvas.getContext( '2d' ); - - if ( image instanceof ImageData ) { - - context.putImageData( image, 0, 0 ); - - } else { - - context.drawImage( image, 0, 0, image.width, image.height ); - - } - - } - - if ( canvas.width > 2048 || canvas.height > 2048 ) { - - return canvas.toDataURL( 'image/jpeg', 0.6 ); - - } else { - - return canvas.toDataURL( 'image/png' ); - - } - - } - var output = { metadata: { @@ -223,7 +184,7 @@ Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { for ( var i = 0, l = image.length; i < l; i ++ ) { - url.push( getDataURL( image[ i ] ) ); + url.push( ImageUtils.getDataURL( image[ i ] ) ); } @@ -231,7 +192,7 @@ Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { // process single image - url = getDataURL( image ); + url = ImageUtils.getDataURL( image ); } diff --git a/utils/converters/README.md b/utils/converters/README.md index d692ee78ba8a3aea2332a0bc8e864aa848588550..fe819b864cf8b879f6feb29526129104e3547e98 100644 --- a/utils/converters/README.md +++ b/utils/converters/README.md @@ -7,3 +7,11 @@ Usage: ``` node obj2three.js model.obj ``` + +## fbx2three.js + +Usage: + +``` +node fbx2three.js model.fbx +``` diff --git a/utils/converters/fbx2three.js b/utils/converters/fbx2three.js new file mode 100644 index 0000000000000000000000000000000000000000..72300aa910fc0c87b25e3aafb7d2460ff124f1d0 --- /dev/null +++ b/utils/converters/fbx2three.js @@ -0,0 +1,80 @@ +var fs = require( 'fs' ); +var path = require( 'path' ); + +if ( process.argv.length <= 2 ) { + + console.log( `Usage: ${path.basename( __filename )} model.fbx` ); + process.exit( - 1 ); + +} + +// + +var PRECISION = 6; + +function parseNumber( key, value ) { + + return typeof value === 'number' ? parseFloat( value.toFixed( PRECISION ) ) : value; + +} + +THREE = require( '../../build/three.js' ); +require( '../../examples/js/curves/NURBSCurve.js' ); +require( '../../examples/js/curves/NURBSUtils.js' ); +require( '../../examples/js/loaders/FBXLoader.js' ); +global.Zlib = require( '../../examples/js/libs/inflate.min.js' ).Zlib; + +global.window = { + innerWidth: 1024, + innerHeight: 768, + URL: { + createObjectURL: function () { + throw new Error( 'fbx2three: Images in binary format not yet supported.' ); + } + } +}; + +// HTML Images are not available, so use a Buffer instead. +THREE.ImageLoader.prototype.load = function ( url, onLoad ) { + + if ( this.path !== undefined ) url = this.path + url; + + // If image isn't found, try to ignore it. + if ( !fs.existsSync( url ) ) { + + onLoad( new Buffer( '' ) ); + return; + + } + + onLoad( fs.readFileSync( url ) ); + +}; + +// Convert image buffer to data URL. +THREE.ImageUtils.getDataURL = function ( image ) { + + if ( !( image instanceof Buffer ) ) { + + throw new Error( 'fbx2three: Image should be loaded as Buffer.' ); + + } + + var dataURL = 'data:'; + dataURL += this.format === THREE.RGBAFormat ? 'image/png' : 'image/jpeg'; + dataURL += ';base64,'; + dataURL += image.toString( 'base64' ); + return dataURL; + +}; + +// + +var file = process.argv[ 2 ]; +var resourceDirectory = THREE.LoaderUtils.extractUrlBase( file ); +var loader = new THREE.FBXLoader(); + +var arraybuffer = fs.readFileSync( file ).buffer; +var object = loader.parse( arraybuffer, resourceDirectory ); +var content = JSON.stringify( object.toJSON(), parseNumber ); +fs.writeFileSync( path.basename( file, '.fbx' ) + '.json', content, 'utf8' );