Browse Source

Merge remote-tracking branch 'upstream/dev'

zz85 14 years ago
parent
commit
0f9c3f44ee

+ 4 - 0
build/Three.js

@@ -426,6 +426,10 @@ this.getPrevKeyWith("pos",w,m.index-1).pos,this.points[1]=h,this.points[2]=k,thi
 THREE.Animation.prototype.interpolateCatmullRom=function(b,c){var e=[],f=[],h,k,m,n,p,u;h=(b.length-1)*c;k=Math.floor(h);h-=k;e[0]=k==0?k:k-1;e[1]=k;e[2]=k>b.length-2?k:k+1;e[3]=k>b.length-3?k:k+2;k=b[e[0]];n=b[e[1]];p=b[e[2]];u=b[e[3]];e=h*h;m=h*e;f[0]=this.interpolate(k[0],n[0],p[0],u[0],h,e,m);f[1]=this.interpolate(k[1],n[1],p[1],u[1],h,e,m);f[2]=this.interpolate(k[2],n[2],p[2],u[2],h,e,m);return f};
 THREE.Animation.prototype.interpolate=function(b,c,e,f,h,k,m){b=(e-b)*0.5;f=(f-c)*0.5;return(2*(c-e)+b+f)*m+(-3*(c-e)-2*b-f)*k+b*h+c};THREE.Animation.prototype.getNextKeyWith=function(b,c,e){var f=this.data.hierarchy[c].keys;for(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?e=e<f.length-1?e:f.length-1:e%=f.length;e<f.length;e++)if(f[e][b]!==void 0)return f[e];return this.data.hierarchy[c].keys[0]};
 THREE.Animation.prototype.getPrevKeyWith=function(b,c,e){for(var f=this.data.hierarchy[c].keys,e=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?e>0?e:0:e>=0?e:e+f.length;e>=0;e--)if(f[e][b]!==void 0)return f[e];return this.data.hierarchy[c].keys[f.length-1]};
