浏览代码

added absolute colliders for complex scenes, allow preciseShape to distinguish collisions

ncannasse 8 年之前
父节点
当前提交
2676fc15d3
共有 9 个文件被更改,包括 80 次插入25 次删除
  1. 1 3
      h3d/Camera.hx
  2. 41 0
      h3d/col/ObjectCollider.hx
  3. 4 9
      h3d/col/SkinCollider.hx
  4. 6 0
      h3d/scene/Interactive.hx
  5. 2 2
      h3d/scene/Mesh.hx
  6. 0 1
      h3d/scene/Object.hx
  7. 18 2
      h3d/scene/Scene.hx
  8. 2 2
      h3d/scene/Skin.hx
  9. 6 6
      samples/Interactive.hx

+ 1 - 3
h3d/Camera.hx

@@ -130,9 +130,7 @@ class Camera {
 		var engine = h3d.Engine.getCurrent();
 		var engine = h3d.Engine.getCurrent();
 		var rx = (pixelX / engine.width - 0.5) * 2;
 		var rx = (pixelX / engine.width - 0.5) * 2;
 		var ry = (0.5 - pixelY / engine.height) * 2;
 		var ry = (0.5 - pixelY / engine.height) * 2;
-		var r = h3d.col.Ray.fromPoints(unproject(rx, ry, 0).toPoint(), unproject(rx, ry, 1).toPoint());
-		r.normalize();
-		return r;
+		return h3d.col.Ray.fromPoints(unproject(rx, ry, 0).toPoint(), unproject(rx, ry, 1).toPoint());
 	}
 	}
 
 
 	public function update() {
 	public function update() {

+ 41 - 0
h3d/col/ObjectCollider.hx

@@ -0,0 +1,41 @@
+package h3d.col;
+
+class ObjectCollider implements Collider {
+
+	public var obj : h3d.scene.Object;
+	public var collider : Collider;
+	var tmpRay = new Ray();
+
+	public function new(obj, collider) {
+		this.obj = obj;
+		this.collider = collider;
+	}
+
+	public function rayIntersection( r : Ray, bestMatch : Bool ) : Float {
+		tmpRay.load(r);
+		r.transform(obj.getInvPos());
+		var hit = collider.rayIntersection(r, bestMatch);
+		if( hit < 0 ) {
+			r.load(tmpRay);
+			return hit;
+		}
+		var pt = r.getPoint(hit);
+		pt.transform(@:privateAccess obj.absPos);
+		r.load(tmpRay);
+		return hxd.Math.distance(pt.x - r.px, pt.y - r.py, pt.z - r.pz);
+	}
+
+	public function contains( p : Point ) {
+		var ptmp = p.clone();
+		p.transform(obj.getInvPos());
+		var b = collider.contains(p);
+		p.load(ptmp);
+		return b;
+	}
+
+	public function inFrustum( mvp : h3d.Matrix ) {
+		throw "Not implemented";
+		return false;
+	}
+
+}

+ 4 - 9
h3d/col/SkinTransform.hx → h3d/col/SkinCollider.hx

@@ -2,7 +2,7 @@ package h3d.col;
 
 
 @:access(h3d.col.PolygonBuffer)
 @:access(h3d.col.PolygonBuffer)
 @:access(h3d.scene.Skin)
 @:access(h3d.scene.Skin)
-class SkinTransform implements Collider {
+class SkinCollider implements Collider {
 
 
 	var obj : h3d.scene.Skin;
 	var obj : h3d.scene.Skin;
 	var col : PolygonBuffer;
 	var col : PolygonBuffer;
@@ -31,7 +31,6 @@ class SkinTransform implements Collider {
 	}
 	}
 
 
 	function applyTransform() {
 	function applyTransform() {
-		var invMat = obj.getInvPos();
 		if( !obj.jointsUpdated && lastFrame == obj.lastFrame ) return;
 		if( !obj.jointsUpdated && lastFrame == obj.lastFrame ) return;
 		lastFrame = obj.lastFrame;
 		lastFrame = obj.lastFrame;
 		obj.syncJoints();
 		obj.syncJoints();
@@ -54,14 +53,10 @@ class SkinTransform implements Collider {
 				py += p2.y * w;
 				py += p2.y * w;
 				pz += p2.z * w;
 				pz += p2.z * w;
 			}
 			}
-
-			var p = new h3d.col.Point(px, py, pz);
-			p.transform(invMat);
-			transform.buffer[v++] = p.x;
-			transform.buffer[v++] = p.y;
-			transform.buffer[v++] = p.z;
+			transform.buffer[v++] = px;
+			transform.buffer[v++] = py;
+			transform.buffer[v++] = pz;
 		}
 		}
-
 	}
 	}
 
 
 }
 }

