Browse Source

added h3d.col.HeightMap

ncannasse 6 years ago
parent
commit
e24a6e4df2
1 changed files with 88 additions and 0 deletions
  1. 88 0
      h3d/col/HeightMap.hx

+ 88 - 0
h3d/col/HeightMap.hx

@@ -0,0 +1,88 @@
+package h3d.col;
+
+/**
+	This is an helper class to define a heightmap-based collider.
+	In order to use, you need to extends this class and override the getZ method
+	in order to return appropriate Z value based on X and Y coordinates.
+**/
+class HeightMap implements Collider {
+
+	/**
+		When performing raycast check, tells by how much step we advance.
+		If this is too small, raycast check will be too expensive.
+		If this is too big, we might step through a hip without noticing.
+		Default : 1.0
+	**/
+	public var step : Float = 1.0;
+
+	/**
+		Tells which precision is required for the result.
+		We will iterate until we have reach the given precision.
+	**/
+	public var precision : Float = 1e-2;
+
+	/**
+		Returns the height value at given coordinates.
+	**/
+	public function getZ( x : Float, y : Float ) : Float {
+		throw "Not implemented: requires override";
+	}
+
+	public inline function contains( pt : Point ) : Bool {
+		return getZ(pt.x, pt.y) > pt.z;
+	}
+
+	public function inFrustum( f : Frustum ) : Bool {
+		throw "Not implemented : is infinite";
+	}
+
+	public function inSphere( s : Sphere ) : Bool {
+		throw "Not implemented : is infinite";
+	}
+
+	public function rayIntersection( r : Ray, bestMatch : Bool ) : Float {
+		var px = r.px, py = r.py, pz = r.pz;
+		var lx = r.lx, ly = r.ly, lz = r.lz;
+
+		// if we are looking up or almost razing, consider out
+		if( lz >= -precision )
+			return -1;
+
+		// if we are already under the heightmap, consider out
+		var hprev = getZ(px,py);
+		if( hprev > pz )
+			return -1;
+
+		var dist = step;
+		while( true ) {
+			var x = px + lx * dist;
+			var y = py + ly * dist;
+			var z = pz + lz * dist;
+			var h = getZ(x,y);
+			if( h > z ) {
+				// if( !bestMatch ) : TODO : calculate immediate approx
+				break;
+			}
+			hprev = h;
+			dist += step;
+		}
+
+		var dmin = dist - step;
+		var dmax = dist;
+		var prec = precision;
+		while( true ) {
+			var d = (dmin + dmax) * 0.5;
+			if( dmax - dmin < prec ) return d;
+			var x = px + lx * dist;
+			var y = py + ly * dist;
+			var z = pz + lz * dist;
+			var h = getZ(x,y);
+			if( h > z ) {
+				dmax = d;
+			} else {
+				dmin = d;
+			}
+		}
+	}
+
+}