浏览代码

Merged physics branch into master.

Also some whitespace and titles cleanup.
alteredq 14 年之前
父节点
当前提交
4470e0f619

+ 1 - 1
examples/webgl_collisions_box.html

@@ -2,7 +2,7 @@
 <html> 
  
 <head> 
-<title>Intersection: ray with box</title> 
+<title>threej.s webgl - intersection: ray with box</title> 
 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
 <style type="text/css"> 
 

+ 1 - 1
examples/webgl_collisions_mesh.html

@@ -2,7 +2,7 @@
 <html> 
  
 <head> 
-<title>Intersection: ray with mesh (through box)</title> 
+<title>three.js webgl - intersection: ray with mesh (through box)</title> 
 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
 <style type="text/css"> 
 

+ 1 - 1
examples/webgl_collisions_primitives.html

@@ -1,6 +1,6 @@
 <html>
     <head>
-        <title>Intersection: ray with sphere/AABB/plane</title>
+        <title>three.js webgl - intersection: ray with sphere/AABB/plane</title>
         <meta http-equiv="content-type" content="text/html; charset=utf-8">
         <style type="text/css">
             

+ 1 - 1
examples/webgl_collisions_reaction.html

@@ -1,6 +1,6 @@
 <html>
     <head>
-        <title>Collision reaction</title>
+        <title>three.js webgl - collision reaction</title>
         <meta http-equiv="content-type" content="text/html; charset=utf-8">
         <style type="text/css">
             

+ 1 - 1
examples/webgl_collisions_terrain.html

@@ -1,7 +1,7 @@
 <html> 
  
 <head> 
-<title>Intersection: ray with mesh (through box)</title> 
+<title>three.js webgl - intersection: ray with terrain mesh (through box)</title> 
 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
 <style type="text/css"> 
 

+ 1 - 1
examples/webgl_collisions_trigger.html

@@ -1,6 +1,6 @@
 <html>
     <head>
-        <title>Collision detection</title>
+        <title>three.js webgl - collision detection</title>
         <meta http-equiv="content-type" content="text/html; charset=utf-8">
         <style type="text/css">
             

+ 32 - 15
src/physics/CollisionUtils.js

@@ -1,15 +1,22 @@
+/**
+ * @author drojdjou / http://everyday3d.com/
+ */
+
 THREE.CollisionUtils = {};
 
 // @params m THREE.Mesh
 // @returns CBox dynamic Object Bounding Box
