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/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