+THREE.CubeCamera=function(b,c,e,f){this.cameraPX=new THREE.Camera(90,1,b,c);this.cameraNX=new THREE.Camera(90,1,b,c);this.cameraPY=new THREE.Camera(90,1,b,c);this.cameraNY=new THREE.Camera(90,1,b,c);this.cameraPZ=new THREE.Camera(90,1,b,c);this.cameraNZ=new THREE.Camera(90,1,b,c);this.height=e;this.position=new THREE.Vector3(0,e,0);this.cameraPX.position=this.position;this.cameraNX.position=this.position;this.cameraPY.position=this.position;this.cameraNY.position=this.position;this.cameraPZ.position=
+this.position;this.cameraNZ.position=this.position;this.cameraPY.up.set(0,0,1);this.cameraPZ.up.set(0,-1,0);this.cameraNZ.up.set(0,-1,0);this.renderTarget=new THREE.WebGLRenderTargetCube(f,f,{format:THREE.RGBFormat,magFilter:THREE.LinearFilter,minFilter:THREE.LinearFilter});this.updatePosition=function(b){this.position.x=b.x;this.position.z=b.z;this.cameraPX.target.position.add(this.position,new THREE.Vector3(-1,0,0));this.cameraNX.target.position.add(this.position,new THREE.Vector3(1,0,0));this.cameraPY.target.position.add(this.position,
+new THREE.Vector3(0,1,0));this.cameraNY.target.position.add(this.position,new THREE.Vector3(0,-1,0));this.cameraPZ.target.position.add(this.position,new THREE.Vector3(0,0,1));this.cameraNZ.target.position.add(this.position,new THREE.Vector3(0,0,-1))};this.updateCubeMap=function(b,e){var c=this.renderTarget;b.setFaceCulling("back","cw");e.scale.y=-1;e.position.y=2*this.height;e.updateMatrix();c.activeCubeFace=0;b.render(e,this.cameraPX,c);c.activeCubeFace=1;b.render(e,this.cameraNX,c);e.scale.y=1;
+e.position.y=0;e.updateMatrix();e.scale.x=-1;e.updateMatrix();c.activeCubeFace=2;b.render(e,this.cameraPY,c);e.scale.x=1;e.updateMatrix();b.setFaceCulling("back","ccw");c.activeCubeFace=3;b.render(e,this.cameraNY,c);e.scale.x=-1;e.updateMatrix();b.setFaceCulling("back","cw");c.activeCubeFace=4;b.render(e,this.cameraPZ,c);c.activeCubeFace=5;b.render(e,this.cameraNZ,c);e.scale.x=1;e.updateMatrix();b.setFaceCulling("back","ccw")}};
 THREE.FirstPersonCamera=function(b){function c(b,c){return function(){c.apply(b,arguments)}}THREE.Camera.call(this,b.fov,b.aspect,b.near,b.far,b.target);this.movementSpeed=1;this.lookSpeed=0.0050;this.noFly=!1;this.lookVertical=!0;this.autoForward=!1;this.activeLook=!0;this.heightSpeed=!1;this.heightCoef=1;this.heightMin=0;this.constrainVertical=!1;this.verticalMin=0;this.verticalMax=Math.PI;this.domElement=document;this.lastUpdate=(new Date).getTime();this.tdiff=0;if(b){if(b.movementSpeed!==void 0)this.movementSpeed=
 b.movementSpeed;if(b.lookSpeed!==void 0)this.lookSpeed=b.lookSpeed;if(b.noFly!==void 0)this.noFly=b.noFly;if(b.lookVertical!==void 0)this.lookVertical=b.lookVertical;if(b.autoForward!==void 0)this.autoForward=b.autoForward;if(b.activeLook!==void 0)this.activeLook=b.activeLook;if(b.heightSpeed!==void 0)this.heightSpeed=b.heightSpeed;if(b.heightCoef!==void 0)this.heightCoef=b.heightCoef;if(b.heightMin!==void 0)this.heightMin=b.heightMin;if(b.heightMax!==void 0)this.heightMax=b.heightMax;if(b.constrainVertical!==
 void 0)this.constrainVertical=b.constrainVertical;if(b.verticalMin!==void 0)this.verticalMin=b.verticalMin;if(b.verticalMax!==void 0)this.verticalMax=b.verticalMax;if(b.domElement!==void 0)this.domElement=b.domElement}this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX=this.autoSpeedFactor=0;this.mouseDragOn=this.freeze=this.moveRight=this.moveLeft=this.moveBackward=this.moveForward=!1;this.domElement===document?(this.viewHalfX=window.innerWidth/2,this.viewHalfY=window.innerHeight/2):(this.viewHalfX=

+ 4 - 0
build/custom/ThreeExtras.js

@@ -81,6 +81,10 @@ this.getPrevKeyWith("pos",p,f.index-1).pos,this.points[1]=g,this.points[2]=h,thi
 THREE.Animation.prototype.interpolateCatmullRom=function(a,b){var c=[],e=[],g,h,f,k,l,m;g=(a.length-1)*b;h=Math.floor(g);g-=h;c[0]=h==0?h:h-1;c[1]=h;c[2]=h>a.length-2?h:h+1;c[3]=h>a.length-3?h:h+2;h=a[c[0]];k=a[c[1]];l=a[c[2]];m=a[c[3]];c=g*g;f=g*c;e[0]=this.interpolate(h[0],k[0],l[0],m[0],g,c,f);e[1]=this.interpolate(h[1],k[1],l[1],m[1],g,c,f);e[2]=this.interpolate(h[2],k[2],l[2],m[2],g,c,f);return e};
 THREE.Animation.prototype.interpolate=function(a,b,c,e,g,h,f){a=(c-a)*0.5;e=(e-b)*0.5;return(2*(b-c)+a+e)*f+(-3*(b-c)-2*a-e)*h+a*g+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){var e=this.data.hierarchy[b].keys;for(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c=c<e.length-1?c:e.length-1:c%=e.length;c<e.length;c++)if(e[c][a]!==void 0)return e[c];return this.data.hierarchy[b].keys[0]};
 THREE.Animation.prototype.getPrevKeyWith=function(a,b,c){for(var e=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c>0?c:0:c>=0?c:c+e.length;c>=0;c--)if(e[c][a]!==void 0)return e[c];return this.data.hierarchy[b].keys[e.length-1]};
+THREE.CubeCamera=function(a,b,c,e){this.cameraPX=new THREE.Camera(90,1,a,b);this.cameraNX=new THREE.Camera(90,1,a,b);this.cameraPY=new THREE.Camera(90,1,a,b);this.cameraNY=new THREE.Camera(90,1,a,b);this.cameraPZ=new THREE.Camera(90,1,a,b);this.cameraNZ=new THREE.Camera(90,1,a,b);this.height=c;this.position=new THREE.Vector3(0,c,0);this.cameraPX.position=this.position;this.cameraNX.position=this.position;this.cameraPY.position=this.position;this.cameraNY.position=this.position;this.cameraPZ.position=
+this.position;this.cameraNZ.position=this.position;this.cameraPY.up.set(0,0,1);this.cameraPZ.up.set(0,-1,0);this.cameraNZ.up.set(0,-1,0);this.renderTarget=new THREE.WebGLRenderTargetCube(e,e,{format:THREE.RGBFormat,magFilter:THREE.LinearFilter,minFilter:THREE.LinearFilter});this.updatePosition=function(a){this.position.x=a.x;this.position.z=a.z;this.cameraPX.target.position.add(this.position,new THREE.Vector3(-1,0,0));this.cameraNX.target.position.add(this.position,new THREE.Vector3(1,0,0));this.cameraPY.target.position.add(this.position,
+new THREE.Vector3(0,1,0));this.cameraNY.target.position.add(this.position,new THREE.Vector3(0,-1,0));this.cameraPZ.target.position.add(this.position,new THREE.Vector3(0,0,1));this.cameraNZ.target.position.add(this.position,new THREE.Vector3(0,0,-1))};this.updateCubeMap=function(a,c){var b=this.renderTarget;a.setFaceCulling("back","cw");c.scale.y=-1;c.position.y=2*this.height;c.updateMatrix();b.activeCubeFace=0;a.render(c,this.cameraPX,b);b.activeCubeFace=1;a.render(c,this.cameraNX,b);c.scale.y=1;
+c.position.y=0;c.updateMatrix();c.scale.x=-1;c.updateMatrix();b.activeCubeFace=2;a.render(c,this.cameraPY,b);c.scale.x=1;c.updateMatrix();a.setFaceCulling("back","ccw");b.activeCubeFace=3;a.render(c,this.cameraNY,b);c.scale.x=-1;c.updateMatrix();a.setFaceCulling("back","cw");b.activeCubeFace=4;a.render(c,this.cameraPZ,b);b.activeCubeFace=5;a.render(c,this.cameraNZ,b);c.scale.x=1;c.updateMatrix();a.setFaceCulling("back","ccw")}};
 THREE.FirstPersonCamera=function(a){function b(a,b){return function(){b.apply(a,arguments)}}THREE.Camera.call(this,a.fov,a.aspect,a.near,a.far,a.target);this.movementSpeed=1;this.lookSpeed=0.0050;this.noFly=!1;this.lookVertical=!0;this.autoForward=!1;this.activeLook=!0;this.heightSpeed=!1;this.heightCoef=1;this.heightMin=0;this.constrainVertical=!1;this.verticalMin=0;this.verticalMax=Math.PI;this.domElement=document;this.lastUpdate=(new Date).getTime();this.tdiff=0;if(a){if(a.movementSpeed!==void 0)this.movementSpeed=
 a.movementSpeed;if(a.lookSpeed!==void 0)this.lookSpeed=a.lookSpeed;if(a.noFly!==void 0)this.noFly=a.noFly;if(a.lookVertical!==void 0)this.lookVertical=a.lookVertical;if(a.autoForward!==void 0)this.autoForward=a.autoForward;if(a.activeLook!==void 0)this.activeLook=a.activeLook;if(a.heightSpeed!==void 0)this.heightSpeed=a.heightSpeed;if(a.heightCoef!==void 0)this.heightCoef=a.heightCoef;if(a.heightMin!==void 0)this.heightMin=a.heightMin;if(a.heightMax!==void 0)this.heightMax=a.heightMax;if(a.constrainVertical!==
 void 0)this.constrainVertical=a.constrainVertical;if(a.verticalMin!==void 0)this.verticalMin=a.verticalMin;if(a.verticalMax!==void 0)this.verticalMax=a.verticalMax;if(a.domElement!==void 0)this.domElement=a.domElement}this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX=this.autoSpeedFactor=0;this.mouseDragOn=this.freeze=this.moveRight=this.moveLeft=this.moveBackward=this.moveForward=!1;this.domElement===document?(this.viewHalfX=window.innerWidth/2,this.viewHalfY=window.innerHeight/2):(this.viewHalfX=

+ 371 - 0
examples/js/Car.js

@@ -0,0 +1,371 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.Car = function () {
+
+	var scope = this;
+
+	// car geometry manual parameters
+
+	this.modelScale = 1;
+
+	this.backWheelOffset = 2;
+
+	this.autoWheelGeometry = true;
+
+	// car geometry parameters automatically set from wheel mesh
+	// 	- assumes wheel mesh is front left wheel in proper global
+	//    position with respect to body mesh
+	//	- other wheels are mirrored against car root
+	//	- if necessary back wheels can be offset manually
+
+	this.wheelOffsetX = 0;
+	this.wheelOffsetY = 0;
+	this.wheelOffsetZ = 0;
+
+	this.wheelDiameter = 1;
+
+	// car "feel" parameters
+
+	this.MAX_SPEED = 2200;
+	this.MAX_REVERSE_SPEED = -1500;
+
+	this.MAX_WHEEL_ROTATION = 0.6;
+
+	this.FRONT_ACCELERATION = 1250;
+	this.BACK_ACCELERATION = 1500;
+
+	this.WHEEL_ANGULAR_ACCELERATION = 1.5;
+
+	this.FRONT_DECCELERATION = 750;
+	this.WHEEL_ANGULAR_DECCELERATION = 1.0;
+
+	this.STEERING_RADIUS_RATIO = 0.0023;
+
+	this.MAX_TILT_SIDES = 0.05;
+	this.MAX_TILT_FRONTBACK = 0.015;
+
+	// internal control variables
+
+	this.speed = 0;
+	this.acceleration = 0;
+
+	this.wheelOrientation = 0;
+	this.carOrientation = 0;
+
+	// car rigging
+
+	this.root = new THREE.Object3D();
+
+	this.frontLeftWheelRoot = new THREE.Object3D();
+	this.frontRightWheelRoot = new THREE.Object3D();
+
+	this.bodyMesh = null;
+
+	this.frontLeftWheelMesh = null;
+	this.frontRightWheelMesh = null;
+
+	this.backLeftWheelMesh = null;
+	this.backRightWheelMesh = null;
+
+	this.bodyGeometry = null;
+	this.wheelGeometry = null;
+
+	// internal helper variables
+
+	this.loaded = false;
+
+	this.meshes = [];
+
+	// API
+
+	this.enableShadows = function ( enable ) {
+
+		for ( var i = 0; i < this.meshes.length; i ++ ) {
+
+			this.meshes[ i ].castShadow = enable;
+			this.meshes[ i ].receiveShadow = enable;
+
+		}
+
+	};
+
+	this.setVisible = function ( enable ) {
+
+		for ( var i = 0; i < this.meshes.length; i ++ ) {
+
+			this.meshes[ i ].visible = enable;
+			this.meshes[ i ].visible = enable;
+
+		}
+
+	};
+
+	this.loadPartsJSON = function ( bodyURL, wheelURL ) {
+
+		var loader = new THREE.JSONLoader();
+
+		loader.load( { model: bodyURL, callback: function( geometry ) { createBody( geometry ) } } );
+		loader.load( { model: wheelURL, callback: function( geometry ) { createWheels( geometry ) } } );
+
+	};
+
+	this.loadPartsBinary = function ( bodyURL, wheelURL ) {
+
+		var loader = new THREE.BinaryLoader();
+
+		loader.load( { model: bodyURL, callback: function( geometry ) { createBody( geometry ) } } );
+		loader.load( { model: wheelURL, callback: function( geometry ) { createWheels( geometry ) } } );
+
+	};
+
+	this.updateCarModel = function ( delta, controls ) {
+
+		// speed and wheels based on controls
+
+		if ( controls.moveForward ) {
+
+			this.speed = clamp( this.speed + delta * this.FRONT_ACCELERATION, this.MAX_REVERSE_SPEED, this.MAX_SPEED );
+			this.acceleration = clamp( this.acceleration + delta, -1, 1 );
+
+		}
+
+		if ( controls.moveBackward ) {
+
+
+			this.speed = clamp( this.speed - delta * this.BACK_ACCELERATION, this.MAX_REVERSE_SPEED, this.MAX_SPEED );
+			this.acceleration = clamp( this.acceleration - delta, -1, 1 );
+
+		}
+
+		if ( controls.moveLeft ) {
+
+			this.wheelOrientation = clamp( this.wheelOrientation + delta * this.WHEEL_ANGULAR_ACCELERATION, - this.MAX_WHEEL_ROTATION, this.MAX_WHEEL_ROTATION );
+
+		}
+
+		if ( controls.moveRight ) {
+
+			this.wheelOrientation = clamp( this.wheelOrientation - delta * this.WHEEL_ANGULAR_ACCELERATION, - this.MAX_WHEEL_ROTATION, this.MAX_WHEEL_ROTATION );
+
+		}
+
+		// speed decay
+
+		if ( ! ( controls.moveForward || controls.moveBackward ) ) {
+
+			if ( this.speed > 0 ) {
+
+				var k = exponentialEaseOut( this.speed / this.MAX_SPEED );
+
+				this.speed = clamp( this.speed - k * delta * this.FRONT_DECCELERATION, 0, this.MAX_SPEED );
+				this.acceleration = clamp( this.acceleration - k * delta, 0, 1 );
+
+			} else {
+
+				var k = exponentialEaseOut( this.speed / this.MAX_REVERSE_SPEED );
+
+				this.speed = clamp( this.speed + k * delta * this.BACK_ACCELERATION, this.MAX_REVERSE_SPEED, 0 );
+				this.acceleration = clamp( this.acceleration + k * delta, -1, 0 );
+
+			}
+
+
+		}
+
+		// steering decay
+
+		if ( ! ( controls.moveLeft || controls.moveRight ) ) {
+
+			if ( this.wheelOrientation > 0 ) {
+
+				this.wheelOrientation = clamp( this.wheelOrientation - delta * this.WHEEL_ANGULAR_DECCELERATION, 0, this.MAX_WHEEL_ROTATION );
+
+			} else {
+
+				this.wheelOrientation = clamp( this.wheelOrientation + delta * this.WHEEL_ANGULAR_DECCELERATION, - this.MAX_WHEEL_ROTATION, 0 );
+
+			}
+
+		}
+
+		// car update
+
+		var forwardDelta = this.speed * delta;
+
+		this.carOrientation += ( forwardDelta * this.STEERING_RADIUS_RATIO )* this.wheelOrientation;
+
+		// displacement
+
+		this.root.position.x += Math.sin( this.carOrientation ) * forwardDelta;
+		this.root.position.z += Math.cos( this.carOrientation ) * forwardDelta;
+
+		// steering
+
+		this.root.rotation.y = this.carOrientation;
+
+		// tilt
+
+		if ( this.loaded ) {
+
+			this.bodyMesh.rotation.z = this.MAX_TILT_SIDES * this.wheelOrientation * ( this.speed / this.MAX_SPEED );
+			this.bodyMesh.rotation.x = - this.MAX_TILT_FRONTBACK * this.acceleration;
+
+		}
+
+		// wheels rolling
+
+		var angularSpeedRatio = 1 / ( this.modelScale * ( this.wheelDiameter / 2 ) );
+
+		var wheelDelta = forwardDelta * angularSpeedRatio;
+
+		if ( this.loaded ) {
+
+			this.frontLeftWheelMesh.rotation.x += wheelDelta;
+			this.frontRightWheelMesh.rotation.x += wheelDelta;
+			this.backLeftWheelMesh.rotation.x += wheelDelta;
+			this.backRightWheelMesh.rotation.x += wheelDelta;
+
+		}
+
+		// front wheels steering
+
+		this.frontLeftWheelRoot.rotation.y = this.wheelOrientation;
+		this.frontRightWheelRoot.rotation.y = this.wheelOrientation;
+
+	};
+
+	// internal helper methods
+
+	function createBody ( geometry ) {
+
+		scope.bodyGeometry = geometry;
+
+		createCar();
+
+	};
+
+	function createWheels ( geometry ) {
+
+		scope.wheelGeometry = geometry;
+
+		createCar();
+
+	};
+
+	function createCar () {
+
+		if ( scope.bodyGeometry && scope.wheelGeometry ) {
+
+			// compute wheel geometry parameters
+
+			if ( scope.autoWheelGeometry ) {
+
+				scope.wheelGeometry.computeBoundingBox();
+
+				var bb = scope.wheelGeometry.boundingBox;
+
+				var dx = 0.5 * ( bb.x[ 1 ] + bb.x[ 0 ] );
+				var dy = 0.5 * ( bb.y[ 1 ] + bb.y[ 0 ] );
+				var dz = 0.5 * ( bb.z[ 1 ] + bb.z[ 0 ] );
+
+				scope.wheelOffsetX = dx;
+				scope.wheelOffsetY = dy;
+				scope.wheelOffsetZ = dz;
+
+				scope.wheelDiameter = bb.y[ 1 ] - bb.y[ 0 ];
+
+				THREE.GeometryUtils.center( scope.wheelGeometry );
+
+			}
+
+			// rig the car
+
+			var delta,
+				s = scope.modelScale,
+				faceMaterial = new THREE.MeshFaceMaterial();
+
+			// body
+
+			scope.bodyMesh = new THREE.Mesh( scope.bodyGeometry, faceMaterial );
+			scope.bodyMesh.scale.set( s, s, s );
+
+			scope.root.add( scope.bodyMesh );
+
+			// front left wheel
+
+			delta = new THREE.Vector3( s * scope.wheelOffsetX, s * scope.wheelOffsetY, s * scope.wheelOffsetZ );
+
+			scope.frontLeftWheelRoot.position.addSelf( delta );
+
+			scope.frontLeftWheelMesh = new THREE.Mesh( scope.wheelGeometry, faceMaterial );
+			scope.frontLeftWheelMesh.scale.set( s, s, s );
+
+			scope.frontLeftWheelRoot.add( scope.frontLeftWheelMesh );
+			scope.root.add( scope.frontLeftWheelRoot );
+
+			// front right wheel
+
+			delta = new THREE.Vector3( -s * scope.wheelOffsetX, s * scope.wheelOffsetY, s * scope.wheelOffsetZ );
+
+			scope.frontRightWheelRoot.position.addSelf( delta );
+
+			scope.frontRightWheelMesh = new THREE.Mesh( scope.wheelGeometry, faceMaterial );
+
+			scope.frontRightWheelMesh.scale.set( s, s, s );
+			scope.frontRightWheelMesh.rotation.z = Math.PI;
+
+			scope.frontRightWheelRoot.add( scope.frontRightWheelMesh );
+			scope.root.add( scope.frontRightWheelRoot );
+
+			// back left wheel
+
+			delta = new THREE.Vector3( s * scope.wheelOffsetX, s * scope.wheelOffsetY, - s * scope.wheelOffsetZ - scope.backWheelOffset );
+
+			scope.backLeftWheelMesh = new THREE.Mesh( scope.wheelGeometry, faceMaterial );
+
+			scope.backLeftWheelMesh.position.addSelf( delta );
+			scope.backLeftWheelMesh.scale.set( s, s, s );
+
+			scope.root.add( scope.backLeftWheelMesh );
+
+			// back right wheel
+
+			delta = new THREE.Vector3( -s * scope.wheelOffsetX, s * scope.wheelOffsetY, - s * scope.wheelOffsetZ - scope.backWheelOffset )
+
+			scope.backRightWheelMesh = new THREE.Mesh( scope.wheelGeometry, faceMaterial );
+
+			scope.backRightWheelMesh.position.addSelf( delta );
+			scope.backRightWheelMesh.scale.set( s, s, s );
+			scope.backRightWheelMesh.rotation.z = Math.PI;
+
+			scope.root.add( scope.backRightWheelMesh );
+
+			// cache meshes
+
+			scope.meshes = [ scope.bodyMesh, scope.frontLeftWheelMesh, scope.frontRightWheelMesh, scope.backLeftWheelMesh, scope.backRightWheelMesh ];
+
+			// callback
+
+			scope.loaded = true;
+
+			if ( scope.callback ) {
+
+				scope.callback( scope );
+
+			}
+
+		}
+
+	};
+
+	function clamp( x, a, b ) { return x < a ? a : ( x > b ? b : x ); }
+
+	function quadraticEaseOut( k ) { return - k * ( k - 2 ); }
+	function cubicEaseOut( k ) { return --k * k * k + 1; }
+	function circularEaseOut( k ) { return Math.sqrt( 1 - --k * k ); }
+	function sinusoidalEaseOut( k ) { return Math.sin( k * Math.PI / 2 ); }
+	function exponentialEaseOut( k ) { return k == 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1; }
+
+};

+ 97 - 0
examples/js/ShaderExtras.js

@@ -19,6 +19,7 @@
  *  horizontalBlur + verticalBlur
  *  horizontalTiltShift + verticalTiltShift
  *  blend
+ *  fxaa
  */
 
 THREE.ShaderExtras = {
@@ -1134,6 +1135,102 @@ THREE.ShaderExtras = {
 
 	},
 
+	/* -------------------------------------------------------------------------
+	//	NVIDIA FXAA by Timothy Lottes
+	//		http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html
+	//	- WebGL port by @supereggbert
+	//		http://www.glge.org/demos/fxaa/
+	 ------------------------------------------------------------------------- */
+
+	'fxaa': {
+
+		uniforms: {
+
+			"tDiffuse": 	{ type: "t", value: 0, texture: null },
+			"resolution": 	{ type: "v2", value: new THREE.Vector2( 1 / 1024, 1 / 512 )  }
+
+		},
+
+		vertexShader: [
+
+			"varying vec2 vUv;",
+
+			"void main() {",
+
+				"vUv = vec2( uv.x, 1.0 - uv.y );",
+
+				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+			"}"
+
+		].join("\n"),
+
+		fragmentShader: [
+
+			"uniform sampler2D tDiffuse;",
+			"uniform vec2 resolution;",
+
+			"varying vec2 vUv;",
+
+			"#define FXAA_REDUCE_MIN   (1.0/128.0)",
+			"#define FXAA_REDUCE_MUL   (1.0/8.0)",
+			"#define FXAA_SPAN_MAX     8.0",
+
+			"void main() {",
+
+				"vec3 rgbNW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ).xyz;",
+				"vec3 rgbNE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ).xyz;",
+				"vec3 rgbSW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ).xyz;",
+				"vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;",
+				"vec3 rgbM  = texture2D( tDiffuse,  gl_FragCoord.xy  * resolution ).xyz;",
+
+				"vec3 luma = vec3( 0.299, 0.587, 0.114 );",
+
+				"float lumaNW = dot( rgbNW, luma );",
+				"float lumaNE = dot( rgbNE, luma );",
+				"float lumaSW = dot( rgbSW, luma );",
+				"float lumaSE = dot( rgbSE, luma );",
+				"float lumaM  = dot( rgbM,  luma );",
+				"float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );",
+				"float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );",
+
+				"vec2 dir;",
+				"dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));",
+				"dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));",
+
+				"float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );",
+
+				"float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );",
+				"dir = min( vec2( FXAA_SPAN_MAX,  FXAA_SPAN_MAX),",
+					  "max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),",
+							"dir * rcpDirMin)) * resolution;",
+
+				"vec3 rgbA = 0.5 * (",
+					"texture2D( tDiffuse, gl_FragCoord.xy  * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ).xyz +",
+					"texture2D( tDiffuse, gl_FragCoord.xy  * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ).xyz );",
+
+				"vec3 rgbB = rgbA * 0.5 + 0.25 * (",
+					"texture2D( tDiffuse, gl_FragCoord.xy  * resolution + dir * -0.5 ).xyz +",
+					"texture2D( tDiffuse, gl_FragCoord.xy  * resolution + dir * 0.5 ).xyz );",
+
+				"float lumaB = dot( rgbB, luma );",
+
+				"if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {",
+
+					"gl_FragColor = vec4( rgbA, 1.0 );",
+
+				"} else {",
+
+					"gl_FragColor = vec4( rgbB, 1.0 );",
+
+				"}",
+
+			"}",
+
+		].join("\n"),
+
+	},
+
 	// METHODS
 
 	buildKernel: function( sigma ) {

+ 52 - 0
examples/js/postprocessing/SavePass.js

@@ -0,0 +1,52 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.SavePass = function( renderTarget ) {
+
+	var shader = THREE.ShaderExtras[ "screen" ];
+
+	this.textureID = "tDiffuse";
+
+	this.uniforms = THREE.UniformsUtils.clone( shader.uniforms );
+
+	this.material = new THREE.ShaderMaterial( {
+
+		uniforms: this.uniforms,
+		vertexShader: shader.vertexShader,
+		fragmentShader: shader.fragmentShader
+
+	} );
+
+	this.renderTarget = renderTarget;
+
+	if ( this.renderTarget === undefined ) {
+
+		this.renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBufer: false };
+		this.renderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, this.renderTargetParameters );
+
+	}
+
+	this.enabled = true;
+	this.needsSwap = false;
+	this.clear = false;
+
+};
+
+THREE.SavePass.prototype = {
+
+	render: function ( renderer, writeBuffer, readBuffer, delta ) {
+
+		if ( this.uniforms[ this.textureID ] ) {
+
+			this.uniforms[ this.textureID ].texture = readBuffer;
+
+		}
+
+		THREE.EffectComposer.quad.materials[ 0 ] = this.material;
+
+		renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, this.renderTarget, this.clear );
+
+	}
+
+};

BIN
examples/obj/gallardo/parts/gallardo_body_bin.bin


+ 110 - 0
examples/obj/gallardo/parts/gallardo_body_bin.js

@@ -0,0 +1,110 @@
+// Converted from: gallardo_body.obj
+//  vertices: 59791
+//  faces: 57252
+//  materials: 7
+//
+//  Generated with OBJ -> Three.js converter
+//  http://github.com/alteredq/three.js/blob/master/utils/exporters/convert_obj_three.py
+
+
+var model = {
+
+    "version" : 1,
+
+    "materials": [	{
+	"DbgColor" : 15658734,
+	"DbgIndex" : 0,
+	"DbgName" : "02___Default",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.64, 0.0, 0.0],
+	"colorSpecular" : [0.6525, 0.6525, 0.6525],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 21.568627,
+	"transparency" : 0.0
+	},
+
+	{
+	"DbgColor" : 15597568,
+	"DbgIndex" : 1,
+	"DbgName" : "wire_115115115",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.28864, 0.28864, 0.28864],
+	"colorSpecular" : [0.175, 0.175, 0.175],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 27.45098,
+	"transparency" : 0.0
+	},
+
+	{
+	"DbgColor" : 60928,
+	"DbgIndex" : 2,
+	"DbgName" : "wire_132132132",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.331264, 0.331264, 0.331264],
+	"colorSpecular" : [0.175, 0.175, 0.175],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 27.45098,
+	"transparency" : 0.0
+	},
+
+	{
+	"DbgColor" : 238,
+	"DbgIndex" : 3,
+	"DbgName" : "wire_255255255",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.64, 0.64, 0.64],
+	"colorSpecular" : [0.175, 0.175, 0.175],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 27.45098,
+	"transparency" : 0.0
+	},
+
+	{
+	"DbgColor" : 15658496,
+	"DbgIndex" : 4,
+	"DbgName" : "03___Default",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.105408, 0.105408, 0.105408],
+	"colorSpecular" : [0.0, 0.0, 0.0],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 3.921569,
+	"transparency" : 0.0
+	},
+
+	{
+	"DbgColor" : 61166,
+	"DbgIndex" : 5,
+	"DbgName" : "wire_252252000",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.632448, 0.632448, 0.0],
+	"colorSpecular" : [0.175, 0.175, 0.175],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 27.45098,
+	"transparency" : 0.0
+	},
+
+	{
+	"DbgColor" : 15597806,
+	"DbgIndex" : 6,
+	"DbgName" : "wire_255000000",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.64, 0.0, 0.0],
+	"colorSpecular" : [0.175, 0.175, 0.175],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 27.45098,
+	"transparency" : 0.0
+	}],
+
+    "buffers": "gallardo_body_bin.bin"
+
+};
+
+postMessage( model );
+close();

