X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=laserbrain_demo;a=blobdiff_plain;f=src%2Fgeom.cc;h=a96066fba377a03fc754a7f74fc7eac8398ad35a;hp=5fc3dce208cc6385f02f4b5cd20ee183fa1a48e7;hb=74034a459f47934ef60ba295033b9cb7e597d32a;hpb=03085a16aa2fef785083fa3921be83015e08b290 diff --git a/src/geom.cc b/src/geom.cc index 5fc3dce..a96066f 100644 --- a/src/geom.cc +++ b/src/geom.cc @@ -1,5 +1,6 @@ -#include +#include #include +#include #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,29 @@ 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 +{ + Vec3 c = (max - min) * 0.5f; + switch(pidx) { + case AABOX_PLANE_PX: + return Plane(Vec3(max.x, c.y, c.z), Vec3(1, 0, 0)); + case AABOX_PLANE_NX: + return Plane(Vec3(min.x, c.y, c.z), Vec3(-1, 0, 0)); + case AABOX_PLANE_PY: + return Plane(Vec3(c.x, max.x, c.z), Vec3(0, 1, 0)); + case AABOX_PLANE_NY: + return Plane(Vec3(c.x, min.x, c.z), Vec3(0, -1, 0)); + case AABOX_PLANE_PZ: + return Plane(Vec3(c.x, c.y, max.z), Vec3(0, 0, 1)); + case AABOX_PLANE_NZ: + return Plane(Vec3(c.x, c.y, 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 +250,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 +361,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 +432,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 +493,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 +765,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; +}