Browse Source

Merge pull request #13013 from donmccurdy/feat-fbx2three

fbx2three: Create Node.js fbx2three converter.
Mr.doob 7 years ago
parent
commit
b4908d2aa5

+ 2 - 2
examples/js/loaders/FBXLoader.js

@@ -51,7 +51,7 @@
 
 
 				} catch ( error ) {
 				} catch ( error ) {
 
 
-					window.setTimeout( function () {
+					setTimeout( function () {
 
 
 						if ( onError ) onError( error );
 						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' );
 						console.error( 'THREE.FBXLoader: External library Inflate.min.js required, obtain or import from https://github.com/imaya/zlib.js' );
 
 

+ 23 - 26
src/Three.Legacy.js

@@ -73,6 +73,7 @@ import { WebGLRenderer } from './renderers/WebGLRenderer.js';
 import { WebGLRenderTarget } from './renderers/WebGLRenderTarget.js';
 import { WebGLRenderTarget } from './renderers/WebGLRenderTarget.js';
 import { WebGLShadowMap } from './renderers/webgl/WebGLShadowMap.js';
 import { WebGLShadowMap } from './renderers/webgl/WebGLShadowMap.js';
 import { WebVRManager } from './renderers/webvr/WebVRManager.js';
 import { WebVRManager } from './renderers/webvr/WebVRManager.js';
+import { ImageUtils } from './extras/ImageUtils.js';
 import { Shape } from './extras/core/Shape.js';
 import { Shape } from './extras/core/Shape.js';
 import { CubeCamera } from './cameras/CubeCamera.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.' );
 
 
 };
 };
 
 

+ 1 - 0
src/Three.js

@@ -145,6 +145,7 @@ export { ShapePath } from './extras/core/ShapePath.js';
 export { Font } from './extras/core/Font.js';
 export { Font } from './extras/core/Font.js';
 export { CurvePath } from './extras/core/CurvePath.js';
 export { CurvePath } from './extras/core/CurvePath.js';
 export { Curve } from './extras/core/Curve.js';
 export { Curve } from './extras/core/Curve.js';
+export { ImageUtils } from './extras/ImageUtils.js';
 export { ShapeUtils } from './extras/ShapeUtils.js';
 export { ShapeUtils } from './extras/ShapeUtils.js';
 export { WebGLUtils } from './renderers/webgl/WebGLUtils.js';
 export { WebGLUtils } from './renderers/webgl/WebGLUtils.js';
 export * from './constants.js';
 export * from './constants.js';

+ 59 - 0
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 };

+ 3 - 42
src/textures/Texture.js

@@ -10,6 +10,7 @@ import { MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, LinearEnco
 import { _Math } from '../math/Math.js';
 import { _Math } from '../math/Math.js';
 import { Vector2 } from '../math/Vector2.js';
 import { Vector2 } from '../math/Vector2.js';
 import { Matrix3 } from '../math/Matrix3.js';
 import { Matrix3 } from '../math/Matrix3.js';
+import { ImageUtils } from '../extras/ImageUtils.js';
 
 
 var textureId = 0;
 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 = {
 		var output = {
 
 
 			metadata: {
 			metadata: {
@@ -223,7 +184,7 @@ Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
 
 
 					for ( var i = 0, l = image.length; i < l; i ++ ) {
 					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
 					// process single image
 
 
-					url = getDataURL( image );
+					url = ImageUtils.getDataURL( image );
 
 
 				}
 				}
 
 

+ 8 - 0
utils/converters/README.md

@@ -7,3 +7,11 @@ Usage:
 ```
 ```
 node obj2three.js model.obj
 node obj2three.js model.obj
 ```
 ```
+
+## fbx2three.js
+
+Usage:
+
+```
+node fbx2three.js model.fbx
+```

+ 80 - 0
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' );