+ 6 - 0
h3d/scene/Interactive.hx

@@ -3,6 +3,12 @@ package h3d.scene;
 class Interactive extends Object implements hxd.SceneEvents.Interactive {
 class Interactive extends Object implements hxd.SceneEvents.Interactive {
 
 
 	public var shape : h3d.col.Collider;
 	public var shape : h3d.col.Collider;
+
+	/**
+		If several interactive conflicts, the preciseShape (if defined) can be used to distinguish between the two.
+	**/
+	public var preciseShape : Null<h3d.col.Collider>;
+
 	public var cursor(default,set) : hxd.Cursor;
 	public var cursor(default,set) : hxd.Cursor;
 	/**
 	/**
 		Set the default `cancel` mode (see `hxd.Event`), default to false.
 		Set the default `cancel` mode (see `hxd.Event`), default to false.

+ 2 - 2
h3d/scene/Mesh.hx

@@ -30,8 +30,8 @@ class Mesh extends Object {
 		return m;
 		return m;
 	}
 	}
 
 
-	override function getCollider() {
-		return primitive.getCollider();
+	override function getCollider() : h3d.col.Collider {
+		return new h3d.col.ObjectCollider(this, primitive.getCollider());
 	}
 	}
 
 
 	override function draw( ctx : RenderContext ) {
 	override function draw( ctx : RenderContext ) {

+ 0 - 1
h3d/scene/Object.hx

@@ -373,7 +373,6 @@ class Object {
 			} else
 			} else
 				colliders.push(c);
 				colliders.push(c);
 		}
 		}
-		// TODO : handle child position/transform
 		return new h3d.col.Collider.GroupCollider(colliders);
 		return new h3d.col.Collider.GroupCollider(colliders);
 	}
 	}
 
 

+ 18 - 2
h3d/scene/Scene.hx

@@ -104,7 +104,6 @@ class Scene extends Object implements h3d.IDrawable implements hxd.SceneEvents.I
 
 
 				var minv = i.getInvPos();
 				var minv = i.getInvPos();
 				r.transform(minv);
 				r.transform(minv);
-				r.normalize();
 
 
 				// check for NaN
 				// check for NaN
 				if( r.lx != r.lx ) {
 				if( r.lx != r.lx ) {
@@ -130,13 +129,30 @@ class Scene extends Object implements h3d.IDrawable implements hxd.SceneEvents.I
 			if( hitInteractives.length == 0 )
 			if( hitInteractives.length == 0 )
 				return null;
 				return null;
 
 
+
 			if( hitInteractives.length > 1 ) {
 			if( hitInteractives.length > 1 ) {
 				for( i in hitInteractives ) {
 				for( i in hitInteractives ) {
 					var m = i.invPos;
 					var m = i.invPos;
+					var wfactor = 0.;
+
+					// adjust result with better precision
+					if( i.preciseShape != null ) {
+						r.transform(m);
+						var hit = i.preciseShape.rayIntersection(r, i.bestMatch);
+						if( hit > 0 ) {
+							var hitPoint = r.getPoint(hit);
+							i.hitPoint.x = hitPoint.x;
+							i.hitPoint.y = hitPoint.y;
+							i.hitPoint.z = hitPoint.z;
+						} else
+							wfactor = 1.;
+						r.load(saveR);
+					}
+
 					var p = i.hitPoint.clone();
 					var p = i.hitPoint.clone();
 					p.transform3x4(i.absPos);
 					p.transform3x4(i.absPos);
 					p.project(camera.m);
 					p.project(camera.m);
-					i.hitPoint.w = p.z;
+					i.hitPoint.w = p.z + wfactor;
 				}
 				}
 				hitInteractives.sort(sortHitPointByCameraDistance);
 				hitInteractives.sort(sortHitPointByCameraDistance);
 			}
 			}

+ 2 - 2
h3d/scene/Skin.hx

@@ -111,9 +111,9 @@ class Skin extends MultiMaterial {
 	}
 	}
 
 
 	override function getCollider() {
 	override function getCollider() {
-		var col = cast(super.getCollider(), h3d.col.Collider.OptimizedCollider);
+		var col = cast(primitive.getCollider(), h3d.col.Collider.OptimizedCollider);
 		cast(primitive, h3d.prim.HMDModel).loadSkin(skinData);
 		cast(primitive, h3d.prim.HMDModel).loadSkin(skinData);
-		return new h3d.col.SkinTransform(this, cast(col.b, h3d.col.PolygonBuffer));
+		return new h3d.col.SkinCollider(this, cast(col.b, h3d.col.PolygonBuffer));
 	}
 	}
 
 
 	override function calcAbsPos() {
 	override function calcAbsPos() {

+ 6 - 6
samples/Interactive.hx

@@ -7,7 +7,7 @@ class Interactive extends hxd.App {
 	var obj : h3d.scene.Object;
 	var obj : h3d.scene.Object;
 	var b : h2d.Interactive;
 	var b : h2d.Interactive;
 
 
-	function initInteract( i : h3d.scene.Interactive, m : h3d.scene.Mesh, scale = 1. ) {
+	function initInteract( i : h3d.scene.Interactive, m : h3d.scene.Mesh ) {
 		var beacon = null;
 		var beacon = null;
 		var color = m.material.color.clone();
 		var color = m.material.color.clone();
 		i.bestMatch = true;
 		i.bestMatch = true;
@@ -15,10 +15,10 @@ class Interactive extends hxd.App {
 			m.material.color.set(0, 1, 0);
 			m.material.color.set(0, 1, 0);
 			var s = new h3d.prim.Sphere(1, 32, 32);
 			var s = new h3d.prim.Sphere(1, 32, 32);
 			s.addNormals();
 			s.addNormals();
-			beacon = new h3d.scene.Mesh(s, m);
+			beacon = new h3d.scene.Mesh(s, s3d);
 			beacon.material.mainPass.enableLights = true;
 			beacon.material.mainPass.enableLights = true;
 			beacon.material.color.set(1, 0, 0);
 			beacon.material.color.set(1, 0, 0);
-			beacon.scale(0.05 * scale / m.parent.scaleX);
+			beacon.scale(0.01);
 			beacon.x = e.relX;
 			beacon.x = e.relX;
 			beacon.y = e.relY;
 			beacon.y = e.relY;
 			beacon.z = e.relZ;
 			beacon.z = e.relZ;
@@ -58,7 +58,7 @@ class Interactive extends hxd.App {
 			var color = new h3d.Vector(c, c * 0.6, c * 0.6);
 			var color = new h3d.Vector(c, c * 0.6, c * 0.6);
 			m.material.color.load(color);
 			m.material.color.load(color);
 
 
-			var interact = new h3d.scene.Interactive(m.getCollider(), m);
+			var interact = new h3d.scene.Interactive(m.getCollider(), s3d);
 			initInteract(interact, m);
 			initInteract(interact, m);
 		}
 		}
 
 
@@ -74,8 +74,8 @@ class Interactive extends hxd.App {
 
 
 		for( o in obj ) {
 		for( o in obj ) {
 			var m = o.toMesh();
 			var m = o.toMesh();
-			var i = new h3d.scene.Interactive(m.getCollider(), m);
-			initInteract(i, m, 0.2);
+			var i = new h3d.scene.Interactive(m.getCollider(), s3d);
+			initInteract(i, m);
 		}
 		}
 
 
 		b = new h2d.Interactive(150, 100, s2d);
 		b = new h2d.Interactive(150, 100, s2d);