Quellcode durchsuchen

Fixed the normal on mesh collision.

Bartek Drozdz vor 14 Jahren
Ursprung
Commit
5c55a4f751
3 geänderte Dateien mit 225 neuen und 14 gelöschten Zeilen
  1. 6 6
      build/Three.js
  2. 208 0
      examples/webgl_collisions_normal.html
  3. 11 8
      src/extras/physics/Collisions.js

+ 6 - 6
build/Three.js

@@ -511,17 +511,17 @@ THREE.triTable=new Int32Array([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0
 4,1,4,0,7,4,11,-1,-1,-1,-1,3,1,4,3,4,8,1,10,4,7,4,11,10,11,4,-1,4,11,7,9,11,4,9,2,11,9,1,2,-1,-1,-1,-1,9,7,4,9,11,7,9,1,11,2,11,1,0,8,3,-1,11,7,4,11,4,2,2,4,0,-1,-1,-1,-1,-1,-1,-1,11,7,4,11,4,2,8,3,4,3,2,4,-1,-1,-1,-1,2,9,10,2,7,9,2,3,7,7,4,9,-1,-1,-1,-1,9,10,7,9,7,4,10,2,7,8,7,0,2,0,7,-1,3,7,10,3,10,2,7,4,10,1,10,0,4,0,10,-1,1,10,2,8,7,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,9,1,4,1,7,7,1,3,-1,-1,-1,-1,-1,-1,-1,4,9,1,4,1,7,0,8,1,8,7,1,-1,-1,-1,-1,4,0,3,7,4,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,8,7,-1,-1,-1,
 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,9,10,8,10,11,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,0,9,3,9,11,11,9,10,-1,-1,-1,-1,-1,-1,-1,0,1,10,0,10,8,8,10,11,-1,-1,-1,-1,-1,-1,-1,3,1,10,11,3,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,2,11,1,11,9,9,11,8,-1,-1,-1,-1,-1,-1,-1,3,0,9,3,9,11,1,2,9,2,11,9,-1,-1,-1,-1,0,2,11,8,0,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,2,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,3,8,2,8,10,10,8,9,-1,-1,-1,-1,-1,-1,-1,9,10,2,0,9,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,3,8,2,8,10,0,1,8,1,10,8,-1,-1,-1,-1,1,10,
 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,3,8,9,1,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,9,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,3,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]);THREE.PlaneCollider=function(b,d){this.point=b;this.normal=d};THREE.SphereCollider=function(b,d){this.center=b;this.radius=d;this.radiusSq=d*d};THREE.BoxCollider=function(b,d){this.min=b;this.max=d;this.dynamic=!0};
-THREE.MeshCollider=function(b,d,c,f){this.vertices=b;this.faces=d;this.normals=c;this.box=f;this.numFaces=this.faces.length};THREE.CollisionSystem=function(){this.collisionNormal=null;this.colliders=[];this.hits=[]};THREE.Collisions=new THREE.CollisionSystem;
+THREE.MeshCollider=function(b,d,c,f){this.vertices=b;this.faces=d;this.normals=c;this.box=f;this.numFaces=this.faces.length};THREE.CollisionSystem=function(){this.collisionNormal=new THREE.Vector3;this.colliders=[];this.hits=[];console.log("Collision system init / 004")};THREE.Collisions=new THREE.CollisionSystem;
 THREE.CollisionSystem.prototype.rayCastAll=function(b){b.direction.normalize();this.hits.length=0;var d,c,f,g,h=0;d=0;for(c=this.colliders.length;d<c;d++){g=this.colliders[d];f=this.rayCast(b,g);if(f<Number.MAX_VALUE){g.distance=f;f>h?this.hits.push(g):this.hits.unshift(g);h=f}}return this.hits};
 THREE.CollisionSystem.prototype.rayCastNearest=function(b){var d=this.rayCastAll(b);if(d.length==0)return null;for(var c=0;d[c]instanceof THREE.MeshCollider;){var f=this.rayMesh(b,d[c]);if(f<Number.MAX_VALUE){d[c].distance=f;break}c++}if(c>d.length)return null;return d[c]};
 THREE.CollisionSystem.prototype.rayCast=function(b,d){if(d instanceof THREE.PlaneCollider)return this.rayPlane(b,d);else if(d instanceof THREE.SphereCollider)return this.raySphere(b,d);else if(d instanceof THREE.BoxCollider)return this.rayBox(b,d);else if(d instanceof THREE.MeshCollider&&d.box)return this.rayBox(b,d.box)};
