assimp
[laserbrain_demo] / src / geom.cc
index a6b26e8..55cfed7 100644 (file)
@@ -1,6 +1,5 @@
-#include <assert.h>
-#include <float.h>
 #include <algorithm>
+#include <float.h>
 #include "geom.h"
 
 GeomObject::~GeomObject()
@@ -19,15 +18,19 @@ Sphere::Sphere(const Vec3 &cent, float radius)
        this->radius = radius;
 }
 
-void Sphere::set_union(const GeomObject *obj1, const GeomObject *obj2)
+GeomObjectType Sphere::get_type() const
 {
-       const Sphere *sph1 = dynamic_cast<const Sphere*>(obj1);
-       const Sphere *sph2 = dynamic_cast<const Sphere*>(obj2);
+       return GOBJ_SPHERE;
+}
 
-       if(!sph1 || !sph2) {
+void Sphere::set_union(const GeomObject *obj1, const GeomObject *obj2)
+{
+       if(obj1->get_type() != GOBJ_SPHERE || obj2->get_type() != GOBJ_SPHERE) {
                fprintf(stderr, "Sphere::set_union: arguments must be spheres");
                return;
        }
+       const Sphere *sph1 = (const Sphere*)obj1;
+       const Sphere *sph2 = (const Sphere*)obj2;
 
        float dist = length(sph1->center - sph2->center);
        float surf_dist = dist - (sph1->radius + sph2->radius);
@@ -85,6 +88,15 @@ bool Sphere::intersect(const Ray &ray, HitPoint *hit) const
        return true;
 }
 
+bool Sphere::contains(const Vec3 &pt) const
+{
+       return length_sq(pt - center) <= radius * radius;
+}
+
+float Sphere::distance(const Vec3 &v) const
+{
+       return length(v - center) - radius;
+}
 
 AABox::AABox()
 {
@@ -95,15 +107,19 @@ AABox::AABox(const Vec3 &vmin, const Vec3 &vmax)
 {
 }
 
-void AABox::set_union(const GeomObject *obj1, const GeomObject *obj2)
+GeomObjectType AABox::get_type() const
 {
-       const AABox *box1 = dynamic_cast<const AABox*>(obj1);
-       const AABox *box2 = dynamic_cast<const AABox*>(obj2);
+       return GOBJ_AABOX;
+}
 
-       if(!box1 || !box2) {
+void AABox::set_union(const GeomObject *obj1, const GeomObject *obj2)
+{
+       if(obj1->get_type() != GOBJ_AABOX || obj2->get_type() != GOBJ_AABOX) {
                fprintf(stderr, "AABox::set_union: arguments must be AABoxes too\n");
                return;
        }
+       const AABox *box1 = (const AABox*)obj1;
+       const AABox *box2 = (const AABox*)obj2;
 
        min.x = std::min(box1->min.x, box2->min.x);
        min.y = std::min(box1->min.y, box2->min.y);
@@ -116,13 +132,12 @@ void AABox::set_union(const GeomObject *obj1, const GeomObject *obj2)
 
 void AABox::set_intersection(const GeomObject *obj1, const GeomObject *obj2)
 {
-       const AABox *box1 = dynamic_cast<const AABox*>(obj1);
-       const AABox *box2 = dynamic_cast<const AABox*>(obj2);
-
-       if(!box1 || !box2) {
+       if(obj1->get_type() != GOBJ_AABOX || obj2->get_type() != GOBJ_AABOX) {
                fprintf(stderr, "AABox::set_intersection: arguments must be AABoxes too\n");
                return;
        }
+       const AABox *box1 = (const AABox*)obj1;
+       const AABox *box2 = (const AABox*)obj2;
 
        for(int i=0; i<3; i++) {
                min[i] = std::max(box1->min[i], box2->min[i]);
@@ -197,9 +212,20 @@ bool AABox::intersect(const Ray &ray, HitPoint *hit) const
                return true;
        }
        return false;
+}
+
+bool AABox::contains(const Vec3 &v) const
+{
+       return v.x >= min.x && v.y >= min.y && v.z >= min.z &&
+               v.x <= max.x && v.y <= max.y && v.z <= max.z;
+}
 
+float AABox::distance(const Vec3 &v) const
+{
+       return 0.0;     // TODO
 }
 
+
 Plane::Plane()
        : normal(0.0, 1.0, 0.0)
 {
@@ -223,6 +249,11 @@ Plane::Plane(const Vec3 &normal, float dist)
        pt = this->normal * dist;
 }
 
+GeomObjectType Plane::get_type() const
+{
+       return GOBJ_PLANE;
+}
+
 void Plane::set_union(const GeomObject *obj1, const GeomObject *obj2)
 {
        fprintf(stderr, "Plane::set_union undefined\n");
@@ -252,84 +283,12 @@ bool Plane::intersect(const Ray &ray, HitPoint *hit) const
        return true;
 }
 
-float sphere_distance(const Vec3 &cent, float rad, const Vec3 &pt)
-{
-       return length(pt - cent) - rad;
-}
-
-// TODO version which takes both radii into account
-float capsule_distance(const Vec3 &a, float ra, const Vec3 &b, float rb, const Vec3 &pt)
+bool Plane::contains(const Vec3 &v) const
 {
-       Vec3 ab_dir = b - a;
-       float ab_len_sq = length_sq(ab_dir);
-
-       if(fabs(ab_len_sq) < 1e-5) {
-               // if a == b, the capsule is a sphere with radius the maximum of the capsule radii
-               return sphere_distance(a, std::max(ra, rb), pt);
-       }
-       float ab_len = sqrt(ab_len_sq);
-
-       Vec3 ap_dir = pt - a;
-
-       float t = dot(ap_dir, ab_dir / ab_len) / ab_len;
-       if(t < 0.0) {
-               return sphere_distance(a, ra, pt);
-       }
-       if(t >= 1.0) {
-               return sphere_distance(b, rb, pt);
-       }
-
-       Vec3 pproj = a + ab_dir * t;
-       return length(pproj - pt) - ra;
+       return dot(v, normal) <= 0.0;
 }
 
-#if 0
-float capsule_distance(const Vec3 &a, float ra, const Vec3 &b, float rb, const Vec3 &pt)
+float Plane::distance(const Vec3 &v) const
 {
-       Vec3 ab_dir = b - a;
-
-       if(fabs(length_sq(ab_dir)) < 1e-5) {
-               // if a == b, the capsule is a sphere with radius the maximum of the capsule radii
-               return sphere_distance(a, std::max(ra, rb), pt);
-       }
-       float ab_len = length(ab_dir);
-
-       Vec3 ap_dir = pt - a;
-       Vec3 rotaxis = normalize(cross(ab_dir, ap_dir));
-
-       Mat4 rmat;
-       rmat.set_rotation(rotaxis, M_PI / 2.0);
-       Vec3 right = rmat * ab_dir / ab_len;
-
-       // XXX I think this check is redundant, always false, due to the cross product order
-       //assert(dot(right, ab_dir) >= 0.0);
-       if(dot(right, ab_dir) < 0.0) {
-               right = -right;
-       }
-       Vec3 aa = a + right * ra;
-       Vec3 bb = b + right * rb;
-
-       // project pt to the line segment bb-aa, see if the projection lies within the interval [0, 1)
-       Vec3 aabb_dir = bb - aa;
-       float aabb_len = length(aabb_dir);
-       Vec3 aap_dir = pt - aa;
-
-       float t = dot(aap_dir, aabb_dir / aabb_len) / aabb_len;
-       if(t < 0.0) {
-               return sphere_distance(a, ra, pt);
-       }
-       if(t >= 1.0) {
-               return sphere_distance(b, rb, pt);
-       }
-
-       Vec3 ppt = aa + aabb_dir * t;
-       Vec3 norm = ppt - pt;
-       float dist = length(norm);
-
-       if(dot(norm, right) < 0.0) {
-               // inside the cone
-               dist = -dist;
-       }
-       return dist;
+       return dot(v - pt, normal);
 }
-#endif