|
@@ -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;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|