X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=laserbrain_demo;a=blobdiff_plain;f=src%2Fgeom.cc;h=55cfed7d2fb41aa161d0e8d5d6d267bda4105fc5;hp=a6b26e88d53eae7d96b18a9a6c90dbf1d3638f87;hb=b7c92831285013b2a0783bccaf3d900545ebb5ba;hpb=a58455a92c7ecab980cbe1b7e282aeb6bfe7e889 diff --git a/src/geom.cc b/src/geom.cc index a6b26e8..55cfed7 100644 --- a/src/geom.cc +++ b/src/geom.cc @@ -1,6 +1,5 @@ -#include -#include #include +#include #include "geom.h" GeomObject::~GeomObject() @@ -19,15 +18,19 @@ Sphere::Sphere(const Vec3 ¢, 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(obj1); - const Sphere *sph2 = dynamic_cast(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(obj1); - const AABox *box2 = dynamic_cast(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(obj1); - const AABox *box2 = dynamic_cast(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 ¢, 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