BIN
examples/obj/gallardo/parts/gallardo_wheel_bin.bin


+ 45 - 0
examples/obj/gallardo/parts/gallardo_wheel_bin.js

@@ -0,0 +1,45 @@
+// Converted from: gallardo_wheel.obj
+//  vertices: 4434
+//  faces: 4394
+//  materials: 2
+//
+//  Generated with OBJ -> Three.js converter
+//  http://github.com/alteredq/three.js/blob/master/utils/exporters/convert_obj_three.py
+
+
+var model = {
+
+    "version" : 1,
+
+    "materials": [	{
+	"DbgColor" : 15658734,
+	"DbgIndex" : 0,
+	"DbgName" : "wire_255255255",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.64, 0.64, 0.64],
+	"colorSpecular" : [0.175, 0.175, 0.175],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 27.45098,
+	"transparency" : 0.0
+	},
+
+	{
+	"DbgColor" : 15597568,
+	"DbgIndex" : 1,
+	"DbgName" : "wire_115115115",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.28864, 0.28864, 0.28864],
+	"colorSpecular" : [0.175, 0.175, 0.175],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 27.45098,
+	"transparency" : 0.0
+	}],
+
+    "buffers": "gallardo_wheel_bin.bin"
+
+};
+
+postMessage( model );
+close();