-THREE.CollisionSystem.prototype.rayMesh=function(b,d){for(var c=this.makeRayLocal(b,d.mesh),f=Number.MAX_VALUE,g=0;g<d.numFaces/3;g++){var h=g*3;h=this.rayTriangle(c,d.vertices[d.faces[h+0]],d.vertices[d.faces[h+1]],d.vertices[d.faces[h+2]],d.normals[d.faces[g]],f);if(h<f){f=h;d.normal=this.collisionNormal}}return f};
-THREE.CollisionSystem.prototype.rayTriangle=function(b,d,c,f,g,h){var j=THREE.CollisionSystem.__v1,k=THREE.CollisionSystem.__v2;j.sub(c,d);k.sub(f,c);g.cross(j,k);k=g.dot(b.direction);if(!(k<0))return Number.MAX_VALUE;j=g.dot(d)-g.dot(b.origin);if(!(j<=0))return Number.MAX_VALUE;if(!(j>=k*h))return Number.MAX_VALUE;j/=k;var m=THREE.CollisionSystem.__v3;m.copy(b.direction);m.multiplyScalar(j);m.addSelf(b.origin);if(Math.abs(g.x)>Math.abs(g.y))if(Math.abs(g.x)>Math.abs(g.z)){b=m.y-d.y;h=c.y-d.y;k=f.y-
-d.y;m=m.z-d.z;c=c.z-d.z;f=f.z-d.z}else{b=m.x-d.x;h=c.x-d.x;k=f.x-d.x;m=m.y-d.y;c=c.y-d.y;f=f.y-d.y}else if(Math.abs(g.y)>Math.abs(g.z)){b=m.x-d.x;h=c.x-d.x;k=f.x-d.x;m=m.z-d.z;c=c.z-d.z;f=f.z-d.z}else{b=m.x-d.x;h=c.x-d.x;k=f.x-d.x;m=m.y-d.y;c=c.y-d.y;f=f.y-d.y}d=h*f-c*k;if(d==0)return Number.MAX_VALUE;d=1/d;f=(b*f-m*k)*d;if(!(f>=0))return Number.MAX_VALUE;d*=h*m-c*b;if(!(d>=0))return Number.MAX_VALUE;if(!(1-f-d>=0))return Number.MAX_VALUE;this.collisionNormal=g;return j};
-THREE.CollisionSystem.prototype.makeRayLocal=function(b,d){var c=new THREE.Ray(b.origin.clone(),b.direction.clone()),f=THREE.Matrix4.makeInvert(d.matrixWorld);f.multiplyVector3(c.origin);f.rotateAxis(c.direction);c.direction.normalize();return c};
+THREE.CollisionSystem.prototype.rayMesh=function(b,d){for(var c=this.makeRayLocal(b,d.mesh),f=Number.MAX_VALUE,g=0;g<d.numFaces/3;g++){var h=g*3;h=this.rayTriangle(c,d.vertices[d.faces[h+0]],d.vertices[d.faces[h+1]],d.vertices[d.faces[h+2]],f);if(h<f){f=h;d.normal=this.collisionNormal.clone().normalize()}}return f};
+THREE.CollisionSystem.prototype.rayTriangle=function(b,d,c,f,g){var h=THREE.CollisionSystem.__v1,j=THREE.CollisionSystem.__v2,k=new THREE.Vector3;this.collisionNormal.set(0,0,0);h.sub(c,d);j.sub(f,c);k.cross(h,j);j=k.dot(b.direction);if(!(j<0))return Number.MAX_VALUE;h=k.dot(d)-k.dot(b.origin);if(!(h<=0))return Number.MAX_VALUE;if(!(h>=j*g))return Number.MAX_VALUE;h/=j;var m=THREE.CollisionSystem.__v3;m.copy(b.direction);m.multiplyScalar(h);m.addSelf(b.origin);if(Math.abs(k.x)>Math.abs(k.y))if(Math.abs(k.x)>
+Math.abs(k.z)){b=m.y-d.y;g=c.y-d.y;j=f.y-d.y;m=m.z-d.z;c=c.z-d.z;f=f.z-d.z}else{b=m.x-d.x;g=c.x-d.x;j=f.x-d.x;m=m.y-d.y;c=c.y-d.y;f=f.y-d.y}else if(Math.abs(k.y)>Math.abs(k.z)){b=m.x-d.x;g=c.x-d.x;j=f.x-d.x;m=m.z-d.z;c=c.z-d.z;f=f.z-d.z}else{b=m.x-d.x;g=c.x-d.x;j=f.x-d.x;m=m.y-d.y;c=c.y-d.y;f=f.y-d.y}d=g*f-c*j;if(d==0)return Number.MAX_VALUE;d=1/d;f=(b*f-m*j)*d;if(!(f>=0))return Number.MAX_VALUE;d*=g*m-c*b;if(!(d>=0))return Number.MAX_VALUE;if(!(1-f-d>=0))return Number.MAX_VALUE;this.collisionNormal=
+k;return h};THREE.CollisionSystem.prototype.makeRayLocal=function(b,d){var c=new THREE.Ray(b.origin.clone(),b.direction.clone()),f=THREE.Matrix4.makeInvert(d.matrixWorld);f.multiplyVector3(c.origin);f.rotateAxis(c.direction);c.direction.normalize();return c};
 THREE.CollisionSystem.prototype.rayBox=function(b,d){var c;c=d.dynamic&&d.mesh&&d.mesh.matrixWorld?this.makeRayLocal(b,d.mesh):new THREE.Ray(b.origin.clone(),b.direction.clone());var f=0,g=0,h=0,j=0,k=0,m=0,o=!0;if(c.origin.x<d.min.x){f=d.min.x-c.origin.x;f/=c.direction.x;o=!1;j=-1}else if(c.origin.x>d.max.x){f=d.max.x-c.origin.x;f/=c.direction.x;o=!1;j=1}if(c.origin.y<d.min.y){g=d.min.y-c.origin.y;g/=c.direction.y;o=!1;k=-1}else if(c.origin.y>d.max.y){g=d.max.y-c.origin.y;g/=c.direction.y;o=!1;k=
 1}if(c.origin.z<d.min.z){h=d.min.z-c.origin.z;h/=c.direction.z;o=!1;m=-1}else if(c.origin.z>d.max.z){h=d.max.z-c.origin.z;h/=c.direction.z;o=!1;m=1}if(o)return-1;o=0;if(g>f){o=1;f=g}if(h>f){o=2;f=h}switch(o){case 0:k=c.origin.y+c.direction.y*f;if(k<d.min.y||k>d.max.y)return Number.MAX_VALUE;c=c.origin.z+c.direction.z*f;if(c<d.min.z||c>d.max.z)return Number.MAX_VALUE;d.normal=new THREE.Vector3(j,0,0);break;case 1:j=c.origin.x+c.direction.x*f;if(j<d.min.x||j>d.max.x)return Number.MAX_VALUE;c=c.origin.z+
 c.direction.z*f;if(c<d.min.z||c>d.max.z)return Number.MAX_VALUE;d.normal=new THREE.Vector3(0,k,0);break;case 2:j=c.origin.x+c.direction.x*f;if(j<d.min.x||j>d.max.x)return Number.MAX_VALUE;k=c.origin.y+c.direction.y*f;if(k<d.min.y||k>d.max.y)return Number.MAX_VALUE;d.normal=new THREE.Vector3(0,0,m)}return f};THREE.CollisionSystem.prototype.rayPlane=function(b,d){var c=b.direction.dot(d.normal),f=d.point.dot(d.normal);if(c<0)c=(f-b.origin.dot(d.normal))/c;else return Number.MAX_VALUE;return c>0?c:Number.MAX_VALUE};
