diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index fda65cb32..5807d1e1b 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -243,7 +243,8 @@ All definitions files include a header with the author and editors, so at some p * [Marked](https://github.com/chjj/marked) (by [William Orr](https://github.com/worr)) * [MathJax](https://github.com/mathjax/MathJax) (by [Roland Zwaga](https://github.com/rolandzwaga)) * [mCustomScrollbar](https://github.com/malihu/malihu-custom-scrollbar-plugin) (by [Sarah Williams](https://github.com/flurg)) -* [Meteor](https://www.meteor.com) (by [Dave Allen](https://github.com/fullflavedave)) +* [Meteor](https://www.meteor.com) (by [Dave Allen](https://github.com/fullflavedave)) +* [md5.js](http://labs.cybozu.co.jp/blog/mitsunari/2007/07/md5js_1.html) (by [MIZUNE Pine](https://github.com/pine613)) * [Microsoft Ajax](http://msdn.microsoft.com/en-us/library/ee341002(v=vs.100).aspx) (by [Patrick Magee](https://github.com/pjmagee)) * [Microsoft Live Connect](http://msdn.microsoft.com/en-us/library/live/hh243643.aspx) (by [John Vilk](https://github.com/jvilk)) * [Minimatch](https://github.com/isaacs/minimatch) (by [vvakame](https://github.com/vvakame)) @@ -290,6 +291,7 @@ All definitions files include a header with the author and editors, so at some p * [Persona](http://www.mozilla.org/en-US/persona) (by [James Frasca](https://github.com/Nycto)) * [PhantomJS](http://phantomjs.org) (by [Jed Hunsaker](https://github.com/jedhunsaker)) * [PhoneGap](http://phonegap.com) (by [Boris Yankov](https://github.com/borisyankov)) +* [Physijs](http://chandlerprall.github.io/Physijs/) (by [gyoh_k](https://github.com/gyohk)) * [PixiJS](https://github.com/GoodBoyDigital/pixi.js) (by [Pedro Casaubon](https://github.com/xperiments)) * [Platform](https://github.com/bestiejs/platform.js) (by [Jake Hickman](https://github.com/JakeH)) * [PouchDB](http://pouchdb.com) (by [Bill Sears](https://github.com/MrBigDog2U/)) diff --git a/md5/md5-test.ts b/md5/md5-test.ts new file mode 100644 index 000000000..036ad9c2a --- /dev/null +++ b/md5/md5-test.ts @@ -0,0 +1,9 @@ +/// + +var hash: string; +hash = CybozuLabs.MD5.calc("abc"); +hash = CybozuLabs.MD5.calc("abc", CybozuLabs.MD5.BY_ASCII); +hash = CybozuLabs.MD5.calc("abc", CybozuLabs.MD5.BY_UTF16); + +var version: string; +version = CybozuLabs.MD5.VERSION; \ No newline at end of file diff --git a/md5/md5.d.ts b/md5/md5.d.ts new file mode 100644 index 000000000..207a30699 --- /dev/null +++ b/md5/md5.d.ts @@ -0,0 +1,11 @@ +// Type definitions for CybozuLabs.MD5 +// Project: http://labs.cybozu.co.jp/blog/mitsunari/2007/07/md5js_1.html +// Definitions by: MIZUNE Pine +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +declare module CybozuLabs.MD5 { + var VERSION: string; + var BY_ASCII: number; + var BY_UTF16: number; + function calc(str: string, option?: number): string; +} \ No newline at end of file diff --git a/physijs/physijs-tests.ts b/physijs/physijs-tests.ts new file mode 100644 index 000000000..35591c12d --- /dev/null +++ b/physijs/physijs-tests.ts @@ -0,0 +1,15 @@ +///////////////////////////////////////////////////////////// +// https://github.com/chandlerprall/Physijs/tree/master/examples +////////////////////////////////////////////////////////////// + +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// diff --git a/physijs/physijs-tests.ts.tscparams b/physijs/physijs-tests.ts.tscparams new file mode 100644 index 000000000..3b6942a9d --- /dev/null +++ b/physijs/physijs-tests.ts.tscparams @@ -0,0 +1,2 @@ +"" + diff --git a/physijs/physijs.d.ts b/physijs/physijs.d.ts new file mode 100644 index 000000000..8a63b5ad4 --- /dev/null +++ b/physijs/physijs.d.ts @@ -0,0 +1,250 @@ +// Type definitions for Physijs +// Project: http://chandlerprall.github.io/Physijs/ +// Definitions by: Satoru Kimura +// Definitions: https://github.com/borisyankov/DefinitelyTyped + + +/// + +declare module Physijs { + export function noConflict():Object; + export function createMaterial(material: THREE.Material, friction?: number, restitution?: number): Material; + + export interface Material extends THREE.Material{ + _physijs: { + id: number; + friction: number; + restriction: number + }; + } + + export interface Constraint { + getDefinition(): any; + } + + export interface PointConstraintDefinition { + type: string; + id: number; + objecta: THREE.Object3D; + objectb: THREE.Object3D; + positiona: THREE.Vector3; + positionb: THREE.Vector3; + } + + export class PointConstraint implements Constraint { + constructor(objecta: THREE.Object3D, objectb: THREE.Object3D, position?: THREE.Vector3); + + getDefinition(): PointConstraintDefinition; + } + + export interface HingeConstraintDefinition { + type: string; + id: number; + objecta: THREE.Object3D; + objectb: THREE.Object3D; + positiona: THREE.Vector3; + positionb: THREE.Vector3; + axis: THREE.Vector3; + } + + export class HingeConstraint implements Constraint { + constructor(objecta: THREE.Object3D, objectb: THREE.Object3D, position: THREE.Vector3, axis?: THREE.Vector3); + + getDefinition(): HingeConstraintDefinition; + setLimits( low: number, high: number, bias_factor: number, relaxation_factor: number ): void; + enableAngularMotor( velocity: number, acceleration: number ): void; + disableMotor(): void; + } + + export interface SliderConstraintDefinition { + type: string; + id: number; + objecta: THREE.Object3D; + objectb: THREE.Object3D; + positiona: THREE.Vector3; + positionb: THREE.Vector3; + axis: THREE.Vector3; + } + + export class SliderConstraint implements Constraint { + constructor(objecta: THREE.Object3D, objectb: THREE.Object3D, position: THREE.Vector3, axis?: THREE.Vector3); + + getDefinition(): SliderConstraintDefinition; + setLimits( lin_lower: number, lin_upper: number, ang_lower: number, ang_upper: number ): void; + setRestitution( linear: number, angular: number ): void; + enableLinearMotor( velocity: number, acceleration: number): void; + disableLinearMotor(): void; + enableAngularMotor( velocity: number, acceleration: number ): void; + disableAngularMotor(): void; + } + + export interface ConeTwistConstraintDefinition { + type: string; + id: number; + objecta: THREE.Object3D; + objectb: THREE.Object3D; + positiona: THREE.Vector3; + positionb: THREE.Vector3; + axisa: THREE.Vector3; + axisb: THREE.Vector3; + } + + export class ConeTwistConstraint implements Constraint { + constructor(objecta: THREE.Object3D, objectb: THREE.Object3D, position: THREE.Vector3); + + getDefinition(): ConeTwistConstraintDefinition; + setLimit( x: number, y: number, z: number ): void; + enableMotor(): void; + setMaxMotorImpulse( max_impulse: number ): void; + setMotorTarget( target: THREE.Vector3 ): void; + setMotorTarget( target: THREE.Euler ): void; + setMotorTarget( target: THREE.Matrix4 ): void; + disableMotor(): void; + + } + + export interface DOFConstraintDefinition { + type: string; + id: number; + objecta: THREE.Object3D; + objectb: THREE.Object3D; + positiona: THREE.Vector3; + positionb: THREE.Vector3; + axisa: THREE.Vector3; + axisb: THREE.Vector3; + } + + export class DOFConstraint implements Constraint { + constructor(objecta: THREE.Object3D, objectb: THREE.Object3D, position?: THREE.Vector3); + + getDefinition(): DOFConstraintDefinition; + setLinearLowerLimit(limit: THREE.Vector3): void; + setLinearUpperLimit(limit: THREE.Vector3): void; + setAngularLowerLimit(limit: THREE.Vector3): void; + setAngularUpperLimit(limit: THREE.Vector3): void; + enableAngularMotor( which: number ): void; + configureAngularMotor( which: number, low_angle: number, high_angle: number, velocity: number, max_force: number ): void; + disableAngularMotor( which: number ): void; + } + export var scripts: { + worker: string; + ammo: string; + }; + + export interface SceneParameters { + ammo?: string; + fixedTimeStep?: number; + rateLimit?: boolean; + } + + export class Scene extends THREE.Scene { + constructor(param?: SceneParameters); + + addConstraint(constraint:Constraint, show_marker?:boolean):void; + onSimulationResume():void; + removeConstraint(constraint:Constraint):void; + execute(cmd:string, params:any):void; + add(object:THREE.Object3D):void; + remove(object:THREE.Object3D):void; + setFixedTimeStep(fixedTimeStep:number):void; + setGravity(gravity:number):void; + simulate(timeStep?:number, maxSubSteps?:number):boolean; + + + // Eventable mixins + addEventListener( event_name: string, callback: (event: any) => void ): void; + removeEventListener( event_name: string, callback: (event: any) => void): void; + dispatchEvent( event_name: string ): void; + + // (extends from Object3D) + dispatchEvent( event: { type: string; target: any; } ): void; + } + + export class Mesh extends THREE.Mesh { + constructor(geometry:THREE.Geometry, material?:THREE.Material, mass?:number); + + applyCentralImpulse(force:THREE.Vector3):void; + applyImpulse(force:THREE.Vector3, offset:THREE.Vector3):void; + applyCentralForce(force:THREE.Vector3):void; + applyForce(force:THREE.Vector3, offset:THREE.Vector3):void; + getAngularVelocity():THREE.Vector3; + setAngularVelocity(velocity:THREE.Vector3):void; + getLinearVelocity():THREE.Vector3; + setLinearVelocity(velocity:THREE.Vector3):void; + setAngularFactor(factor:THREE.Vector3):void; + setLinearFactor(factor:THREE.Vector3):void; + setDamping(linear:number, angular:number):void; + setCcdMotionThreshold(threshold:number):void; + setCcdSweptSphereRadius(radius:number):void; + + + // Eventable mixins + addEventListener( event_name: string, callback: (event: any) => void ): void; + removeEventListener( event_name: string, callback: (event: any) => void): void; + dispatchEvent( event_name: string ): void; + + // (extends from Object3D) + dispatchEvent( event: { type: string; target: any; } ): void; + } + + export class PlaneMesh extends Mesh { + constructor(geometry:THREE.Geometry, material:THREE.Material, mass?:number); + + } + + export class HeightfieldMesh extends Mesh { + constructor(geometry:THREE.Geometry, material:THREE.Material, mass?:number, xdiv?:number, ydiv?:number); + } + + export class BoxMesh extends Mesh { + constructor(geometry:THREE.Geometry, material:THREE.Material, mass?:number); + } + + export class SphereMesh extends Mesh { + constructor(geometry:THREE.Geometry, material:THREE.Material, mass?:number); + } + + export class CylinderMesh extends Mesh { + constructor(geometry:THREE.Geometry, material:THREE.Material, mass?:number); + } + + export class CapsuleMesh extends Mesh { + constructor(geometry:THREE.Geometry, material:THREE.Material, mass?:number); + } + + export class ConeMesh extends Mesh { + constructor(geometry:THREE.Geometry, material:THREE.Material, mass?:number); + } + + export class ConcaveMesh extends Mesh { + constructor(geometry:THREE.Geometry, material:THREE.Material, mass?:number); + } + + export class ConvexMesh extends Mesh { + constructor(geometry:THREE.Geometry, material:THREE.Material, mass?:number); + } + + export class Vehicle { + constructor(mesh:Mesh, tuning?:VehicleTuning); + + mesh:THREE.Mesh; + wheels:THREE.Mesh[]; + + addWheel(wheel_geometry:THREE.Geometry, wheel_material:THREE.Material, connection_point:THREE.Vector3, wheel_direction:THREE.Vector3, wheel_axle:THREE.Vector3, suspension_rest_length:number, wheel_radius:number, is_front_wheel:boolean, tuning?:VehicleTuning): void; + setSteering(amount: number, wheel?: THREE.Mesh): void; + setBrake(amount: number, wheel?: THREE.Mesh): void; + applyEngineForce(amount: number, wheel?: THREE.Mesh): void; + } + + export class VehicleTuning { + constructor(suspension_stiffness?:number, suspension_compression?:number, suspension_damping?:number, max_suspension_travel?:number, friction_slip?:number, max_suspension_force?:number); + + suspension_stiffness:number; + suspension_compression:number; + suspension_damping:number; + max_suspension_travel:number; + friction_slip:number; + max_suspension_force:number; + } +} + diff --git a/physijs/tests/body.ts b/physijs/tests/body.ts new file mode 100644 index 000000000..acf9df500 --- /dev/null +++ b/physijs/tests/body.ts @@ -0,0 +1,160 @@ +/// +/// + + +Physijs.scripts.worker = '../physijs_worker.js'; +Physijs.scripts.ammo = 'examples/js/ammo.js'; + +var initScene, render, applyForce, setMousePosition, mouse_position, + ground_material, box_material, + projector, renderer, render_stats, physics_stats, scene, ground, light, camera, box, boxes = []; + +initScene = function() { + projector = new THREE.Projector; + + renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.shadowMapEnabled = true; + renderer.shadowMapSoft = true; + document.getElementById( 'viewport' ).appendChild( renderer.domElement ); + + render_stats = new Stats(); + render_stats.domElement.style.position = 'absolute'; + render_stats.domElement.style.top = '1px'; + render_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( render_stats.domElement ); + + physics_stats = new Stats(); + physics_stats.domElement.style.position = 'absolute'; + physics_stats.domElement.style.top = '50px'; + physics_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( physics_stats.domElement ); + + scene = new Physijs.Scene(); + scene.setGravity(new THREE.Vector3( 0, -30, 0 )); + scene.addEventListener( + 'update', + function() { + applyForce(); + scene.simulate( undefined, 1 ); + physics_stats.update(); + } + ); + + camera = new THREE.PerspectiveCamera( + 35, + window.innerWidth / window.innerHeight, + 1, + 1000 + ); + camera.position.set( 60, 50, 60 ); + camera.lookAt( scene.position ); + scene.add( camera ); + + // Light + light = new THREE.DirectionalLight( 0xFFFFFF ); + light.position.set( 20, 40, -15 ); + light.target.position.copy( scene.position ); + light.castShadow = true; + light.shadowCameraLeft = -60; + light.shadowCameraTop = -60; + light.shadowCameraRight = 60; + light.shadowCameraBottom = 60; + light.shadowCameraNear = 20; + light.shadowCameraFar = 200; + light.shadowBias = -.0001 + light.shadowMapWidth = light.shadowMapHeight = 2048; + light.shadowDarkness = .7; + scene.add( light ); + + // Materials + ground_material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/rocks.jpg' ) }), + .8, // high friction + .4 // low restitution + ); + ground_material.map.wrapS = ground_material.map.wrapT = THREE.RepeatWrapping; + ground_material.map.repeat.set( 3, 3 ); + + box_material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/plywood.jpg' ) }), + .4, // low friction + .6 // high restitution + ); + box_material.map.wrapS = ground_material.map.wrapT = THREE.RepeatWrapping; + box_material.map.repeat.set( .25, .25 ); + + // Ground + ground = new Physijs.BoxMesh( + new THREE.BoxGeometry(100, 1, 100), + ground_material, + 0 // mass + ); + ground.receiveShadow = true; + scene.add( ground ); + + for ( var i = 0; i < 10; i++ ) { + box = new Physijs.BoxMesh( + new THREE.BoxGeometry( 4, 4, 4 ), + box_material + ); + box.position.set( + Math.random() * 50 - 25, + 10 + Math.random() * 5, + Math.random() * 50 - 25 + ); + box.rotation.set( + Math.random() * Math.PI * 2, + Math.random() * Math.PI * 2, + Math.random() * Math.PI * 2 + ); + box.scale.set( + Math.random() * 1 + .5, + Math.random() * 1 + .5, + Math.random() * 1 + .5 + ); + box.castShadow = true; + scene.add( box ); + boxes.push( box ); + } + + renderer.domElement.addEventListener( 'mousemove', setMousePosition ); + + requestAnimationFrame( render ); + scene.simulate(); +}; + +render = function() { + requestAnimationFrame( render ); + renderer.render( scene, camera ); + render_stats.update(); +}; + +setMousePosition = function( evt ) { + // Find where mouse cursor intersects the ground plane + var vector = new THREE.Vector3( + ( evt.clientX / renderer.domElement.clientWidth ) * 2 - 1, + -( ( evt.clientY / renderer.domElement.clientHeight ) * 2 - 1 ), + .5 + ); + projector.unprojectVector( vector, camera ); + vector.sub( camera.position ).normalize(); + + var coefficient = (box.position.y - camera.position.y) / vector.y + mouse_position = camera.position.clone().add( vector.multiplyScalar( coefficient ) ); +}; + +applyForce = function() { + if (!mouse_position) return; + var strength = 35, distance, effect, offset, box; + + for ( var i = 0; i < boxes.length; i++ ) { + box = boxes[i]; + distance = mouse_position.distanceTo( box.position ), + effect = mouse_position.clone().sub( box.position ).normalize().multiplyScalar( strength / distance ).negate(), + offset = mouse_position.clone().sub( box.position ); + box.applyImpulse( effect, offset ); + } +}; + +window.onload = initScene; diff --git a/physijs/tests/collisions.ts b/physijs/tests/collisions.ts new file mode 100644 index 000000000..bc43a60d6 --- /dev/null +++ b/physijs/tests/collisions.ts @@ -0,0 +1,171 @@ +/// +/// + + +Physijs.scripts.worker = '../physijs_worker.js'; +Physijs.scripts.ammo = 'examples/js/ammo.js'; + +var initScene, render, _boxes = [], spawnBox, + renderer, render_stats, physics_stats, scene, ground_material, ground, light, camera; + +initScene = function() { + renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.shadowMapEnabled = true; + renderer.shadowMapSoft = true; + document.getElementById( 'viewport' ).appendChild( renderer.domElement ); + + render_stats = new Stats(); + render_stats.domElement.style.position = 'absolute'; + render_stats.domElement.style.top = '0px'; + render_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( render_stats.domElement ); + + physics_stats = new Stats(); + physics_stats.domElement.style.position = 'absolute'; + physics_stats.domElement.style.top = '50px'; + physics_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( physics_stats.domElement ); + + scene = new Physijs.Scene; + scene.setGravity(new THREE.Vector3( 0, -30, 0 )); + scene.addEventListener( + 'update', + function() { + scene.simulate( undefined, 1 ); + physics_stats.update(); + } + ); + + camera = new THREE.PerspectiveCamera( + 35, + window.innerWidth / window.innerHeight, + 1, + 1000 + ); + camera.position.set( 60, 50, 60 ); + camera.lookAt( scene.position ); + scene.add( camera ); + + // Light + light = new THREE.DirectionalLight( 0xFFFFFF ); + light.position.set( 20, 40, -15 ); + light.target.position.copy( scene.position ); + light.castShadow = true; + light.shadowCameraLeft = -60; + light.shadowCameraTop = -60; + light.shadowCameraRight = 60; + light.shadowCameraBottom = 60; + light.shadowCameraNear = 20; + light.shadowCameraFar = 200; + light.shadowBias = -.0001 + light.shadowMapWidth = light.shadowMapHeight = 2048; + light.shadowDarkness = .7; + scene.add( light ); + + // Ground + ground_material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/rocks.jpg' ) }), + .8, // high friction + .3 // low restitution + ); + ground_material.map.wrapS = ground_material.map.wrapT = THREE.RepeatWrapping; + ground_material.map.repeat.set( 3, 3 ); + + ground = new Physijs.BoxMesh( + new THREE.BoxGeometry(100, 1, 100), + ground_material, + 0 // mass + ); + ground.receiveShadow = true; + scene.add( ground ); + + spawnBox(); + + requestAnimationFrame( render ); + scene.simulate(); +}; + +spawnBox = (function() { + + var box_geometry = new THREE.BoxGeometry( 4, 4, 4 ), + handleCollision = function( collided_with, linearVelocity, angularVelocity ) { + var target = this; + target.collisions = 0; + switch (++target.collisions) { + + case 1: + target.material.color.setHex(0xcc8855); + break; + + case 2: + target.material.color.setHex(0xbb9955); + break; + + case 3: + target.material.color.setHex(0xaaaa55); + break; + + case 4: + target.material.color.setHex(0x99bb55); + break; + + case 5: + target.material.color.setHex(0x88cc55); + break; + + case 6: + target.material.color.setHex(0x77dd55); + break; + } + }, + createBox = function() { + var box, material; + + material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/plywood.jpg' ) }), + .6, // medium friction + .3 // low restitution + ); + material.map.wrapS = material.map.wrapT = THREE.RepeatWrapping; + material.map.repeat.set( .5, .5 ); + + //material = new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/rocks.jpg' ) }); + + box = new Physijs.BoxMesh( + box_geometry, + material + ); + + box.collisions = 0; + + box.position.set( + Math.random() * 15 - 7.5, + 25, + Math.random() * 15 - 7.5 + ); + + box.rotation.set( + Math.random() * Math.PI, + Math.random() * Math.PI, + Math.random() * Math.PI + ); + + box.castShadow = true; + box.addEventListener( 'collision', handleCollision ); + box.addEventListener( 'ready', spawnBox ); + scene.add( box ); + }; + + return function() { + setTimeout( createBox, 1000 ); + }; +})(); + +render = function() { + requestAnimationFrame( render ); + renderer.render( scene, camera ); + render_stats.update(); +}; + +window.onload = initScene; \ No newline at end of file diff --git a/physijs/tests/compound.ts b/physijs/tests/compound.ts new file mode 100644 index 000000000..bfd103ca7 --- /dev/null +++ b/physijs/tests/compound.ts @@ -0,0 +1,238 @@ +/// +/// + + +Physijs.scripts.worker = '../physijs_worker.js'; +Physijs.scripts.ammo = 'examples/js/ammo.js'; + +var initScene, render, renderer, render_stats, physics_stats, scene, ground, light, camera, spawnChair, + ground_material, chair_material; + +initScene = function() { + renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.shadowMapEnabled = true; + renderer.shadowMapSoft = true; + document.getElementById( 'viewport' ).appendChild( renderer.domElement ); + + render_stats = new Stats(); + render_stats.domElement.style.position = 'absolute'; + render_stats.domElement.style.top = '0px'; + render_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( render_stats.domElement ); + + physics_stats = new Stats(); + physics_stats.domElement.style.position = 'absolute'; + physics_stats.domElement.style.top = '50px'; + physics_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( physics_stats.domElement ); + + scene = new Physijs.Scene; + scene.setGravity(new THREE.Vector3( 0, -50, 0 )); + scene.addEventListener( + 'update', + function() { + scene.simulate( undefined, 2 ); + physics_stats.update(); + } + ); + + camera = new THREE.PerspectiveCamera( + 35, + window.innerWidth / window.innerHeight, + 1, + 1000 + ); + camera.position.set( 60, 50, 60 ); + camera.lookAt( scene.position ); + scene.add( camera ); + + // Light + light = new THREE.DirectionalLight( 0xFFFFFF ); + light.position.set( 20, 40, -15 ); + light.target.position.copy( scene.position ); + light.castShadow = true; + light.shadowCameraLeft = -60; + light.shadowCameraTop = -60; + light.shadowCameraRight = 60; + light.shadowCameraBottom = 60; + light.shadowCameraNear = 20; + light.shadowCameraFar = 200; + light.shadowBias = -.0001 + light.shadowMapWidth = light.shadowMapHeight = 2048; + light.shadowDarkness = .7; + scene.add( light ); + + // Materials + ground_material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/rocks.jpg' ) }), + .8, // high friction + .4 // low restitution + ); + ground_material.map.wrapS = ground_material.map.wrapT = THREE.RepeatWrapping; + ground_material.map.repeat.set( 3, 3 ); + + chair_material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/wood.jpg' ) }), + .6, // medium friction + .2 // low restitution + ); + chair_material.map.wrapS = chair_material.map.wrapT = THREE.RepeatWrapping; + chair_material.map.repeat.set( .25, .25 ); + + // Ground + ground = new Physijs.BoxMesh( + new THREE.BoxGeometry(100, 1, 100), + ground_material, + 0 // mass + );; + ground.receiveShadow = true; + scene.add( ground ); + + spawnChair(); + + requestAnimationFrame( render ); + scene.simulate(); +}; + +spawnChair = (function() { + var buildBack, buildLegs, doSpawn; + + buildBack = function() { + var back, _object; + + back = new Physijs.BoxMesh( + new THREE.BoxGeometry( 5, 1, .5 ), + chair_material + ); + back.position.y = 5; + back.position.z = -2.5; + back.castShadow = true; + back.receiveShadow = true; + + // rungs - relative to back + _object = new Physijs.BoxMesh( + new THREE.BoxGeometry( 1, 5, .5 ), + chair_material + ); + _object.position.y = -3; + _object.position.x = -2; + _object.castShadow = true; + _object.receiveShadow = true; + back.add( _object ); + + _object = new Physijs.BoxMesh( + new THREE.BoxGeometry( 1, 5, .5 ), + chair_material + ); + _object.position.y = -3; + _object.castShadow = true; + _object.receiveShadow = true; + back.add( _object ); + + _object = new Physijs.BoxMesh( + new THREE.BoxGeometry( 1, 5, .5 ), + chair_material + ); + _object.position.y = -3; + _object.position.x = 2; + _object.castShadow = true; + _object.receiveShadow = true; + back.add( _object ); + + return back; + }; + + buildLegs = function() { + var leg, _leg; + + // back left + leg = new Physijs.BoxMesh( + new THREE.BoxGeometry( .5, 4, .5 ), + chair_material + ); + leg.position.x = 2.25; + leg.position.z = -2.25; + leg.position.y = -2.5; + leg.castShadow = true; + leg.receiveShadow = true; + + // back right - relative to back left leg + _leg = new Physijs.BoxMesh( + new THREE.BoxGeometry( .5, 4, .5 ), + chair_material + ); + _leg.position.x = -4.5; + _leg.castShadow = true; + _leg.receiveShadow = true; + leg.add( _leg ); + + // front left - relative to back left leg + _leg = new Physijs.BoxMesh( + new THREE.BoxGeometry( .5, 4, .5 ), + chair_material + ); + _leg.position.z = 4.5; + _leg.castShadow = true; + _leg.receiveShadow = true; + leg.add( _leg ); + + // front right - relative to back left leg + _leg = new Physijs.BoxMesh( + new THREE.BoxGeometry( .5, 4, .5 ), + chair_material + ); + _leg.position.x = -4.5; + _leg.position.z = 4.5; + _leg.castShadow = true; + _leg.receiveShadow = true; + leg.add( _leg ); + + return leg; + }; + + doSpawn = function() { + var chair, back, legs; + + // seat of the chair + chair = new Physijs.BoxMesh( + new THREE.BoxGeometry( 5, 1, 5 ), + chair_material + ); + chair.castShadow = true; + chair.receiveShadow = true; + + // back - relative to chair ( seat ) + back = buildBack(); + chair.add( back ); + + // legs - relative to chair ( seat ) + legs = buildLegs(); + chair.add( legs ); + + chair.position.y = 20; + chair.position.x = Math.random() * 50 - 25; + chair.position.z = Math.random() * 50 - 25; + + chair.rotation.set( + Math.random() * Math.PI * 2, + Math.random() * Math.PI * 2, + Math.random() * Math.PI * 2 + ); + + chair.addEventListener( 'ready', spawnChair ); + scene.add( chair ); + }; + + return function() { + setTimeout( doSpawn, 500 ); + }; +})(); + +render = function() { + requestAnimationFrame( render ); + renderer.render( scene, camera ); + render_stats.update(); +}; + +window.onload = initScene; diff --git a/physijs/tests/constraints_car.ts b/physijs/tests/constraints_car.ts new file mode 100644 index 000000000..b74c44449 --- /dev/null +++ b/physijs/tests/constraints_car.ts @@ -0,0 +1,257 @@ +/// +/// + + +Physijs.scripts.worker = '../physijs_worker.js'; +Physijs.scripts.ammo = 'examples/js/ammo.js'; + +var initScene, render, + ground_material, car_material, wheel_material, wheel_geometry, + projector, renderer, render_stats, physics_stats, scene, ground_geometry, ground, light, camera, + car: any = {}; + +initScene = function() { + projector = new THREE.Projector; + + renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.shadowMapEnabled = true; + renderer.shadowMapSoft = true; + document.getElementById( 'viewport' ).appendChild( renderer.domElement ); + + render_stats = new Stats(); + render_stats.domElement.style.position = 'absolute'; + render_stats.domElement.style.top = '0px'; + render_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( render_stats.domElement ); + + physics_stats = new Stats(); + physics_stats.domElement.style.position = 'absolute'; + physics_stats.domElement.style.top = '50px'; + physics_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( physics_stats.domElement ); + + scene = new Physijs.Scene; + scene.setGravity(new THREE.Vector3( 0, -30, 0 )); + scene.addEventListener( + 'update', + function() { + scene.simulate( undefined, 2 ); + physics_stats.update(); + } + ); + + camera = new THREE.PerspectiveCamera( + 35, + window.innerWidth / window.innerHeight, + 1, + 1000 + ); + camera.position.set( 60, 50, 60 ); + camera.lookAt( scene.position ); + scene.add( camera ); + + // Light + light = new THREE.DirectionalLight( 0xFFFFFF ); + light.position.set( 20, 40, -15 ); + light.target.position.copy( scene.position ); + light.castShadow = true; + light.shadowCameraLeft = -60; + light.shadowCameraTop = -60; + light.shadowCameraRight = 60; + light.shadowCameraBottom = 60; + light.shadowCameraNear = 20; + light.shadowCameraFar = 200; + light.shadowBias = -.0001 + light.shadowMapWidth = light.shadowMapHeight = 2048; + light.shadowDarkness = .7; + scene.add( light ); + + // Materials + ground_material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/rocks.jpg' ) }), + .8, // high friction + .4 // low restitution + ); + ground_material.map.wrapS = ground_material.map.wrapT = THREE.RepeatWrapping; + ground_material.map.repeat.set( 3, 3 ); + + // Ground + ground = new Physijs.BoxMesh( + new THREE.BoxGeometry(100, 1, 100), + ground_material, + 0 // mass + ); + ground.receiveShadow = true; + scene.add( ground ); + + + // Car + car_material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ color: 0xff6666 }), + .8, // high friction + .2 // low restitution + ); + + wheel_material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ color: 0x444444 }), + .8, // high friction + .5 // medium restitution + ); + wheel_geometry = new THREE.CylinderGeometry( 2, 2, 1, 8 ); + + car.body = new Physijs.BoxMesh( + new THREE.BoxGeometry( 10, 5, 7 ), + car_material, + 1000 + ); + car.body.position.y = 10; + car.body.receiveShadow = car.body.castShadow = true; + scene.add( car.body ); + + car.wheel_fl = new Physijs.CylinderMesh( + wheel_geometry, + wheel_material, + 500 + ); + car.wheel_fl.rotation.x = Math.PI / 2; + car.wheel_fl.position.set( -3.5, 6.5, 5 ); + car.wheel_fl.receiveShadow = car.wheel_fl.castShadow = true; + scene.add( car.wheel_fl ); + car.wheel_fl_constraint = new Physijs.DOFConstraint( + car.wheel_fl, car.body, new THREE.Vector3( -3.5, 6.5, 5 ) + ); + scene.addConstraint( car.wheel_fl_constraint ); + car.wheel_fl_constraint.setAngularLowerLimit({ x: 0, y: -Math.PI / 8, z: 1 }); + car.wheel_fl_constraint.setAngularUpperLimit({ x: 0, y: Math.PI / 8, z: 0 }); + + car.wheel_fr = new Physijs.CylinderMesh( + wheel_geometry, + wheel_material, + 500 + ); + car.wheel_fr.rotation.x = Math.PI / 2; + car.wheel_fr.position.set( -3.5, 6.5, -5 ); + car.wheel_fr.receiveShadow = car.wheel_fr.castShadow = true; + scene.add( car.wheel_fr ); + car.wheel_fr_constraint = new Physijs.DOFConstraint( + car.wheel_fr, car.body, new THREE.Vector3( -3.5, 6.5, -5 ) + ); + scene.addConstraint( car.wheel_fr_constraint ); + car.wheel_fr_constraint.setAngularLowerLimit({ x: 0, y: -Math.PI / 8, z: 1 }); + car.wheel_fr_constraint.setAngularUpperLimit({ x: 0, y: Math.PI / 8, z: 0 }); + + car.wheel_bl = new Physijs.CylinderMesh( + wheel_geometry, + wheel_material, + 500 + ); + car.wheel_bl.rotation.x = Math.PI / 2; + car.wheel_bl.position.set( 3.5, 6.5, 5 ); + car.wheel_bl.receiveShadow = car.wheel_bl.castShadow = true; + scene.add( car.wheel_bl ); + car.wheel_bl_constraint = new Physijs.DOFConstraint( + car.wheel_bl, car.body, new THREE.Vector3( 3.5, 6.5, 5 ) + ); + scene.addConstraint( car.wheel_bl_constraint ); + car.wheel_bl_constraint.setAngularLowerLimit({ x: 0, y: 0, z: 0 }); + car.wheel_bl_constraint.setAngularUpperLimit({ x: 0, y: 0, z: 0 }); + + car.wheel_br = new Physijs.CylinderMesh( + wheel_geometry, + wheel_material, + 500 + ); + car.wheel_br.rotation.x = Math.PI / 2; + car.wheel_br.position.set( 3.5, 6.5, -5 ); + car.wheel_br.receiveShadow = car.wheel_br.castShadow = true; + scene.add( car.wheel_br ); + car.wheel_br_constraint = new Physijs.DOFConstraint( + car.wheel_br, car.body, new THREE.Vector3( 3.5, 6.5, -5 ) + ); + scene.addConstraint( car.wheel_br_constraint ); + car.wheel_br_constraint.setAngularLowerLimit({ x: 0, y: 0, z: 0 }); + car.wheel_br_constraint.setAngularUpperLimit({ x: 0, y: 0, z: 0 }); + + document.addEventListener( + 'keydown', + function( ev ) { + switch( ev.keyCode ) { + case 37: + // Left + car.wheel_fl_constraint.configureAngularMotor( 1, -Math.PI / 2, Math.PI / 2, 1, 200 ); + car.wheel_fr_constraint.configureAngularMotor( 1, -Math.PI / 2, Math.PI / 2, 1, 200 ); + car.wheel_fl_constraint.enableAngularMotor( 1 ); + car.wheel_fr_constraint.enableAngularMotor( 1 ); + break; + + case 39: + // Right + car.wheel_fl_constraint.configureAngularMotor( 1, -Math.PI / 2, Math.PI / 2, -1, 200 ); + car.wheel_fr_constraint.configureAngularMotor( 1, -Math.PI / 2, Math.PI / 2, -1, 200 ); + car.wheel_fl_constraint.enableAngularMotor( 1 ); + car.wheel_fr_constraint.enableAngularMotor( 1 ); + break; + + case 38: + // Up + car.wheel_bl_constraint.configureAngularMotor( 2, 1, 0, 5, 2000 ); + car.wheel_br_constraint.configureAngularMotor( 2, 1, 0, 5, 2000 ); + car.wheel_bl_constraint.enableAngularMotor( 2 ); + car.wheel_br_constraint.enableAngularMotor( 2 ); + break; + + case 40: + // Down + car.wheel_bl_constraint.configureAngularMotor( 2, 1, 0, -5, 2000 ); + car.wheel_br_constraint.configureAngularMotor( 2, 1, 0, -5, 2000 ); + car.wheel_bl_constraint.enableAngularMotor( 2 ); + //car.wheel_br_constraint.enableAngularMotor( 2 ); + break; + } + } + ); + + document.addEventListener( + 'keyup', + function( ev ) { + switch( ev.keyCode ) { + case 37: + // Left + car.wheel_fl_constraint.disableAngularMotor( 1 ); + car.wheel_fr_constraint.disableAngularMotor( 1 ); + break; + + case 39: + // Right + car.wheel_fl_constraint.disableAngularMotor( 1 ); + car.wheel_fr_constraint.disableAngularMotor( 1 ); + break; + + case 38: + // Up + car.wheel_bl_constraint.disableAngularMotor( 2 ); + car.wheel_br_constraint.disableAngularMotor( 2 ); + break; + + case 40: + // Down + car.wheel_bl_constraint.disableAngularMotor( 2 ); + car.wheel_br_constraint.disableAngularMotor( 2 ); + break; + } + } + ); + + + requestAnimationFrame( render ); + scene.simulate(); +}; + +render = function() { + requestAnimationFrame( render ); + renderer.render( scene, camera ); + render_stats.update(); +}; + +window.onload = initScene; diff --git a/physijs/tests/heightfield.ts b/physijs/tests/heightfield.ts new file mode 100644 index 000000000..19d0e8c78 --- /dev/null +++ b/physijs/tests/heightfield.ts @@ -0,0 +1,189 @@ +/// +/// + +var TWEEN: any; +var SimplexNoise: any; + + +Physijs.scripts.worker = '../physijs_worker.js'; +Physijs.scripts.ammo = 'examples/js/ammo.js'; + +var initScene, render, createShape, NoiseGen, + renderer, render_stats, physics_stats, scene, light, ground, ground_geometry, ground_material, camera; + +initScene = function() { + TWEEN.start(); + + renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.shadowMapEnabled = true; + renderer.shadowMapSoft = true; + document.getElementById( 'viewport' ).appendChild( renderer.domElement ); + + render_stats = new Stats(); + render_stats.domElement.style.position = 'absolute'; + render_stats.domElement.style.top = '0px'; + render_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( render_stats.domElement ); + + physics_stats = new Stats(); + physics_stats.domElement.style.position = 'absolute'; + physics_stats.domElement.style.top = '50px'; + physics_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( physics_stats.domElement ); + + scene = new Physijs.Scene({ fixedTimeStep: 1 / 120 }); + scene.setGravity(new THREE.Vector3( 0, -30, 0 )); + scene.addEventListener( + 'update', + function() { + scene.simulate( undefined, 2 ); + physics_stats.update(); + } + ); + + camera = new THREE.PerspectiveCamera( + 35, + window.innerWidth / window.innerHeight, + 1, + 1000 + ); + camera.position.set( 60, 50, 60 ); + camera.lookAt( scene.position ); + scene.add( camera ); + + // Light + light = new THREE.DirectionalLight( 0xFFFFFF ); + light.position.set( 20, 40, -15 ); + light.target.position.copy( scene.position ); + light.castShadow = true; + light.shadowCameraLeft = -60; + light.shadowCameraTop = -60; + light.shadowCameraRight = 60; + light.shadowCameraBottom = 60; + light.shadowCameraNear = 20; + light.shadowCameraFar = 200; + light.shadowBias = -.0001 + light.shadowMapWidth = light.shadowMapHeight = 2048; + light.shadowDarkness = .7; + scene.add( light ); + + // Materials + ground_material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/grass.png' ) }), + .8, // high friction + .4 // low restitution + ); + ground_material.map.wrapS = ground_material.map.wrapT = THREE.RepeatWrapping; + ground_material.map.repeat.set( 2.5, 2.5 ); + + // Ground + NoiseGen = new SimplexNoise; + + ground_geometry = new THREE.PlaneGeometry( 75, 75, 50, 50 ); + for ( var i = 0; i < ground_geometry.vertices.length; i++ ) { + var vertex = ground_geometry.vertices[i]; + vertex.z = NoiseGen.noise( vertex.x / 10, vertex.y / 10 ) * 2; + } + ground_geometry.computeFaceNormals(); + ground_geometry.computeVertexNormals(); + + // If your plane is not square as far as face count then the HeightfieldMesh + // takes two more arguments at the end: # of x faces and # of y faces that were passed to THREE.PlaneMaterial + ground = new Physijs.HeightfieldMesh( + ground_geometry, + ground_material, + 0, // mass + 50, + 50 + ); + ground.rotation.x = Math.PI / -2; + ground.receiveShadow = true; + scene.add( ground ); + + requestAnimationFrame( render ); + scene.simulate(); + + createShape(); +}; + +render = function() { + requestAnimationFrame( render ); + renderer.render( scene, camera ); + render_stats.update(); +}; + +createShape = (function() { + var addshapes = true, + shapes = 0, + box_geometry = new THREE.BoxGeometry( 3, 3, 3 ), + sphere_geometry = new THREE.SphereGeometry( 1.5, 32, 32 ), + cylinder_geometry = new THREE.CylinderGeometry( 2, 2, 1, 32 ), + cone_geometry = new THREE.CylinderGeometry( 0, 2, 4, 32 ), + octahedron_geometry = new THREE.OctahedronGeometry( 1.7, 1 ), + torus_geometry = new THREE.TorusKnotGeometry ( 1.7, .2, 32, 4 ), + doCreateShape; + + setTimeout( + function addListener() { + var button = document.getElementById( 'stop' ); + if ( button ) { + button.addEventListener( 'click', function() { addshapes = false; } ); + } else { + setTimeout( addListener ); + } + } + ); + + doCreateShape = function() { + var shape, material = new THREE.MeshLambertMaterial({ opacity: 0, transparent: true }); + + switch ( Math.floor(Math.random() * 2) ) { + case 0: + shape = new Physijs.BoxMesh( + box_geometry, + material + ); + break; + + case 1: + shape = new Physijs.SphereMesh( + sphere_geometry, + material, + undefined + ); + break; + } + + shape.material.color.setRGB( Math.random() * 100 / 100, Math.random() * 100 / 100, Math.random() * 100 / 100 ); + shape.castShadow = true; + shape.receiveShadow = true; + + shape.position.set( + Math.random() * 30 - 15, + 20, + Math.random() * 30 - 15 + ); + + shape.rotation.set( + Math.random() * Math.PI, + Math.random() * Math.PI, + Math.random() * Math.PI + ); + + if ( addshapes ) { + shape.addEventListener( 'ready', createShape ); + } + scene.add( shape ); + + new TWEEN.Tween(shape.material).to({opacity: 1}, 500).start(); + + document.getElementById('shapecount').textContent = (++shapes) + ' shapes created'; + }; + + return function() { + setTimeout( doCreateShape, 250 ); + }; +})(); + +window.onload = initScene; \ No newline at end of file diff --git a/physijs/tests/jenga.ts b/physijs/tests/jenga.ts new file mode 100644 index 000000000..05bbd7861 --- /dev/null +++ b/physijs/tests/jenga.ts @@ -0,0 +1,236 @@ +/// +/// + + +Physijs.scripts.worker = '../physijs_worker.js'; +Physijs.scripts.ammo = 'examples/js/ammo.js'; + +var initScene, initEventHandling, render, createTower, + renderer, render_stats, physics_stats, scene, dir_light, am_light, camera, + table, blocks = [], table_material, block_material, intersect_plane, _i, + selected_block = null, mouse_pos = new THREE.Vector3(), block_offset = new THREE.Vector3(), _v3 = new THREE.Vector3(); + +initScene = function() { + renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.shadowMapEnabled = true; + renderer.shadowMapSoft = true; + document.getElementById( 'viewport' ).appendChild( renderer.domElement ); + + render_stats = new Stats(); + render_stats.domElement.style.position = 'absolute'; + render_stats.domElement.style.top = '1px'; + render_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( render_stats.domElement ); + + physics_stats = new Stats(); + physics_stats.domElement.style.position = 'absolute'; + physics_stats.domElement.style.top = '50px'; + physics_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( physics_stats.domElement ); + + scene = new Physijs.Scene({ fixedTimeStep: 1 / 120 }); + scene.setGravity(new THREE.Vector3( 0, -30, 0 )); + scene.addEventListener( + 'update', + function() { + + if ( selected_block !== null ) { + + _v3.copy( mouse_pos ).add( block_offset ).sub( selected_block.position ).multiplyScalar( 5 ); + _v3.y = 0; + selected_block.setLinearVelocity( _v3 ); + + // Reactivate all of the blocks + _v3.set( 0, 0, 0 ); + for ( _i = 0; _i < blocks.length; _i++ ) { + blocks[_i].applyCentralImpulse( _v3 ); + } + } + + scene.simulate( undefined, 1 ); + physics_stats.update(); + } + ); + + camera = new THREE.PerspectiveCamera( + 35, + window.innerWidth / window.innerHeight, + 1, + 1000 + ); + camera.position.set( 25, 20, 25 ); + camera.lookAt(new THREE.Vector3( 0, 7, 0 )); + scene.add( camera ); + + // ambient light + am_light = new THREE.AmbientLight( 0x444444 ); + scene.add( am_light ); + + // directional light + dir_light = new THREE.DirectionalLight( 0xFFFFFF ); + dir_light.position.set( 20, 30, -5 ); + dir_light.target.position.copy( scene.position ); + dir_light.castShadow = true; + dir_light.shadowCameraLeft = -30; + dir_light.shadowCameraTop = -30; + dir_light.shadowCameraRight = 30; + dir_light.shadowCameraBottom = 30; + dir_light.shadowCameraNear = 20; + dir_light.shadowCameraFar = 200; + dir_light.shadowBias = -.001 + dir_light.shadowMapWidth = dir_light.shadowMapHeight = 2048; + dir_light.shadowDarkness = .5; + scene.add( dir_light ); + + // Materials + table_material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/wood.jpg' ), ambient: 0xFFFFFF }), + .9, // high friction + .2 // low restitution + ); + table_material.map.wrapS = table_material.map.wrapT = THREE.RepeatWrapping; + table_material.map.repeat.set( 5, 5 ); + + block_material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/plywood.jpg' ), ambient: 0xFFFFFF }), + .4, // medium friction + .4 // medium restitution + ); + block_material.map.wrapS = block_material.map.wrapT = THREE.RepeatWrapping; + block_material.map.repeat.set( 1, .5 ); + + // Table + table = new Physijs.BoxMesh( + new THREE.BoxGeometry(50, 1, 50), + table_material, + 0 + ); + table.position.y = -.5; + table.receiveShadow = true; + scene.add( table ); + + createTower(); + + intersect_plane = new THREE.Mesh( + new THREE.PlaneGeometry( 150, 150 ), + new THREE.MeshBasicMaterial({ opacity: 0, transparent: true }) + ); + intersect_plane.rotation.x = Math.PI / -2; + scene.add( intersect_plane ); + + initEventHandling(); + + requestAnimationFrame( render ); + scene.simulate(); +}; + +render = function() { + requestAnimationFrame( render ); + renderer.render( scene, camera ); + render_stats.update(); +}; + +createTower = (function() { + var block_length = 6, block_height = 1, block_width = 1.5, block_offset = 2, + block_geometry = new THREE.BoxGeometry( block_length, block_height, block_width ); + + return function() { + var i, j, rows = 16, + block; + + for ( i = 0; i < rows; i++ ) { + for ( j = 0; j < 3; j++ ) { + block = new Physijs.BoxMesh( block_geometry, block_material ); + block.position.y = (block_height / 2) + block_height * i; + if ( i % 2 === 0 ) { + block.rotation.y = Math.PI / 2.01; // #TODO: There's a bug somewhere when this is to close to 2 + block.position.x = block_offset * j - ( block_offset * 3 / 2 - block_offset / 2 ); + } else { + block.position.z = block_offset * j - ( block_offset * 3 / 2 - block_offset / 2 ); + } + block.receiveShadow = true; + block.castShadow = true; + scene.add( block ); + blocks.push( block ); + } + } + } +})(); + +initEventHandling = (function() { + var _vector = new THREE.Vector3, + projector = new THREE.Projector(), + handleMouseDown, handleMouseMove, handleMouseUp; + + handleMouseDown = function( evt ) { + var ray, intersections; + + _vector.set( + ( evt.clientX / window.innerWidth ) * 2 - 1, + -( evt.clientY / window.innerHeight ) * 2 + 1, + 1 + ); + + projector.unprojectVector( _vector, camera ); + + ray = new THREE.Raycaster( camera.position, _vector.sub( camera.position ).normalize() ); + intersections = ray.intersectObjects( blocks ); + + if ( intersections.length > 0 ) { + selected_block = intersections[0].object; + + _vector.set( 0, 0, 0 ); + selected_block.setAngularFactor( _vector ); + selected_block.setAngularVelocity( _vector ); + selected_block.setLinearFactor( _vector ); + selected_block.setLinearVelocity( _vector ); + + mouse_pos.copy( intersections[0].point ); + block_offset.subVectors( selected_block.position, mouse_pos ); + + intersect_plane.position.y = mouse_pos.y; + } + }; + + handleMouseMove = function( evt ) { + + var ray, intersection, + i, scalar; + + if ( selected_block !== null ) { + + _vector.set( + ( evt.clientX / window.innerWidth ) * 2 - 1, + -( evt.clientY / window.innerHeight ) * 2 + 1, + 1 + ); + projector.unprojectVector( _vector, camera ); + + ray = new THREE.Raycaster( camera.position, _vector.sub( camera.position ).normalize() ); + intersection = ray.intersectObject( intersect_plane ); + mouse_pos.copy( intersection[0].point ); + } + + }; + + handleMouseUp = function( evt ) { + + if ( selected_block !== null ) { + _vector.set( 1, 1, 1 ); + selected_block.setAngularFactor( _vector ); + selected_block.setLinearFactor( _vector ); + + selected_block = null; + } + + }; + + return function() { + renderer.domElement.addEventListener( 'mousedown', handleMouseDown ); + renderer.domElement.addEventListener( 'mousemove', handleMouseMove ); + renderer.domElement.addEventListener( 'mouseup', handleMouseUp ); + }; +})(); + +window.onload = initScene; diff --git a/physijs/tests/memorytest-compound.ts b/physijs/tests/memorytest-compound.ts new file mode 100644 index 000000000..0455b71f2 --- /dev/null +++ b/physijs/tests/memorytest-compound.ts @@ -0,0 +1,171 @@ +/// +/// + + +Physijs.scripts.worker = '../physijs_worker.js'; +Physijs.scripts.ammo = 'examples/js/ammo.js'; + +var initScene, render, _boxes = [], spawnBox, inc_ready, renderer, render_stats, physics_stats, scene, ground_material, ground, light, camera; + +var cubes = []; +var total_cubes = 0; +var total_ready = 0; +var max_on_screen = 100; +var spawn_per_tick = 25; + +initScene = function() { + renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.shadowMapEnabled = true; + renderer.shadowMapSoft = true; + document.getElementById( 'viewport' ).appendChild( renderer.domElement ); + + render_stats = new Stats(); + render_stats.domElement.style.position = 'absolute'; + render_stats.domElement.style.top = '0px'; + render_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( render_stats.domElement ); + + physics_stats = new Stats(); + physics_stats.domElement.style.position = 'absolute'; + physics_stats.domElement.style.top = '50px'; + physics_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( physics_stats.domElement ); + + scene = new Physijs.Scene; + scene.setGravity(new THREE.Vector3( 0, -30, 0 )); + scene.addEventListener( + 'update', + function() { + scene.simulate( undefined, 1 ); + physics_stats.update(); + while(cubes.length > max_on_screen) { + scene.remove(cubes[0]); + cubes[0].geometry.dispose(); + cubes[0].material.dispose(); + cubes.splice( 0, 1 ); + } + document.getElementById( 'totalcubecount' ).textContent = ( total_cubes.toString() ); + document.getElementById( 'currentcubecount' ).textContent = ( cubes.length.toString() ); + document.getElementById( 'totalobjects' ).textContent = ( scene.__objects.length ); + if(total_cubes > total_ready){ + return; + } + for (var i=0;i +/// + + +Physijs.scripts.worker = '../physijs_worker.js'; +Physijs.scripts.ammo = 'examples/js/ammo.js'; + +var initScene, render, _boxes = [], spawnBox, inc_ready, renderer, render_stats, physics_stats, scene, ground_material, ground, light, camera; + +var cubes = []; +var total_cubes = 0; +var total_ready = 0; +var max_on_screen = 100; +var spawn_per_tick = 25; + +initScene = function() { + renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.shadowMapEnabled = true; + renderer.shadowMapSoft = true; + document.getElementById( 'viewport' ).appendChild( renderer.domElement ); + + render_stats = new Stats(); + render_stats.domElement.style.position = 'absolute'; + render_stats.domElement.style.top = '0px'; + render_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( render_stats.domElement ); + + physics_stats = new Stats(); + physics_stats.domElement.style.position = 'absolute'; + physics_stats.domElement.style.top = '50px'; + physics_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( physics_stats.domElement ); + + scene = new Physijs.Scene; + scene.setGravity(new THREE.Vector3( 0, -30, 0 )); + scene.addEventListener( + 'update', + function() { + scene.simulate( undefined, 1 ); + physics_stats.update(); + while(cubes.length > max_on_screen) { + scene.remove(cubes[0]); + cubes[0].geometry.dispose(); + cubes[0].material.dispose(); + cubes.splice( 0, 1 ); + } + document.getElementById( 'totalcubecount' ).textContent = ( total_cubes.toString() ); + document.getElementById( 'currentcubecount' ).textContent = ( cubes.length.toString() ); + document.getElementById( 'totalobjects' ).textContent = ( scene.__objects.length ); + if(total_cubes > total_ready){ + return; + } + for (var i=0;i +/// + + +Physijs.scripts.worker = '../physijs_worker.js'; +Physijs.scripts.ammo = 'examples/js/ammo.js'; + +var initScene, render, _boxes = [], spawnBox, inc_ready, renderer, render_stats, physics_stats, scene, ground_material, ground, light, camera; + +var cubes = []; +var total_cubes = 0; +var total_ready = 0; +var max_on_screen = 100; +var spawn_per_tick = 25; + +initScene = function() { + renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.shadowMapEnabled = true; + renderer.shadowMapSoft = true; + document.getElementById( 'viewport' ).appendChild( renderer.domElement ); + + render_stats = new Stats(); + render_stats.domElement.style.position = 'absolute'; + render_stats.domElement.style.top = '0px'; + render_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( render_stats.domElement ); + + physics_stats = new Stats(); + physics_stats.domElement.style.position = 'absolute'; + physics_stats.domElement.style.top = '50px'; + physics_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( physics_stats.domElement ); + + scene = new Physijs.Scene; + scene.setGravity(new THREE.Vector3( 0, -30, 0 )); + scene.addEventListener( + 'update', + function() { + scene.simulate( undefined, 1 ); + physics_stats.update(); + while(cubes.length > max_on_screen) { + scene.remove(cubes[0]); + cubes[0].geometry.dispose(); + cubes[0].material.dispose(); + cubes.splice( 0, 1 ); + } + document.getElementById( 'totalcubecount' ).textContent = ( total_cubes.toString() ); + document.getElementById( 'currentcubecount' ).textContent = ( cubes.length.toString() ); + document.getElementById( 'totalobjects' ).textContent = ( scene.__objects.length ); + if(total_cubes > total_ready){ + return; + } + for (var i=0;i +/// + + +var TWEEN: any; +var SimplexNoise: any; + + +Physijs.scripts.worker = '../physijs_worker.js'; +Physijs.scripts.ammo = 'examples/js/ammo.js'; + +var initScene, render, createShape, + renderer, render_stats, physics_stats, scene, light, ground, ground_material, camera; + +initScene = function() { + TWEEN.start(); + + renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.shadowMapEnabled = true; + renderer.shadowMapSoft = true; + document.getElementById( 'viewport' ).appendChild( renderer.domElement ); + + render_stats = new Stats(); + render_stats.domElement.style.position = 'absolute'; + render_stats.domElement.style.top = '0px'; + render_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( render_stats.domElement ); + + physics_stats = new Stats(); + physics_stats.domElement.style.position = 'absolute'; + physics_stats.domElement.style.top = '50px'; + physics_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( physics_stats.domElement ); + + scene = new Physijs.Scene({ fixedTimeStep: 1 / 120 }); + scene.setGravity(new THREE.Vector3( 0, -30, 0 )); + scene.addEventListener( + 'update', + function() { + scene.simulate( undefined, 2 ); + physics_stats.update(); + } + ); + + camera = new THREE.PerspectiveCamera( + 35, + window.innerWidth / window.innerHeight, + 1, + 1000 + ); + camera.position.set( 60, 50, 60 ); + camera.lookAt( scene.position ); + scene.add( camera ); + + // Light + light = new THREE.DirectionalLight( 0xFFFFFF ); + light.position.set( 20, 40, -15 ); + light.target.position.copy( scene.position ); + light.castShadow = true; + light.shadowCameraLeft = -60; + light.shadowCameraTop = -60; + light.shadowCameraRight = 60; + light.shadowCameraBottom = 60; + light.shadowCameraNear = 20; + light.shadowCameraFar = 200; + light.shadowBias = -.0001 + light.shadowMapWidth = light.shadowMapHeight = 2048; + light.shadowDarkness = .7; + scene.add( light ); + + // Materials + ground_material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/rocks.jpg' ) }), + .8, // high friction + .4 // low restitution + ); + ground_material.map.wrapS = ground_material.map.wrapT = THREE.RepeatWrapping; + ground_material.map.repeat.set( 2.5, 2.5 ); + + // Ground + ground = new Physijs.BoxMesh( + new THREE.BoxGeometry(50, 1, 50), + //new THREE.PlaneGeometry(50, 50), + ground_material, + 0 // mass + ); + ground.receiveShadow = true; + scene.add( ground ); + + // Bumpers + var bumper, + bumper_geom = new THREE.BoxGeometry(2, 1, 50); + + bumper = new Physijs.BoxMesh( bumper_geom, ground_material, 0 ); + bumper.position.y = 1; + bumper.position.x = -24; + bumper.receiveShadow = true; + bumper.castShadow = true; + scene.add( bumper ); + + bumper = new Physijs.BoxMesh( bumper_geom, ground_material, 0 ); + bumper.position.y = 1; + bumper.position.x = 24; + bumper.receiveShadow = true; + bumper.castShadow = true; + scene.add( bumper ); + + bumper = new Physijs.BoxMesh( bumper_geom, ground_material, 0 ); + bumper.position.y = 1; + bumper.position.z = -24; + bumper.rotation.y = Math.PI / 2; + bumper.receiveShadow = true; + bumper.castShadow = true; + scene.add( bumper ); + + bumper = new Physijs.BoxMesh( bumper_geom, ground_material, 0 ); + bumper.position.y = 1; + bumper.position.z = 24; + bumper.rotation.y = Math.PI / 2; + bumper.receiveShadow = true; + bumper.castShadow = true; + scene.add( bumper ); + + requestAnimationFrame( render ); + scene.simulate(); + + createShape(); +}; + +render = function() { + requestAnimationFrame( render ); + renderer.render( scene, camera ); + render_stats.update(); +}; + +createShape = (function() { + var addshapes = true, + shapes = 0, + box_geometry = new THREE.BoxGeometry( 3, 3, 3 ), + sphere_geometry = new THREE.SphereGeometry( 1.5, 32, 32 ), + cylinder_geometry = new THREE.CylinderGeometry( 2, 2, 1, 32 ), + cone_geometry = new THREE.CylinderGeometry( 0, 2, 4, 32 ), + octahedron_geometry = new THREE.OctahedronGeometry( 1.7, 1 ), + torus_geometry = new THREE.TorusKnotGeometry ( 1.7, .2, 32, 4 ), + doCreateShape; + + setTimeout( + function addListener() { + var button = document.getElementById( 'stop' ); + if ( button ) { + button.addEventListener( 'click', function() { addshapes = false; } ); + } else { + setTimeout( addListener ); + } + } + ); + + doCreateShape = function() { + var shape, material = new THREE.MeshLambertMaterial({ opacity: 0, transparent: true }); + + switch ( Math.floor(Math.random() * 6) ) { + case 0: + shape = new Physijs.BoxMesh( + box_geometry, + material + ); + break; + + case 1: + shape = new Physijs.SphereMesh( + sphere_geometry, + material, + undefined + ); + break; + + case 2: + shape = new Physijs.CylinderMesh( + cylinder_geometry, + material + ); + break; + + case 3: + shape = new Physijs.ConeMesh( + cone_geometry, + material + ); + break; + + case 4: + shape = new Physijs.ConvexMesh( + octahedron_geometry, + material + ); + break; + + case 5: + shape = new Physijs.ConvexMesh( + torus_geometry, + material + ); + break; + } + + shape.material.color.setRGB( Math.random() * 100 / 100, Math.random() * 100 / 100, Math.random() * 100 / 100 ); + shape.castShadow = true; + shape.receiveShadow = true; + + shape.position.set( + Math.random() * 30 - 15, + 20, + Math.random() * 30 - 15 + ); + + shape.rotation.set( + Math.random() * Math.PI, + Math.random() * Math.PI, + Math.random() * Math.PI + ); + + if ( addshapes ) { + shape.addEventListener( 'ready', createShape ); + } + scene.add( shape ); + + new TWEEN.Tween(shape.material).to({opacity: 1}, 500).start(); + + document.getElementById( 'shapecount' ).textContent = ( ++shapes ) + ' shapes created'; + }; + + return function() { + setTimeout( doCreateShape, 250 ); + }; +})(); + +window.onload = initScene; diff --git a/physijs/tests/vehicle.ts b/physijs/tests/vehicle.ts new file mode 100644 index 000000000..1b11066fe --- /dev/null +++ b/physijs/tests/vehicle.ts @@ -0,0 +1,254 @@ +/// +/// + +var TWEEN: any; +var SimplexNoise: any; + + +Physijs.scripts.worker = '../physijs_worker.js'; +Physijs.scripts.ammo = 'examples/js/ammo.js'; + +var initScene, render, + ground_material, box_material, + projector, renderer, render_stats, physics_stats, scene, ground, light, camera, + vehicle_body, vehicle; + +initScene = function() { + projector = new THREE.Projector; + + renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.shadowMapEnabled = true; + renderer.shadowMapSoft = true; + document.getElementById( 'viewport' ).appendChild( renderer.domElement ); + + render_stats = new Stats(); + render_stats.domElement.style.position = 'absolute'; + render_stats.domElement.style.top = '1px'; + render_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( render_stats.domElement ); + + physics_stats = new Stats(); + physics_stats.domElement.style.position = 'absolute'; + physics_stats.domElement.style.top = '50px'; + physics_stats.domElement.style.zIndex = 100; + document.getElementById( 'viewport' ).appendChild( physics_stats.domElement ); + + scene = new Physijs.Scene; + scene.setGravity(new THREE.Vector3( 0, -30, 0 )); + scene.addEventListener( + 'update', + function() { + + if ( input && vehicle ) { + if ( input.direction !== null ) { + input.steering += input.direction / 50; + if ( input.steering < -.6 ) input.steering = -.6; + if ( input.steering > .6 ) input.steering = .6; + } + vehicle.setSteering( input.steering, 0 ); + vehicle.setSteering( input.steering, 1 ); + + if ( input.power === true ) { + vehicle.applyEngineForce( 300 ); + } else if ( input.power === false ) { + vehicle.setBrake( 20, 2 ); + vehicle.setBrake( 20, 3 ); + } else { + vehicle.applyEngineForce( 0 ); + } + } + + scene.simulate( undefined, 2 ); + physics_stats.update(); + } + ); + + camera = new THREE.PerspectiveCamera( + 35, + window.innerWidth / window.innerHeight, + 1, + 1000 + ); + scene.add( camera ); + + // Light + light = new THREE.DirectionalLight( 0xFFFFFF ); + light.position.set( 20, 20, -15 ); + light.target.position.copy( scene.position ); + light.castShadow = true; + light.shadowCameraLeft = -150; + light.shadowCameraTop = -150; + light.shadowCameraRight = 150; + light.shadowCameraBottom = 150; + light.shadowCameraNear = 20; + light.shadowCameraFar = 400; + light.shadowBias = -.0001 + light.shadowMapWidth = light.shadowMapHeight = 2048; + light.shadowDarkness = .7; + scene.add( light ); + + + var input; + + + // Materials + ground_material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/rocks.jpg' ) }), + .8, // high friction + .4 // low restitution + ); + ground_material.map.wrapS = ground_material.map.wrapT = THREE.RepeatWrapping; + ground_material.map.repeat.set( 3, 3 ); + + box_material = Physijs.createMaterial( + new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/plywood.jpg' ) }), + .4, // low friction + .6 // high restitution + ); + box_material.map.wrapS = ground_material.map.wrapT = THREE.RepeatWrapping; + box_material.map.repeat.set( .25, .25 ); + + // Ground + var NoiseGen = new SimplexNoise; + + var ground_geometry = new THREE.PlaneGeometry( 300, 300, 100, 100 ); + for ( var i = 0; i < ground_geometry.vertices.length; i++ ) { + var vertex = ground_geometry.vertices[i]; + //vertex.y = NoiseGen.noise( vertex.x / 30, vertex.z / 30 ) * 1; + } + ground_geometry.computeFaceNormals(); + ground_geometry.computeVertexNormals(); + + // If your plane is not square as far as face count then the HeightfieldMesh + // takes two more arguments at the end: # of x faces and # of z faces that were passed to THREE.PlaneMaterial + ground = new Physijs.HeightfieldMesh( + ground_geometry, + ground_material, + 0 // mass + ); + ground.rotation.x = -Math.PI / 2; + ground.receiveShadow = true; + scene.add( ground ); + + for ( i = 0; i < 50; i++ ) { + var size = Math.random() * 2 + .5; + var box = new Physijs.BoxMesh( + new THREE.BoxGeometry( size, size, size ), + box_material + ); + box.castShadow = box.receiveShadow = true; + box.position.set( + Math.random() * 25 - 50, + 5, + Math.random() * 25 - 50 + ); + scene.add( box ) + } + + + var loader = new THREE.JSONLoader(); + + loader.load( "models/mustang.js", function( car, car_materials ) { + loader.load( "models/mustang_wheel.js", function( wheel, wheel_materials ) { + var mesh = new Physijs.BoxMesh( + car, + new THREE.MeshFaceMaterial( car_materials ) + ); + mesh.position.y = 2; + mesh.castShadow = mesh.receiveShadow = true; + + vehicle = new Physijs.Vehicle(mesh, new Physijs.VehicleTuning( + 10.88, + 1.83, + 0.28, + 500, + 10.5, + 6000 + )); + scene.add( vehicle ); + + var wheel_material = new THREE.MeshFaceMaterial( wheel_materials ); + + for ( var i = 0; i < 4; i++ ) { + vehicle.addWheel( + wheel, + wheel_material, + new THREE.Vector3( + i % 2 === 0 ? -1.6 : 1.6, + -1, + i < 2 ? 3.3 : -3.2 + ), + new THREE.Vector3( 0, -1, 0 ), + new THREE.Vector3( -1, 0, 0 ), + 0.5, + 0.7, + i < 2 ? false : true + ); + } + + input = { + power: null, + direction: null, + steering: 0 + }; + document.addEventListener('keydown', function( ev ) { + switch ( ev.keyCode ) { + case 37: // left + input.direction = 1; + break; + + case 38: // forward + input.power = true; + break; + + case 39: // right + input.direction = -1; + break; + + case 40: // back + input.power = false; + break; + } + }); + document.addEventListener('keyup', function( ev ) { + switch ( ev.keyCode ) { + case 37: // left + input.direction = null; + break; + + case 38: // forward + input.power = null; + break; + + case 39: // right + input.direction = null; + break; + + case 40: // back + input.power = null; + break; + } + }); + }); + }); + + requestAnimationFrame( render ); + scene.simulate(); +}; + + +render = function() { + requestAnimationFrame( render ); + if ( vehicle ) { + camera.position.copy( vehicle.mesh.position ).add( new THREE.Vector3( 40, 25, 40 ) ); + camera.lookAt( vehicle.mesh.position ); + + light.target.position.copy( vehicle.mesh.position ); + light.position.addVectors( light.target.position, new THREE.Vector3( 20, 20, -15 ) ); + } + renderer.render( scene, camera ); + render_stats.update(); +}; + +window.onload = initScene;