BIN
examples/obj/veyron/parts/veyron_body_bin.bin


+ 123 - 0
examples/obj/veyron/parts/veyron_body_bin.js

@@ -0,0 +1,123 @@
+// Converted from: veyron_body.obj
+//  vertices: 23013
+//  faces: 21390
+//  materials: 8
+//
+//  Generated with OBJ -> Three.js converter
+//  http://github.com/alteredq/three.js/blob/master/utils/exporters/convert_obj_three.py
+
+
+var model = {
+
+    "version" : 1,
+
+    "materials": [	{
+	"DbgColor" : 15658734,
+	"DbgIndex" : 0,
+	"DbgName" : "ColorBlack",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.173184, 0.173184, 0.173184],
+	"colorSpecular" : [0.75, 0.75, 0.75],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 52.941176,
+	"transparency" : 0.0
+	},
+
+	{
+	"DbgColor" : 15597568,
+	"DbgIndex" : 1,
+	"DbgName" : "02___Default",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.386496, 0.0, 0.0],
+	"colorSpecular" : [0.75, 0.75, 0.75],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 52.941176,
+	"transparency" : 0.0
+	},
+
+	{
+	"DbgColor" : 60928,
+	"DbgIndex" : 2,
+	"DbgName" : "Aluminium",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.376448, 0.376448, 0.376448],
+	"colorSpecular" : [0.4, 0.4, 0.4],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 15.686275,
+	"transparency" : 0.0
+	},
+
+	{
+	"DbgColor" : 238,
+	"DbgIndex" : 3,
+	"DbgName" : "03___Default",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.421632, 0.421632, 0.421632],
+	"colorSpecular" : [0.6, 0.6, 0.6],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 35.294118,
+	"transparency" : 0.0
+	},
+
+	{
+	"DbgColor" : 15658496,
+	"DbgIndex" : 4,
+	"DbgName" : "glassRed",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.459264, 0.0, 0.0],
+	"colorSpecular" : [0.75, 0.75, 0.75],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 64.705882,
+	"transparency" : 0.5
+	},
+
+	{
+	"DbgColor" : 61166,
+	"DbgIndex" : 5,
+	"DbgName" : "glassOranje",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.64, 0.396544, 0.08032],
+	"colorSpecular" : [0.75, 0.75, 0.75],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 64.705882,
+	"transparency" : 0.5
+	},
+
+	{
+	"DbgColor" : 15597806,
+	"DbgIndex" : 6,
+	"DbgName" : "08___Default",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.150592, 0.150592, 0.150592],
+	"colorSpecular" : [0.14825, 0.14825, 0.14825],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 15.686275,
+	"transparency" : 0.0
+	},
+
+	{
+	"DbgColor" : 419610,
+	"DbgIndex" : 7,
+	"DbgName" : "04___Default",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.434176, 0.459264, 0.471872],
+	"colorSpecular" : [0.75, 0.75, 0.75],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 64.705882,
+	"transparency" : 0.5
+	}],
+
+    "buffers": "veyron_body_bin.bin"
+
+};
+
+postMessage( model );
+close();