-THREE.CollisionSystem.prototype.raySphere=function(b,d){var c=d.center.clone().subSelf(b.origin);if(c.lengthSq<d.radiusSq)return-1;var f=c.dot(b.direction.clone());if(f<=0)return Number.MAX_VALUE;c=d.radiusSq-(c.lengthSq()-f*f);if(c>=0)return Math.abs(f)-Math.sqrt(c);return Number.MAX_VALUE};THREE.CollisionSystem.__v1=new THREE.Vector3;THREE.CollisionSystem.__v2=new THREE.Vector3;THREE.CollisionSystem.__v3=new THREE.Vector3;THREE.CollisionUtils={};
+THREE.CollisionSystem.prototype.raySphere=function(b,d){var c=d.center.clone().subSelf(b.origin);if(c.lengthSq<d.radiusSq)return-1;var f=c.dot(b.direction.clone());if(f<=0)return Number.MAX_VALUE;c=d.radiusSq-(c.lengthSq()-f*f);if(c>=0)return Math.abs(f)-Math.sqrt(c);return Number.MAX_VALUE};THREE.CollisionSystem.__v1=new THREE.Vector3;THREE.CollisionSystem.__v2=new THREE.Vector3;THREE.CollisionSystem.__v3=new THREE.Vector3;THREE.CollisionSystem.__nr=new THREE.Vector3;THREE.CollisionUtils={};
 THREE.CollisionUtils.MeshOBB=function(b){b.geometry.computeBoundingBox();var d=b.geometry.boundingBox,c=new THREE.Vector3(d.x[0],d.y[0],d.z[0]);d=new THREE.Vector3(d.x[1],d.y[1],d.z[1]);c=new THREE.BoxCollider(c,d);c.mesh=b;return c};THREE.CollisionUtils.MeshAABB=function(b){var d=THREE.CollisionUtils.MeshOBB(b);d.min.addSelf(b.position);d.max.addSelf(b.position);d.dynamic=!1;return d};
 THREE.CollisionUtils.MeshColliderWBox=function(b){for(var d=b.geometry.vertices,c=d.length,f=b.geometry.faces,g=f.length,h=[],j=[],k=[],m=0;m<c;m++)h.push(new THREE.Vector3(d[m].position.x,d[m].position.y,d[m].position.z));for(m=0;m<g;m++){j.push(f[m].a,f[m].b,f[m].c);k.push(new THREE.Vector3(f[m].normal.x,f[m].normal.y,f[m].normal.z))}d=new THREE.MeshCollider(h,j,k,THREE.CollisionUtils.MeshOBB(b));d.mesh=b;return d};

