hand-tracking and exhibits part one
[laserbrain_demo] / src / geom.cc
index 5fc3dce..3a287a6 100644 (file)
@@ -26,6 +26,15 @@ void GeomObject::invalidate()
 {
 }
 
+float GeomObject::distance(const Vec3 &v) const
+{
+       return sqrt(distance_sq(v));
+}
+
+float GeomObject::signed_distance(const Vec3 &v) const
+{
+       return sqrt(signed_distance_sq(v));
+}
 
 Sphere::Sphere()
 {
@@ -94,14 +103,14 @@ bool Sphere::contains(const Vec3 &pt) const
        return length_sq(pt - center) <= radius * radius;
 }
 
-float Sphere::distance(const Vec3 &v) const
+float Sphere::distance_sq(const Vec3 &v) const
 {
-       return std::max(length(v - center) - radius, 0.0f);
+       return std::max(length_sq(v - center) - radius * radius, 0.0f);
 }
 
-float Sphere::signed_distance(const Vec3 &v) const
+float Sphere::signed_distance_sq(const Vec3 &v) const
 {
-       return length(v - center) - radius;
+       return length_sq(v - center) - radius * radius;
 }
 
 AABox::AABox()
@@ -217,14 +226,31 @@ bool AABox::contains(const Vec3 &v) const
                v.x <= max.x && v.y <= max.y && v.z <= max.z;
 }
 
-float AABox::distance(const Vec3 &v) const
+#define SQ(x)  ((x) * (x))
+float AABox::distance_sq(const Vec3 &v) const
 {
-       return 0.0;     // TODO
+       float dsq = 0.0f;
+
+       for(int i=0; i<3; i++) {
+               if(v[i] < min[i]) dsq += SQ(min[i] - v[i]);
+               if(v[i] > max[i]) dsq += SQ(v[i] - max[i]);
+       }
+       return dsq;
 }
 
-float AABox::signed_distance(const Vec3 &v) const
+float AABox::signed_distance_sq(const Vec3 &v) const
 {
-       return 0.0;     // TODO
+       if(!contains(v)) {
+               return distance_sq(v);
+       }
+
+       float dsq = 0.0f;
+       for(int i=0; i<3; i++) {
+               float dmin = v[i] - min[i];
+               float dmax = max[i] - v[i];
+               dsq -= dmin < dmax ? SQ(dmin) : SQ(dmax);
+       }
+       return dsq;
 }
 
 Box::Box()
@@ -311,12 +337,12 @@ bool Box::contains(const Vec3 &pt) const
        return AABox::contains(inverse(xform) * pt);
 }
 
-float Box::distance(const Vec3 &v) const
+float Box::distance_sq(const Vec3 &v) const
 {
        return 0.0f;    // TODO
 }
 
-float Box::signed_distance(const Vec3 &v) const
+float Box::signed_distance_sq(const Vec3 &v) const
 {
        return 0.0f;    // TODO
 }
@@ -382,6 +408,18 @@ float Plane::signed_distance(const Vec3 &v) const
        return dot(v - pt, normal);
 }
 
+float Plane::distance_sq(const Vec3 &v) const
+{
+       float d = distance(v);
+       return d * d;
+}
+
+float Plane::signed_distance_sq(const Vec3 &v) const
+{
+       float d = distance(v);
+       return dot(v, normal) >= 0.0f ? d * d : -(d * d);
+}
+
 
 Disc::Disc()
 {
@@ -431,12 +469,12 @@ bool Disc::contains(const Vec3 &pt) const
        return length_sq(pj - this->pt) <= radius * radius;
 }
 
-float Disc::distance(const Vec3 &v) const
+float Disc::distance_sq(const Vec3 &v) const
 {
        return 0.0;     // TODO
 }
 
-float Disc::signed_distance(const Vec3 &v) const
+float Disc::signed_distance_sq(const Vec3 &v) const
 {
        return 0.0;     // TODO
 }
@@ -703,3 +741,8 @@ bool intersect_aabox_aabox(AABox *res, const AABox &a, const AABox &b)
        }
        return res->min.x != res->max.x && res->min.y != res->max.y && res->min.z != res->max.z;
 }
+
+bool collision_sphere_aabox(const Sphere &s, const AABox &b)
+{
+       return b.distance_sq(s.center) <= s.radius * s.radius;
+}