BIN
examples/obj/veyron/parts/veyron_wheel_bin.bin


+ 45 - 0
examples/obj/veyron/parts/veyron_wheel_bin.js

@@ -0,0 +1,45 @@
+// Converted from: veyron_wheels.obj
+//  vertices: 3300
+//  faces: 2907
+//  materials: 2
+//
+//  Generated with OBJ -> Three.js converter
+//  http://github.com/alteredq/three.js/blob/master/utils/exporters/convert_obj_three.py
+
+
+var model = {
+
+    "version" : 1,
+
+    "materials": [	{
+	"DbgColor" : 15658734,
+	"DbgIndex" : 0,
+	"DbgName" : "03___Default",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.421632, 0.421632, 0.421632],
+	"colorSpecular" : [0.6, 0.6, 0.6],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 35.294118,
+	"transparency" : 0.0
+	},
+
+	{
+	"DbgColor" : 15597568,
+	"DbgIndex" : 1,
+	"DbgName" : "08___Default",
+	"colorAmbient" : [0.0, 0.0, 0.0],
+	"colorDiffuse" : [0.150592, 0.150592, 0.150592],
+	"colorSpecular" : [0.14825, 0.14825, 0.14825],
+	"illumination" : 2,
+	"opticalDensity" : 1.0,
+	"specularCoef" : 15.686275,
+	"transparency" : 0.0
+	}],
+
+    "buffers": "veyron_wheel_bin.bin"
+
+};
+
+postMessage( model );
+close();