+ 208 - 0
examples/webgl_collisions_normal.html

@@ -0,0 +1,208 @@
+
+<html> 
+ 
+<head> 
+<title>three.js webgl - intersection: ray/mesh readinf normal</title> 
+<meta http-equiv="content-type" content="text/html; charset=utf-8"> 
+<style type="text/css"> 
+
+body {
+	font-family: Monospace;
+	background-color: #f0f0f0;
+	margin: 0px;
+	overflow: hidden;
+}
+ 
+#oldie { background-color: #ddd !important }
+
+#info {
+	position: absolute;
+	top: 30px; left: 10px; width: 800px;
+	color: #000000;
+	padding: 5px;
+	font-family: Monospace;
+	font-size: 13px;
+	text-align: left;
+	z-index:100;
+}
+
+#options {
+	position: absolute;
+	top: 10px; left: 10px; width: 800px;
+	color: #000000;
+	padding: 5px;
+	font-family: Monospace;
+	font-size: 13px;
+	text-align: left;
+	z-index:100;
+}
+
+</style>
+ 
+<script type="text/javascript" src="../build/Three.js"></script> 
+<script type="text/javascript" src="js/RequestAnimationFrame.js"></script>
+<script type="text/javascript" src="js/Stats.js"></script>
+
+<script type="text/javascript"> 
+
+var scene, camera, renderer, info, mouse2d, sun, loader, stats;
+var meshes = [];
+
+var theta = 0;
+var camdist = 500;
+
+var totalFaces = 0;
+var totalColliders = 0;
+
+var ray = new THREE.Ray();
+var matrix = new THREE.Matrix4(),
+	matrix2 = new THREE.Matrix4();
+
+function init() {
+
+	container = document.createElement( 'div' );
+	document.body.appendChild( container );
+	
+	info = document.getElementById("info");
+	
+	camera = new THREE.Camera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
+	camera.position.z = camdist;
+	mouse2d = new THREE.Vector3( 0, 0, 1 );
+	
+	loader = new THREE.JSONLoader(  );
+
+	scene = new THREE.Scene();
+
+	renderer = new THREE.WebGLRenderer();
+	renderer.setSize( window.innerWidth, window.innerHeight );
+	container.appendChild( renderer.domElement );
+	
+	var ambientLight = new THREE.AmbientLight( 0x606060 );
+	scene.addLight( ambientLight );
+
+	sun = new THREE.DirectionalLight( 0xffffff );
+	sun.position = camera.position.clone();
+	scene.addLight( sun );
+	
+	loadCube();
+
+	stats = new Stats();
+	stats.domElement.style.position = 'absolute';
+	stats.domElement.style.top = '0px';
+	container.appendChild( stats.domElement );
+
+	container.onmousemove = onDocumentMouseMove;
+	animate();
+
+}
+
+function loadCube(p) {
+
+	var onGeometry = function( geometry ) {	
+	
+		var sx = 300;
+		var sy = 240;
+		var sz = 300;
+		
+		addCube( new THREE.Vector3(	0,	0,	0), geometry );
+		
+	};
+
+	
+	loader.load( { model: "obj/suzanne/suzanne.js", callback: onGeometry } );
+}
+
+function addCube( p, g) {
+
+	totalFaces += g.faces.length;
+	totalColliders++;
+
+	var mesh = new THREE.Mesh( g, new THREE.MeshLambertMaterial( { color: 0x003300 } ) );
+	mesh.position = p;
+
+	scene.addObject( mesh );
+	var mc = THREE.CollisionUtils.MeshColliderWBox(mesh);
+	THREE.Collisions.colliders.push( mc );
+	meshes.push( mesh );
+
+};
+
+function onDocumentMouseMove( event ) {
+
+	event.preventDefault();	
+	mouse2d.x = ( event.clientX / window.innerWidth ) * 2 - 1;
+	mouse2d.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
+	mouse2d.z = 1;
+
+};
+
+
+function animate() {
+
+	requestAnimationFrame( animate );
+	
+	ray.origin.copy( mouse2d );
+
+	matrix.copy( camera.matrixWorld );
+	matrix.multiplySelf( THREE.Matrix4.makeInvert( camera.projectionMatrix, matrix2 ) );
+	matrix.multiplyVector3( ray.origin );
+	
+	ray.direction.copy( ray.origin );
+	ray.direction.subSelf( camera.position );
+	
+	if( meshes.length == 0 ) return;
+	
+	var i, l = meshes.length;
+	
+	for ( i = 0; i < l; i++ ) {
+		meshes[ i ].materials[ 0 ].color.setHex( 0x003300 );
+	}
+	
+	info.innerHTML = "";
+
+
+	var c = THREE.Collisions.rayCastNearest( ray );
+	
+	if( c ) {
+	
+		info.innerHTML += "Found @ normal " + vts(c.normal);
+		c.mesh.materials[ 0 ].color.setHex( 0xbb0000 );
+
+	} else {
+	
+		info.innerHTML += "No intersection";
+
+	}
+
+	camera.position.x = camdist * Math.cos( theta );
+	camera.position.z = camdist * Math.sin( theta );
+	camera.position.y = camdist/2 * Math.sin( theta * 2) ;
+
+	sun.position.copy( camera.position );
+	sun.position.normalize();
+
+	theta += 0.005;		
+
+	renderer.render( scene, camera );
+	
+	stats.update();
+	
+};
+
+function vts(v) {
+
+	if(!v) return "undefined<br>";
+	else return v.x.toFixed(2) + " , " + v.y.toFixed(2) + " , " + v.z.toFixed(2) + "<br>";
+
+};
+
+</script>
+
+</head> 
+
+<body onload="init();"> 
+<div id="info"></div>
+<div id="options"></div>
+</body> 
+
+</html> 