-THREE.CollisionUtils.MeshOBB = function(m){
+
+THREE.CollisionUtils.MeshOBB = function( m ) {
+
 	m.geometry.computeBoundingBox();
 	var b = m.geometry.boundingBox;
-	var min = new THREE.Vector3(b.x[0], b.y[0], b.z[0]);
-	var max = new THREE.Vector3(b.x[1], b.y[1], b.z[1]);
-	var box = new THREE.BoxCollider(min, max);
+	var min = new THREE.Vector3( b.x[0], b.y[0], b.z[0] );
+	var max = new THREE.Vector3( b.x[1], b.y[1], b.z[1] );
+	var box = new THREE.BoxCollider( min, max );
 	box.mesh = m;
 	return box;
+
 }
 
 // @params m THREE.Mesh
@@ -17,17 +24,22 @@ THREE.CollisionUtils.MeshOBB = function(m){
 //
 // The AABB is calculated based on current 
 // position of the object (assumes it won't move)
-THREE.CollisionUtils.MeshAABB = function(m){
-	var box = THREE.CollisionUtils.MeshOBB(m);
-	box.min.addSelf(m.position);
-	box.max.addSelf(m.position);
+
+THREE.CollisionUtils.MeshAABB = function( m ) {
+
+	var box = THREE.CollisionUtils.MeshOBB( m );
+	box.min.addSelf( m.position );
+	box.max.addSelf( m.position );
 	box.dynamic = false;
 	return box;
-}
+
+};
 
 // @params m THREE.Mesh
 // @returns CMesh with aOOB attached (that speeds up intersection tests)
-THREE.CollisionUtils.MeshColliderWBox = function(m){
+
+THREE.CollisionUtils.MeshColliderWBox = function( m ) {
+
 	var mv = m.geometry.vertices;
 	var mvl = mv.length;
 	var mf = m.geometry.faces;
@@ -37,20 +49,25 @@ THREE.CollisionUtils.MeshColliderWBox = function(m){
 	var faces = [];
 	var normals = [];
 	
-	for(var i = 0; i < mvl; i++) {
+	for( var i = 0; i < mvl; i++ ) {
+
 		vertices.push( new THREE.Vector3( mv[i].position.x, mv[i].position.y, mv[i].position.z) );
+
 	}
 	
-	for(var i = 0; i < mfl; i++) {
-		faces.push(mf[i].a, mf[i].b, mf[i].c);
+	for( var i = 0; i < mfl; i++ ) {
+
+		faces.push( mf[i].a, mf[i].b, mf[i].c );
 		normals.push( new THREE.Vector3( mf[i].normal.x, mf[i].normal.y, mf[i].normal.z) );
+
 	}
 	
-	var mc = new THREE.MeshCollider(vertices, faces, normals, THREE.CollisionUtils.MeshOBB(m));
+	var mc = new THREE.MeshCollider( vertices, faces, normals, THREE.CollisionUtils.MeshOBB( m ) );
 	mc.mesh = m;
 
 	return mc;
-}
+
+};
 
 
 

+ 218 - 122
src/physics/Collisions.js

@@ -1,312 +1,408 @@
-THREE.PlaneCollider = function(pt, nor){
+/**
+ * @author drojdjou / http://everyday3d.com/
+ */
+
+THREE.PlaneCollider = function( pt, nor ) {
+
 	this.point = pt;
 	this.normal = nor;
-}
+
+};
 
 
-THREE.SphereCollider = function(cen, rad){
+THREE.SphereCollider = function( cen, rad ) {
+
 	this.center = cen;
 	this.radius = rad;
 	this.radiusSq = rad * rad;
-}
 
-THREE.BoxCollider = function(min, max){
+};
+
+THREE.BoxCollider = function( min, max ) {
+
 	this.min = min;
 	this.max = max;
 	this.dynamic = true;
-}
 
-THREE.MeshCollider = function(vertices, faces, normals, box) {		
+};
+
+THREE.MeshCollider = function( vertices, faces, normals, box ) {
+	
 	this.vertices = vertices;
 	this.faces = faces;
 	this.normals = normals;
 	this.box = box;
 	this.numFaces = this.faces.length;
-}
 
-THREE.CollisionSystem = function(){
+};
+
+THREE.CollisionSystem = function() {
+
 	this.colliders = [];
 	this.hits = [];
+
 };
 
 THREE.Collisions = new THREE.CollisionSystem();
 
-THREE.CollisionSystem.prototype.rayCastAll = function(r) {
+THREE.CollisionSystem.prototype.rayCastAll = function( r ) {
+
 	r.direction.normalize();
+
 	var ld = 0;	
 	this.hits.length = 0;
 	
-	for (var i = 0; i < this.colliders.length; i++) {
-		var d = this.rayCast(r, this.colliders[i]);		
-		if (d < Number.MAX_VALUE) {
-			this.colliders[i].distance = d;
-			if(d > ld) this.hits.push(this.colliders[i]);
-			else this.hits.unshift(this.colliders[i]);
+	for ( var i = 0; i < this.colliders.length; i++ ) {
+
+		var d = this.rayCast( r, this.colliders[ i ] );	
+		
+		if ( d < Number.MAX_VALUE ) {
+
+			this.colliders[ i ].distance = d;
+
+			if ( d > ld ) 
+				this.hits.push( this.colliders[ i ] );
+			else 
+				this.hits.unshift( this.colliders[ i ] );
+
 			ld = d;
+
 		}
+
 	}
+
 	return this.hits;
-}
 
-THREE.CollisionSystem.prototype.rayCastNearest = function(r){
-	var cs = this.rayCastAll(r);
+};
+
+THREE.CollisionSystem.prototype.rayCastNearest = function( r ) {
+
+	var cs = this.rayCastAll( r );
 	
-	if(cs.length == 0) return null;
+	if( cs.length == 0 ) return null;
 	
 	var i = 0;
-	while(cs[i] instanceof THREE.MeshCollider) {
-		var d = this.rayMesh(r, cs[i]);
-		if(d < Number.MAX_VALUE) {
-			cs[i].distance = d;
+
+	while( cs[i] instanceof THREE.MeshCollider ) {
+
+		var d = this.rayMesh( r, cs[ i ] );
+
+		if( d < Number.MAX_VALUE ) {
+
+			cs[ i ].distance = d;
 			break;
+
 		}
+
 		i++;
+
 	}
 	
-	if(i > cs.length) return null;
+	if ( i > cs.length ) return null;
 	
-	return cs[i];
-}
-
-THREE.CollisionSystem.prototype.rayCast = function(r, c) {
-	if(c instanceof THREE.PlaneCollider)
-		return this.rayPlane(r, c);
-	else if(c instanceof THREE.SphereCollider)
-		return this.raySphere(r, c);
-	else if (c instanceof THREE.BoxCollider)
-		return this.rayBox(r, c);
-	else if (c instanceof THREE.MeshCollider && c.box)
-		return this.rayBox(r, c.box);
-}
-
-THREE.CollisionSystem.prototype.rayMesh = function(r, me){
-	var rt = this.makeRayLocal(r, me.mesh);
+	return cs[ i ];
+
+};
+
+THREE.CollisionSystem.prototype.rayCast = function( r, c ) {
+
+	if ( c instanceof THREE.PlaneCollider )
+		return this.rayPlane( r, c );
+
+	else if ( c instanceof THREE.SphereCollider )
+		return this.raySphere( r, c );
+
+	else if ( c instanceof THREE.BoxCollider )
+		return this.rayBox( r, c );
+
+	else if ( c instanceof THREE.MeshCollider && c.box )
+		return this.rayBox( r, c.box );
+
+};
+
+THREE.CollisionSystem.prototype.rayMesh = function( r, me ) {
+
+	var rt = this.makeRayLocal( r, me.mesh );
 
 	var d = Number.MAX_VALUE;
 	
-	for(var i = 0; i < me.numFaces/3; i++) {
+	for( var i = 0; i < me.numFaces/3; i++ ) {
+
 		var t = i * 3;
 		
-		var p0 = me.vertices[ me.faces[t+0] ];
-		var p1 = me.vertices[ me.faces[t+1] ];
-		var p2 = me.vertices[ me.faces[t+2] ];	
-		var n = me.normals[ me.faces[i] ];
-		
-		d = Math.min(d, this.rayTriangle(rt, p0, p1, p2, n, d));
+		var p0 = me.vertices[ me.faces[ t + 0 ] ];
+		var p1 = me.vertices[ me.faces[ t + 1 ] ];
+		var p2 = me.vertices[ me.faces[ t + 2 ] ];	
+		var n = me.normals[ me.faces[ i ] ];
+
+		d = Math.min(d, this.rayTriangle( rt, p0, p1, p2, n, d ) );
+
 	}
-	
+
 	return d;
-}
 
-THREE.CollisionSystem.prototype.rayTriangle = function(r, p0, p1, p2, n, mind){
+};
+
+THREE.CollisionSystem.prototype.rayTriangle = function( r, p0, p1, p2, n, mind ) {
+
 	//if (!n) {
-		var e1 = new THREE.Vector3().sub(p1, p0);
-		var e2 = new THREE.Vector3().sub(p2, p1);
-		n = new THREE.Vector3().cross(e1, e2);
+		var e1 = new THREE.Vector3().sub( p1, p0 );
+		var e2 = new THREE.Vector3().sub( p2, p1 );
+		n = new THREE.Vector3().cross( e1, e2 );
 	//}
 	
-	var dot = n.dot(r.direction);
-	if(!(dot < 0)) return Number.MAX_VALUE;
+	var dot = n.dot( r.direction );
+	if ( !( dot < 0 ) ) return Number.MAX_VALUE;
 
-	var d = n.dot(p0);
-	var t = d - n.dot(r.origin);
+	var d = n.dot( p0 );
+	var t = d - n.dot( r.origin );
 	
-	if(!(t <= 0)) return Number.MAX_VALUE;
-	if(!(t >= dot*mind)) return Number.MAX_VALUE;
+	if ( !( t <= 0 ) ) return Number.MAX_VALUE;
+	if ( !( t >= dot * mind ) ) return Number.MAX_VALUE;
 	
 	t = t / dot;
 
-	var p = r.origin.clone().addSelf(r.direction.clone().multiplyScalar(t));
+	var p = r.origin.clone().addSelf( r.direction.clone().multiplyScalar( t ) );
 	var u0, u1, u2, v0, v1, v2;
-	if(Math.abs(n.x) > Math.abs(n.y)){
-		if (Math.abs(n.x) > Math.abs(n.z)) {
-			u0 = p.y - p0.y;
+
+	if ( Math.abs( n.x ) > Math.abs( n.y ) ) {
+
+		if ( Math.abs( n.x ) > Math.abs( n.z ) ) {
+
+			u0 = p.y  - p0.y;
 			u1 = p1.y - p0.y;
 			u2 = p2.y - p0.y;
 			
-			v0 = p.z - p0.z;
+			v0 = p.z  - p0.z;
 			v1 = p1.z - p0.z;
 			v2 = p2.z - p0.z;
+
 		} else {
-			u0 = p.x - p0.x;
+
+			u0 = p.x  - p0.x;
 			u1 = p1.x - p0.x;
 			u2 = p2.x - p0.x;
 			
-			v0 = p.y - p0.y;
+			v0 = p.y  - p0.y;
 			v1 = p1.y - p0.y;
 			v2 = p2.y - p0.y;
+
 		}
+
 	} else {
-		if(Math.abs(n.y) > Math.abs(n.z)){
-			u0 = p.x - p0.x;
+
+		if( Math.abs( n.y ) > Math.abs( n.z ) ) {
+
+			u0 = p.x  - p0.x;
 			u1 = p1.x - p0.x;
 			u2 = p2.x - p0.x;
 			
-			v0 = p.z - p0.z;
+			v0 = p.z  - p0.z;
 			v1 = p1.z - p0.z;
 			v2 = p2.z - p0.z;
+
 		} else {
-			u0 = p.x - p0.x;
+
+			u0 = p.x  - p0.x;
 			u1 = p1.x - p0.x;
 			u2 = p2.x - p0.x;
 			
-			v0 = p.y - p0.y;
+			v0 = p.y  - p0.y;
 			v1 = p1.y - p0.y;
 			v2 = p2.y - p0.y;
+
 		}
+
 	}
 	
 	var temp = u1 * v2 - v1 * u2;	
-	if(!(temp != 0)) return Number.MAX_VALUE;
+	if( !(temp != 0) ) return Number.MAX_VALUE;
 	//console.log("temp: " + temp);
 	temp = 1 / temp;
 	
-	var alpha = (u0 * v2 - v0 * u2) * temp;
-	if(!(alpha >= 0)) return Number.MAX_VALUE;
+	var alpha = ( u0 * v2 - v0 * u2 ) * temp;
+	if( !(alpha >= 0) ) return Number.MAX_VALUE;
 	//console.log("alpha: " + alpha);
 	
-	var beta = (u1 * v0 - v1 * u0) * temp;
-	if(!(beta >= 0)) return Number.MAX_VALUE;
+	var beta = ( u1 * v0 - v1 * u0 ) * temp;
+	if( !(beta >= 0) ) return Number.MAX_VALUE;
 	//console.log("beta: " + beta);
 	
 	var gamma = 1 - alpha - beta;
-	if(!(gamma >= 0)) return Number.MAX_VALUE;
+	if( !(gamma >= 0) ) return Number.MAX_VALUE;
 	//console.log("gamma: " + gamma);
 	
 	return t;
-}
 
-THREE.CollisionSystem.prototype.makeRayLocal = function(r, m){
-	var rt = new THREE.Ray(r.origin.clone(), r.direction.clone());
+};
+
+THREE.CollisionSystem.prototype.makeRayLocal = function( r, m ) {
+
+	var rt = new THREE.Ray( r.origin.clone(), r.direction.clone() );
 	var mt = THREE.Matrix4.makeInvert( m.matrixWorld );
-	mt.multiplyVector3(rt.origin);
-	mt.rotateAxis(rt.direction);
+
+	mt.multiplyVector3( rt.origin );
+	mt.rotateAxis( rt.direction );
 	rt.direction.normalize();
 	//m.localRay = rt;
 	return rt;
-}
 
-THREE.CollisionSystem.prototype.rayBox = function(r, ab){
+};
+
+THREE.CollisionSystem.prototype.rayBox = function( r, ab ) {
+
 	var rt;
 	
-	if(ab.dynamic && ab.mesh && ab.mesh.matrixWorld) {
-		rt = this.makeRayLocal(r, ab.mesh);
+	if ( ab.dynamic && ab.mesh && ab.mesh.matrixWorld ) {
+
+		rt = this.makeRayLocal( r, ab.mesh );
+
 	} else {
-		rt = new THREE.Ray(r.origin.clone(), r.direction.clone());
+
+		rt = new THREE.Ray( r.origin.clone(), r.direction.clone() );
+
 	}
 
 	var xt = 0, yt = 0, zt = 0;
 	var xn = 0, yn = 0, zn = 0;
 	var ins = true;
 	
-	if(rt.origin.x < ab.min.x) {
+	if( rt.origin.x < ab.min.x ) {
+
 		xt = ab.min.x - rt.origin.x;
 		//if(xt > r.direction.x) return return Number.MAX_VALUE;
 		xt /= rt.direction.x;
 		ins = false;
 		xn = -1;
-	} else if(rt.origin.x > ab.max.x) {
+
+	} else if( rt.origin.x > ab.max.x ) {
+
 		xt = ab.max.x - rt.origin.x;
 		//if(xt < r.direction.x) return return Number.MAX_VALUE;
 		xt /= rt.direction.x;
 		ins = false;
 		xn = 1;
+
 	}
 	
-	if(rt.origin.y < ab.min.y) {
+	if( rt.origin.y < ab.min.y ) {
+
 		yt = ab.min.y - rt.origin.y;
 		//if(yt > r.direction.y) return return Number.MAX_VALUE;
 		yt /= rt.direction.y;
 		ins = false;
 		yn = -1;
-	} else if(rt.origin.y > ab.max.y) {
+
+	} else if( rt.origin.y > ab.max.y ) {
+
 		yt = ab.max.y - rt.origin.y;
 		//if(yt < r.direction.y) return return Number.MAX_VALUE;
 		yt /= rt.direction.y;
 		ins = false;
 		yn = 1;
+
 	}
 	
-	if(rt.origin.z < ab.min.z) {
+	if( rt.origin.z < ab.min.z ) {
+
 		zt = ab.min.z - rt.origin.z;
 		//if(zt > r.direction.z) return return Number.MAX_VALUE;
 		zt /= rt.direction.z;
 		ins = false;
 		zn = -1;
-	} else if(rt.origin.z > ab.max.z) {
+
+	} else if( rt.origin.z > ab.max.z ) {
+
 		zt = ab.max.z - rt.origin.z;
 		//if(zt < r.direction.z) return return Number.MAX_VALUE;
 		zt /= rt.direction.z;
 		ins = false;
 		zn = 1;
+
 	}
 
-	if(ins) return -1;
+	if( ins ) return -1;
 
 	var which = 0;
 	var t = xt;
-	if(yt > t) {
+
+	if( yt > t ) {
+
 		which = 1;
 		t = yt;
+
 	}
 	
-	if (zt > t) {
+	if ( zt > t ) {
+
 		which = 2;
 		t = zt;
+
 	}
 	
-	switch(which) {
+	switch( which ) {
+
 		case 0:
+
 			var y = rt.origin.y + rt.direction.y * t;
-			if(y < ab.min.y || y > ab.max.y) return Number.MAX_VALUE;
+			if ( y < ab.min.y || y > ab.max.y ) return Number.MAX_VALUE;
 			var z = rt.origin.z + rt.direction.z * t;
-			if(z < ab.min.z || z > ab.max.z) return Number.MAX_VALUE;
-			ab.normal = new THREE.Vector3(xn, 0, 0);
+			if ( z < ab.min.z || z > ab.max.z ) return Number.MAX_VALUE;
+			ab.normal = new THREE.Vector3( xn, 0, 0 );
 			break;
+
 		case 1:
+
 			var x = rt.origin.x + rt.direction.x * t;
-			if(x < ab.min.x || x > ab.max.x) return Number.MAX_VALUE;
+			if ( x < ab.min.x || x > ab.max.x ) return Number.MAX_VALUE;
 			var z = rt.origin.z + rt.direction.z * t;
-			if(z < ab.min.z || z > ab.max.z) return Number.MAX_VALUE;
-			ab.normal = new THREE.Vector3(0, yn, 0);
+			if ( z < ab.min.z || z > ab.max.z ) return Number.MAX_VALUE;
+			ab.normal = new THREE.Vector3( 0, yn, 0) ;
 			break;
+
 		case 2:
+
 			var x = rt.origin.x + rt.direction.x * t;
-			if(x < ab.min.x || x > ab.max.x) return Number.MAX_VALUE;
+			if (x < ab.min.x || x > ab.max.x ) return Number.MAX_VALUE;
 			var y = rt.origin.y + rt.direction.y * t;
-			if(y < ab.min.y || y > ab.max.y) return Number.MAX_VALUE;
-			ab.normal = new THREE.Vector3(0, 0, zn);
+			if (y < ab.min.y || y > ab.max.y ) return Number.MAX_VALUE;
+			ab.normal = new THREE.Vector3( 0, 0, zn );
 			break;
+
 	}
 	
 	return t;
-}
 
-THREE.CollisionSystem.prototype.rayPlane = function(r, p){
-	var t = r.direction.dot(p.normal);
-	var d = p.point.dot(p.normal);
+};
+
+THREE.CollisionSystem.prototype.rayPlane = function( r, p ) {
+
+	var t = r.direction.dot( p.normal );
+	var d = p.point.dot( p.normal );
 	var ds;
 	
-	if(t < 0) ds = (d - r.origin.dot(p.normal)) / t;
+	if( t < 0 ) ds = ( d - r.origin.dot( p.normal ) ) / t;
 	else return Number.MAX_VALUE;
 	
-	if(ds > 0) return ds;
+	if( ds > 0 ) return ds;
 	else return Number.MAX_VALUE;
 
-}
+};
+
+THREE.CollisionSystem.prototype.raySphere = function( r, s ) {
 
-THREE.CollisionSystem.prototype.raySphere = function(r, s){
-	var e = s.center.clone().subSelf(r.origin);
-	if(e.lengthSq < s.radiusSq) return -1;
+	var e = s.center.clone().subSelf( r.origin );
+	if ( e.lengthSq < s.radiusSq ) return -1;
 	
-	var a = e.dot(r.direction.clone());
-	if(a <= 0) return Number.MAX_VALUE;
+	var a = e.dot( r.direction.clone() );
+	if ( a <= 0 ) return Number.MAX_VALUE;
 	
-	var t = s.radiusSq - (e.lengthSq() - a * a);
-	if(t >= 0) return Math.abs(a) - Math.sqrt(t);
+	var t = s.radiusSq - ( e.lengthSq() - a * a );
+	if ( t >= 0 ) return Math.abs( a ) - Math.sqrt( t );
 	
 	return Number.MAX_VALUE;
-}
+
+};