diff --git a/build/Three.js b/build/Three.js index c248e939..ce727bd3 100644 --- a/build/Three.js +++ b/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=e0?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= diff --git a/build/custom/ThreeExtras.js b/build/custom/ThreeExtras.js index f261136e..9f1e62b3 100644 --- a/build/custom/ThreeExtras.js +++ b/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=c0?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= diff --git a/examples/js/Car.js b/examples/js/Car.js new file mode 100644 index 00000000..f48c2de2 --- /dev/null +++ b/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; } + +}; diff --git a/examples/js/ShaderExtras.js b/examples/js/ShaderExtras.js index e54e8a51..2eff5a74 100644 --- a/examples/js/ShaderExtras.js +++ b/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 ) { diff --git a/examples/js/postprocessing/SavePass.js b/examples/js/postprocessing/SavePass.js new file mode 100644 index 00000000..056608c8 --- /dev/null +++ b/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 ); + + } + +}; diff --git a/examples/obj/gallardo/parts/gallardo_body_bin.bin b/examples/obj/gallardo/parts/gallardo_body_bin.bin new file mode 100644 index 00000000..0fe276e7 Binary files /dev/null and b/examples/obj/gallardo/parts/gallardo_body_bin.bin differ diff --git a/examples/obj/gallardo/parts/gallardo_body_bin.js b/examples/obj/gallardo/parts/gallardo_body_bin.js new file mode 100644 index 00000000..712d76e0 --- /dev/null +++ b/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(); diff --git a/examples/obj/gallardo/parts/gallardo_wheel_bin.bin b/examples/obj/gallardo/parts/gallardo_wheel_bin.bin new file mode 100644 index 00000000..40e60576 Binary files /dev/null and b/examples/obj/gallardo/parts/gallardo_wheel_bin.bin differ diff --git a/examples/obj/gallardo/parts/gallardo_wheel_bin.js b/examples/obj/gallardo/parts/gallardo_wheel_bin.js new file mode 100644 index 00000000..d4d30bea --- /dev/null +++ b/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(); diff --git a/examples/obj/veyron/parts/veyron_body_bin.bin b/examples/obj/veyron/parts/veyron_body_bin.bin new file mode 100644 index 00000000..4ded83e1 Binary files /dev/null and b/examples/obj/veyron/parts/veyron_body_bin.bin differ diff --git a/examples/obj/veyron/parts/veyron_body_bin.js b/examples/obj/veyron/parts/veyron_body_bin.js new file mode 100644 index 00000000..7d8dcab9 --- /dev/null +++ b/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(); diff --git a/examples/obj/veyron/parts/veyron_wheel_bin.bin b/examples/obj/veyron/parts/veyron_wheel_bin.bin new file mode 100644 index 00000000..c4581fd4 Binary files /dev/null and b/examples/obj/veyron/parts/veyron_wheel_bin.bin differ diff --git a/examples/obj/veyron/parts/veyron_wheel_bin.js b/examples/obj/veyron/parts/veyron_wheel_bin.js new file mode 100644 index 00000000..0ba1089e --- /dev/null +++ b/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(); diff --git a/examples/textures/lensflare2.jpg b/examples/textures/lensflare2.jpg new file mode 100644 index 00000000..5a16c503 Binary files /dev/null and b/examples/textures/lensflare2.jpg differ diff --git a/examples/textures/shadowAlpha.png b/examples/textures/shadowAlpha.png new file mode 100644 index 00000000..aa4de6bf Binary files /dev/null and b/examples/textures/shadowAlpha.png differ diff --git a/examples/webgl_lines_colors.html b/examples/webgl_lines_colors.html index 566f3dbe..d2b11bbd 100644 --- a/examples/webgl_lines_colors.html +++ b/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() { diff --git a/src/extras/cameras/CubeCamera.js b/src/extras/cameras/CubeCamera.js new file mode 100644 index 00000000..6e2b22a5 --- /dev/null +++ b/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" ); + + }; + +}; + diff --git a/utils/build.py b/utils/build.py index cd9168ef..eb6a0328 100644 --- a/utils/build.py +++ b/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',