+ 11 - 8
src/extras/physics/Collisions.js

@@ -38,9 +38,11 @@ THREE.MeshCollider = function( vertices, faces, normals, box ) {
 
 THREE.CollisionSystem = function() {
 
-	this.collisionNormal = null;
+	this.collisionNormal = new THREE.Vector3();
 	this.colliders = [];
 	this.hits = [];
+	
+	console.log("Collision system init / 004");
 
 };
 
@@ -138,13 +140,12 @@ THREE.CollisionSystem.prototype.rayMesh = function( r, me ) {
 		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 ] ];
 
-		var nd = this.rayTriangle( rt, p0, p1, p2, n, d );
+		var nd = this.rayTriangle( rt, p0, p1, p2, d );
 		
 		if(nd < d) {
 			d = nd;
-			me.normal = this.collisionNormal;
+			me.normal = this.collisionNormal.clone().normalize();
 		}
 	}
 
@@ -152,14 +153,15 @@ THREE.CollisionSystem.prototype.rayMesh = function( r, me ) {
 
 };
 
-THREE.CollisionSystem.prototype.rayTriangle = function( ray, p0, p1, p2, n, mind ) {
+THREE.CollisionSystem.prototype.rayTriangle = function( ray, p0, p1, p2, mind ) {
 
 	var e1 = THREE.CollisionSystem.__v1,
-		e2 = THREE.CollisionSystem.__v2;
+		e2 = THREE.CollisionSystem.__v2,
+		 n = new THREE.Vector3(); //THREE.CollisionSystem.__nr;
 
-	// do not crash on quads, fail instead
+	this.collisionNormal.set(0,0,0);
 
-	//if ( !n ) n = THREE.CollisionSystem.__v3;
+	// do not crash on quads, fail instead
 
 	e1.sub( p1, p0 );
 	e2.sub( p2, p1 );
@@ -428,3 +430,4 @@ THREE.CollisionSystem.prototype.raySphere = function( r, s ) {
 THREE.CollisionSystem.__v1 = new THREE.Vector3();
 THREE.CollisionSystem.__v2 = new THREE.Vector3();
 THREE.CollisionSystem.__v3 = new THREE.Vector3();
+THREE.CollisionSystem.__nr = new THREE.Vector3();