using aabb planes as mirror planes
[laserbrain_demo] / src / geom.cc
index 5fc3dce..1813eea 100644 (file)
@@ -1,5 +1,6 @@
-#include <algorithm>
+#include <stdlib.h>
 #include <float.h>
+#include <algorithm>
 #include "geom.h"
 #include "app.h"
 
@@ -26,6 +27,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 +104,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()
@@ -135,6 +145,28 @@ Vec3 AABox::get_corner(int idx) const
        return Vec3(v[xidx[idx]].x, v[yidx[idx]].y, v[zidx[idx]].z);
 }
 
+Plane AABox::get_plane(int pidx) const
+{
+       switch(pidx) {
+       case AABOX_PLANE_PX:
+               return Plane(Vec3(max.x, 0, 0), Vec3(1, 0, 0));
+       case AABOX_PLANE_NX:
+               return Plane(Vec3(min.x, 0, 0), Vec3(-1, 0, 0));
+       case AABOX_PLANE_PY:
+               return Plane(Vec3(0, max.x, 0), Vec3(0, 1, 0));
+       case AABOX_PLANE_NY:
+               return Plane(Vec3(0, min.x, 0), Vec3(0, -1, 0));
+       case AABOX_PLANE_PZ:
+               return Plane(Vec3(0, 0, max.z), Vec3(0, 0, 1));
+       case AABOX_PLANE_NZ:
+               return Plane(Vec3(0, 0, min.z), Vec3(0, 0, -1));
+       default:
+               break;
+       }
+       abort();
+       return Plane();
+}
+
 bool AABox::intersect(const Ray &ray, HitPoint *hit) const
 {
        Vec3 param[2] = {min, max};
@@ -217,14 +249,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 +360,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 +431,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 +492,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 +764,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;
+}