Преглед изворни кода

changed rayInterest to return float distance, added bestMatch

ncannasse пре 8 година
родитељ
комит
270b7c81d8
7 измењених фајлова са 88 додато и 39 уклоњено
  1. 3 5
      h3d/col/Bounds.hx
  2. 46 7
      h3d/col/Collider.hx
  3. 14 14
      h3d/col/Polygon.hx
  4. 4 0
      h3d/col/Ray.hx
  5. 4 6
      h3d/col/Sphere.hx
  6. 6 0
      h3d/scene/Interactive.hx
  7. 11 7
      h3d/scene/Scene.hx

+ 3 - 5
h3d/col/Bounds.hx

@@ -46,7 +46,7 @@ class Bounds implements Collider {
 		return dd + rr - p.d*2;
 		return dd + rr - p.d*2;
 	}
 	}
 
 
-	public function rayIntersection( r : Ray, ?p : Point ) : Null<Point> {
+	public function rayIntersection( r : Ray, bestMatch : Bool ) : Float {
 		var minTx = (xMin - r.px) / r.lx;
 		var minTx = (xMin - r.px) / r.lx;
 		var minTy = (yMin - r.py) / r.ly;
 		var minTy = (yMin - r.py) / r.ly;
 		var minTz = (zMin - r.pz) / r.lz;
 		var minTz = (zMin - r.pz) / r.lz;
@@ -64,11 +64,9 @@ class Bounds implements Collider {
 		var minmax = Math.min( Math.min(realMaxTx, realMaxTy), realMaxTz);
 		var minmax = Math.min( Math.min(realMaxTx, realMaxTy), realMaxTz);
 		var maxmin = Math.max( Math.max(realMinTx, realMinTy), realMinTz);
 		var maxmin = Math.max( Math.max(realMinTx, realMinTy), realMinTz);
 
 
-		if(minmax < maxmin)	return null;
+		if(minmax < maxmin)	return -1;
 
 
-		if( p == null ) p = new Point();
-		p.set(r.px + maxmin * r.lx , r.py + maxmin * r.ly, r.pz + maxmin * r.lz);
-		return p;
+		return maxmin;
 	}
 	}
 
 
 	/**
 	/**

+ 46 - 7
h3d/col/Collider.hx

@@ -2,7 +2,10 @@ package h3d.col;
 
 
 interface Collider {
 interface Collider {
 
 
-	public function rayIntersection( r : Ray, ?p : Point ) : Null<Point>;
+	/**
+		Returns the distance of intersection between the ray and the collider, or negative if no collision.
+	**/
+	public function rayIntersection( r : Ray, bestMatch : Bool ) : Float;
 	public function contains( p : Point ) : Bool;
 	public function contains( p : Point ) : Bool;
 	public function inFrustum( mvp : h3d.Matrix ) : Bool;
 	public function inFrustum( mvp : h3d.Matrix ) : Bool;
 
 
@@ -19,18 +22,54 @@ class OptimizedCollider implements Collider {
 		this.b = b;
 		this.b = b;
 	}
 	}
 
 
-	public function rayIntersection( r : Ray, ?p : Point ) : Null<Point> {
-		if( a.rayIntersection(r, p) == null )
-			return null;
-		return b.rayIntersection(r, p);
+	public function rayIntersection( r : Ray, bestMatch : Bool ) : Float {
+		if( a.rayIntersection(r, bestMatch) < 0 )
+			return -1;
+		return b.rayIntersection(r, bestMatch);
 	}
 	}
-	
+
 	public function contains( p : Point ) {
 	public function contains( p : Point ) {
 		return a.contains(p) && b.contains(p);
 		return a.contains(p) && b.contains(p);
 	}
 	}
-	
+
 	public function inFrustum( mvp : h3d.Matrix ) {
 	public function inFrustum( mvp : h3d.Matrix ) {
 		return a.inFrustum(mvp) && b.inFrustum(mvp);
 		return a.inFrustum(mvp) && b.inFrustum(mvp);
 	}
 	}
 
 
 }
 }
+
+class GroupCollider implements Collider {
+
+	public var colliders : Array<Collider>;
+
+	public function new(colliders) {
+		this.colliders = colliders;
+	}
+
+	public function rayIntersection( r : Ray, bestMatch : Bool ) : Float {
+		var best = -1.;
+		for( c in colliders ) {
+			var d = c.rayIntersection(r, bestMatch);
+			if( d >= 0 ) {
+				if( !bestMatch ) return d;
+				if( best < 0 || d < best ) best = d;
+			}
+		}
+		return best;
+	}
+
+	public function contains( p : Point ) {
+		for( c in colliders )
+			if( c.contains(p) )
+				return true;
+		return false;
+	}
+
+	public function inFrustum( mvp : h3d.Matrix ) {
+		for( c in colliders )
+			if( c.inFrustum(mvp) )
+				return true;
+		return false;
+	}
+
+}