BIN
examples/textures/lensflare2.jpg


BIN
examples/textures/shadowAlpha.png


+ 8 - 2
examples/webgl_lines_colors.html

@@ -158,12 +158,16 @@
 				var renderModel = new THREE.RenderPass( scene, camera );
 				var effectBloom = new THREE.BloomPass( 1.3 );
 				var effectScreen = new THREE.ShaderPass( THREE.ShaderExtras[ "screen" ] );
+				var effectFXAA = new THREE.ShaderPass( THREE.ShaderExtras[ "fxaa" ] );
+
+				effectFXAA.uniforms[ 'resolution' ].value.set( 1 / window.innerWidth, 1 / window.innerHeight );
 
 				effectScreen.renderToScreen = true;
 
 				composer = new THREE.EffectComposer( renderer );
 
 				composer.addPass( renderModel );
+				composer.addPass( effectFXAA );
 				composer.addPass( effectBloom );
 				composer.addPass( effectScreen );
 
@@ -194,7 +198,7 @@
 				if( --iterations >= 0 ) {
 
 					var tmp = [];
-					
+
 					Array.prototype.push.apply( tmp, hilbert3D ( vec[ 0 ], half, iterations, v0, v3, v4, v7, v6, v5, v2, v1 ) );
 					Array.prototype.push.apply( tmp, hilbert3D ( vec[ 1 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) );
 					Array.prototype.push.apply( tmp, hilbert3D ( vec[ 2 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) );
@@ -203,7 +207,7 @@
 					Array.prototype.push.apply( tmp, hilbert3D ( vec[ 5 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ) );
 					Array.prototype.push.apply( tmp, hilbert3D ( vec[ 6 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ) );
 					Array.prototype.push.apply( tmp, hilbert3D ( vec[ 7 ], half, iterations, v6, v5, v2, v1, v0, v3, v4, v7 ) );
-					
+
 					return tmp;
 
 				}
@@ -252,6 +256,8 @@
 				requestAnimationFrame( animate );
 				render();
 
+				stats.update();
+
 			}
 
 			function render() {

+ 104 - 0
src/extras/cameras/CubeCamera.js

@@ -0,0 +1,104 @@
+/**
+ * Camera for rendering cube maps
+ *	- renders scene into axis-aligned cube
+ *
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.CubeCamera = function ( near, far, height, resolution ) {
+
+	var fov = 90, aspect = 1;
+
+	this.cameraPX = new THREE.Camera( fov, aspect, near, far );
+	this.cameraNX = new THREE.Camera( fov, aspect, near, far );
+	this.cameraPY = new THREE.Camera( fov, aspect, near, far );
+	this.cameraNY = new THREE.Camera( fov, aspect, near, far );
+	this.cameraPZ = new THREE.Camera( fov, aspect, near, far );
+	this.cameraNZ = new THREE.Camera( fov, aspect, near, far );
+
+	this.height = height;
+	this.position = new THREE.Vector3( 0, height, 0 );
+
+	this.cameraPX.position = this.position;
+	this.cameraNX.position = this.position;
+	this.cameraPY.position = this.position;
+	this.cameraNY.position = this.position;
+	this.cameraPZ.position = this.position;
+	this.cameraNZ.position = this.position;
+
+	this.cameraPY.up.set( 0, 0, 1 );
+	this.cameraPZ.up.set( 0, -1, 0 );
+	this.cameraNZ.up.set( 0, -1, 0 );
+
+	this.renderTarget = new THREE.WebGLRenderTargetCube( resolution, resolution, { format: THREE.RGBFormat, magFilter: THREE.LinearFilter, minFilter: THREE.LinearFilter } );
+
+	this.updatePosition = function ( position ) {
+
+		this.position.x = position.x;
+		this.position.z = position.z;
+
+		this.cameraPX.target.position.add( this.position, new THREE.Vector3( -1,  0,  0 ) );
+		this.cameraNX.target.position.add( this.position, new THREE.Vector3(  1,  0,  0 ) );
+
+		this.cameraPY.target.position.add( this.position, new THREE.Vector3(  0,  1,  0 ) );
+		this.cameraNY.target.position.add( this.position, new THREE.Vector3(  0, -1,  0 ) );
+
+		this.cameraPZ.target.position.add( this.position, new THREE.Vector3(  0,  0,  1 ) );
+		this.cameraNZ.target.position.add( this.position, new THREE.Vector3(  0,  0, -1 ) );
+
+	};
+
+	this.updateCubeMap = function ( renderer, scene ) {
+
+		var cubeTarget = this.renderTarget;
+
+		renderer.setFaceCulling( "back", "cw" );
+
+		scene.scale.y = -1;
+		scene.position.y = 2 * this.height;
+		scene.updateMatrix();
+
+		cubeTarget.activeCubeFace = 0;
+		renderer.render( scene, this.cameraPX, cubeTarget );
+
+		cubeTarget.activeCubeFace = 1;
+		renderer.render( scene, this.cameraNX, cubeTarget );
+
+		scene.scale.y = 1;
+		scene.position.y = 0;
+		scene.updateMatrix();
+
+		scene.scale.x = -1;
+		scene.updateMatrix();
+
+		cubeTarget.activeCubeFace = 2;
+		renderer.render( scene, this.cameraPY, cubeTarget );
+
+		scene.scale.x = 1;
+		scene.updateMatrix();
+
+		renderer.setFaceCulling( "back", "ccw" );
+
+		cubeTarget.activeCubeFace = 3;
+		renderer.render( scene, this.cameraNY, cubeTarget );
+
+		scene.scale.x = -1;
+		scene.updateMatrix();
+
+		renderer.setFaceCulling( "back", "cw" );
+
+		cubeTarget.activeCubeFace = 4;
+		renderer.render( scene, this.cameraPZ, cubeTarget );
+
+		cubeTarget.activeCubeFace = 5;
+		renderer.render( scene, this.cameraNZ, cubeTarget );
+
+		scene.scale.x = 1;
+		scene.updateMatrix();
+
+		renderer.setFaceCulling( "back", "ccw" );
+
+	};
+
+};
+

+ 1 - 0
utils/build.py

@@ -93,6 +93,7 @@ EXTRAS_FILES = [
 'extras/core/TextPath.js',
 'extras/animation/AnimationHandler.js',
 'extras/animation/Animation.js',
+'extras/cameras/CubeCamera.js',
 'extras/cameras/FirstPersonCamera.js',
 'extras/cameras/PathCamera.js',
 'extras/cameras/FlyCamera.js',