+ 14 - 14
h3d/col/Polygon.hx

@@ -66,24 +66,20 @@ class TriPlane implements Collider {
 		return false;
 		return false;
 	}
 	}
 
 
-	inline public function rayIntersection( r : Ray, ?pt : Point ) @:privateAccess {
+	inline public function rayIntersection( r : Ray, bestMatch : Bool ) @:privateAccess {
 		var dr = r.lx * nx + r.ly * ny + r.lz * nz;
 		var dr = r.lx * nx + r.ly * ny + r.lz * nz;
-		if( dr > 0 ) // backface culling
-			return null;
+		if( dr >= 0 ) // backface culling
+			return -1.;
 		var nd = d - (r.px * nx + r.py * ny + r.pz * nz);
 		var nd = d - (r.px * nx + r.py * ny + r.pz * nz);
 		var k = nd / dr;
 		var k = nd / dr;
 		if( k < 0 )
 		if( k < 0 )
-			return null;
+			return -1;
 		var px = r.px + r.lx * k;
 		var px = r.px + r.lx * k;
 		var py = r.py + r.ly * k;
 		var py = r.py + r.ly * k;
 		var pz = r.pz + r.lz * k;
 		var pz = r.pz + r.lz * k;
 		if( !isPointInTriangle(px, py, pz) )
 		if( !isPointInTriangle(px, py, pz) )
-			return null;
-		if( pt == null ) pt = new Point();
-		pt.x = px;
-		pt.y = py;
-		pt.z = pz;
-		return pt;
+			return -1;
+		return k;
 	}
 	}
 
 
 	inline function isPointInTriangle( x : Float, y : Float, z : Float ) {
 	inline function isPointInTriangle( x : Float, y : Float, z : Float ) {
@@ -148,14 +144,18 @@ class Polygon implements Collider {
 		return true;
 		return true;
 	}
 	}
 
 
-	public function rayIntersection( r : Ray, ?pt : Point ) {
+	public function rayIntersection( r : Ray, bestMatch : Bool ) {
 		var t = triPlanes;
 		var t = triPlanes;
+		var best = -1.;
 		while( t != null ) {
 		while( t != null ) {
-			var p = t.rayIntersection(r, pt);
-			if( p != null ) return p;
+			var d = t.rayIntersection(r, bestMatch);
+			if( d >= 0 ) {
+				if( !bestMatch ) return d;
+				if( best < 0 || d < best ) best = d;
+			}
 			t = t.next;
 			t = t.next;
 		}
 		}
-		return null;
+		return best;
 	}
 	}
 
 
 	public function inFrustum( m : h3d.Matrix ) {
 	public function inFrustum( m : h3d.Matrix ) {

+ 4 - 0
h3d/col/Ray.hx

@@ -63,6 +63,10 @@ class Ray {
 		return new Point(lx, ly, lz);
 		return new Point(lx, ly, lz);
 	}
 	}
 
 
+	public inline function getPoint( distance : Float ) {
+		return new Point(px + distance * lx, py + distance * ly, pz + distance * lz);
+	}
+
 	public function toString() {
 	public function toString() {
 		return "Ray{" + getPos() + "," + getDir() + "}";
 		return "Ray{" + getPos() + "," + getDir() + "}";
 	}
 	}

+ 4 - 6
h3d/col/Sphere.hx

@@ -17,7 +17,7 @@ class Sphere implements Collider {
 	public inline function getCenter() {
 	public inline function getCenter() {
 		return new Point(x, y, z);
 		return new Point(x, y, z);
 	}
 	}
-	
+
 	public inline function contains( p : Point ) {
 	public inline function contains( p : Point ) {
 		var dx = p.x - x;
 		var dx = p.x - x;
 		var dy = p.y - y;
 		var dy = p.y - y;
@@ -25,7 +25,7 @@ class Sphere implements Collider {
 		return dx * dx + dy * dy + dz * dz < r * r;
 		return dx * dx + dy * dy + dz * dz < r * r;
 	}
 	}
 
 
-	public function rayIntersection( r : Ray, ?p : Point ) : Null<Point> {
+	public function rayIntersection( r : Ray, bestMatch : Bool ) : Float {
 		var r2 = this.r * this.r;
 		var r2 = this.r * this.r;
 		var px = r.px + r.lx;
 		var px = r.px + r.lx;
 		var py = r.py + r.ly;
 		var py = r.py + r.ly;
@@ -36,13 +36,11 @@ class Sphere implements Collider {
 		var c = (x * x + y * y + z * z) + (px * px + py * py + pz * pz) - 2 * (x * px + y * py + z * pz) - r2;
 		var c = (x * x + y * y + z * z) + (px * px + py * py + pz * pz) - 2 * (x * px + y * py + z * pz) - r2;
 
 
 		var d = b * b - 4 * a * c;
 		var d = b * b - 4 * a * c;
-		if( d < 0 )	return null;
+		if( d < 0 )	return -1;
 
 
 		d = Math.sqrt(d);
 		d = Math.sqrt(d);
 		var t = ( -b + d) / (2 * a);
 		var t = ( -b + d) / (2 * a);
-		if( p == null ) p = new Point();
-		p.set(px - t * r.lx , py - t * r.ly, pz - t * r.lz);
-		return p;
+		return 1 - t;
 	}
 	}
 
 
 	public function inFrustum( mvp : Matrix ) {
 	public function inFrustum( mvp : Matrix ) {

+ 6 - 0
h3d/scene/Interactive.hx

@@ -13,6 +13,12 @@ class Interactive extends Object implements hxd.SceneEvents.Interactive {
 	**/
 	**/
 	public var propagateEvents : Bool = false;
 	public var propagateEvents : Bool = false;
 	public var enableRightButton : Bool;
 	public var enableRightButton : Bool;
+
+	/**
+		Is it required to find the best hit point in a complex mesh or any hit possible point will be enough (default = false, faster).
+	**/
+	public var bestMatch : Bool;
+
 	var scene : Scene;
 	var scene : Scene;
 	var mouseDownButton : Int = -1;
 	var mouseDownButton : Int = -1;
 
 

+ 11 - 7
h3d/scene/Scene.hx

@@ -95,7 +95,6 @@ class Scene extends Object implements h3d.IDrawable implements hxd.SceneEvents.I
 			var r = h3d.col.Ray.fromPoints(p0.toPoint(), p1.toPoint());
 			var r = h3d.col.Ray.fromPoints(p0.toPoint(), p1.toPoint());
 			var saveR = r.clone();
 			var saveR = r.clone();
 
 
-			var hitTmp = new h3d.col.Point();
 			for( i in interactives ) {
 			for( i in interactives ) {
 
 
 				var p : h3d.scene.Object = i;
 				var p : h3d.scene.Object = i;
@@ -113,13 +112,18 @@ class Scene extends Object implements h3d.IDrawable implements hxd.SceneEvents.I
 					continue;
 					continue;
 				}
 				}
 
 
-				var hit = i.shape.rayIntersection(r, hitTmp);
+				var hit = i.shape.rayIntersection(r, i.bestMatch);
+				if( hit < 0 ) {
+					r.load(saveR);
+					continue;
+				}
+
+				var hitPoint = r.getPoint(hit);
 				r.load(saveR);
 				r.load(saveR);
-				if( hit == null ) continue;
 
 
-				i.hitPoint.x = hit.x;
-				i.hitPoint.y = hit.y;
-				i.hitPoint.z = hit.z;
+				i.hitPoint.x = hitPoint.x;
+				i.hitPoint.y = hitPoint.y;
+				i.hitPoint.z = hitPoint.z;
 				hitInteractives.push(i);
 				hitInteractives.push(i);
 			}
 			}
 
 
@@ -222,7 +226,7 @@ class Scene extends Object implements h3d.IDrawable implements hxd.SceneEvents.I
 		iterVisibleMeshes(function(m) {
 		iterVisibleMeshes(function(m) {
 			if( m.primitive == null ) return;
 			if( m.primitive == null ) return;
 			ray.transform(m.getInvPos());
 			ray.transform(m.getInvPos());
-			if( m.primitive.getBounds().rayIntersection(ray) != null )
+			if( m.primitive.getBounds().rayIntersection(ray,false) >= 0 )
 				ctx.emitPass(m.material.mainPass, m);
 				ctx.emitPass(m.material.mainPass, m);
 			ray.load(savedRay);
 			ray.load(savedRay);
 		});
 		});