#include <algorithm>
#include <float.h>
#include "geom.h"
+#include "app.h"
#define SPHERE(ptr) ((Sphere*)ptr)
#define AABOX(ptr) ((AABox*)ptr)
{
}
+bool GeomObject::valid() const
+{
+ return true;
+}
+
+void GeomObject::invalidate()
+{
+}
+
Sphere::Sphere()
{
this->radius = radius;
}
+bool Sphere::valid() const
+{
+ return radius >= 0.0f;
+}
+
+void Sphere::invalidate()
+{
+ center = Vec3(0, 0, 0);
+ radius = -1;
+}
+
bool Sphere::intersect(const Ray &ray, HitPoint *hit) const
{
float a = dot(ray.dir, ray.dir);
type = GOBJ_AABOX;
}
+bool AABox::valid() const
+{
+ return min.x <= max.x && min.y <= max.y && min.z <= max.z;
+}
+
+void AABox::invalidate()
+{
+ min = Vec3(FLT_MAX, FLT_MAX, FLT_MAX);
+ max = Vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+}
+
Vec3 AABox::get_corner(int idx) const
{
- static const Vec3 v[] = {
- Vec3(-0.5, -0.5, -0.5), Vec3(0.5, -0.5, -0.5), Vec3(0.5, -0.5, 0.5), Vec3(-0.5, -0.5, 0.5),
- Vec3(-0.5, 0.5, -0.5), Vec3(0.5, 0.5, -0.5), Vec3(0.5, 0.5, 0.5), Vec3(-0.5, 0.5, 0.5)
- };
- return v[idx] * Vec3(max - min);
+ Vec3 v[] = {min, max};
+ static const int xidx[] = {0, 1, 1, 0, 0, 1, 1, 0};
+ static const int yidx[] = {0, 0, 0, 0, 1, 1, 1, 1};
+ static const int zidx[] = {0, 0, 1, 1, 0, 0, 1, 1};
+ return Vec3(v[xidx[idx]].x, v[yidx[idx]].y, v[zidx[idx]].z);
}
bool AABox::intersect(const Ray &ray, HitPoint *hit) const
{
Vec3 param[2] = {min, max};
+#ifndef NDEBUG
+ Vec3 inv_dir;
+ if(fpexcept_enabled) {
+ inv_dir.x = ray.dir.x == 0.0f ? 1.0f : 1.0f / ray.dir.x;
+ inv_dir.y = ray.dir.y == 0.0f ? 1.0f : 1.0f / ray.dir.y;
+ inv_dir.z = ray.dir.z == 0.0f ? 1.0f : 1.0f / ray.dir.z;
+ } else {
+ inv_dir = Vec3(1.0 / ray.dir.x, 1.0 / ray.dir.y, 1.0 / ray.dir.z);
+ }
+#else
Vec3 inv_dir(1.0 / ray.dir.x, 1.0 / ray.dir.y, 1.0 / ray.dir.z);
+#endif
int sign[3] = {inv_dir.x < 0, inv_dir.y < 0, inv_dir.z < 0};
float tmin = (param[sign[0]].x - ray.origin.x) * inv_dir.x;
Box::Box()
{
+ type = GOBJ_BOX;
}
Box::Box(const AABox &aabox, const Mat4 &xform)
: xform(xform)
{
+ type = GOBJ_BOX;
min = aabox.min;
max = aabox.max;
}
+void Box::invalidate()
+{
+ AABox::invalidate();
+ xform = Mat4::identity;
+}
+
Box::Box(const Vec3 &min, const Vec3 &max)
: AABox(min, max)
{
+ type = GOBJ_BOX;
}
Box::Box(const Vec3 &min, const Vec3 &max, const Mat4 &xform)
: AABox(min, max), xform(xform)
{
+ type = GOBJ_BOX;
}
// XXX all this shit is completely untested
Box::Box(const Vec3 &pos, const Vec3 &vi, const Vec3 &vj, const Vec3 &vk)
{
+ type = GOBJ_BOX;
float ilen = length(vi);
float jlen = length(vj);
float klen = length(vk);
Box::Box(const Vec3 *varr, int vcount)
{
+ type = GOBJ_BOX;
calc_bounding_aabox(this, varr, vcount);
}
Vec3 Box::get_corner(int idx) const
{
- static const Vec3 v[] = {
- Vec3(-0.5, -0.5, -0.5), Vec3(0.5, -0.5, -0.5), Vec3(0.5, -0.5, 0.5), Vec3(-0.5, -0.5, 0.5),
- Vec3(-0.5, 0.5, -0.5), Vec3(0.5, 0.5, -0.5), Vec3(0.5, 0.5, 0.5), Vec3(-0.5, 0.5, 0.5)
- };
-
- return xform * (v[idx] * Vec3(max - min));
+ return xform * AABox::get_corner(idx);
}
bool Box::intersect(const Ray &ray, HitPoint *hit) const
Plane::Plane()
: normal(0.0, 1.0, 0.0)
{
+ type = GOBJ_PLANE;
}
Plane::Plane(const Vec3 &p, const Vec3 &norm)
: pt(p)
{
+ type = GOBJ_PLANE;
normal = normalize(norm);
}
Plane::Plane(const Vec3 &p1, const Vec3 &p2, const Vec3 &p3)
: pt(p1)
{
+ type = GOBJ_PLANE;
normal = normalize(cross(p2 - p1, p3 - p1));
}
Plane::Plane(const Vec3 &normal, float dist)
{
+ type = GOBJ_PLANE;
this->normal = normalize(normal);
pt = this->normal * dist;
}
Disc::Disc()
{
+ type = GOBJ_DISC;
radius = 1.0;
}
Disc::Disc(const Vec3 &pt, const Vec3 &normal, float rad)
: Plane(pt, normal)
{
+ type = GOBJ_DISC;
radius = rad;
}
Disc::Disc(const Vec3 &normal, float dist, float rad)
: Plane(normal, dist)
{
+ type = GOBJ_DISC;
radius = rad;
}
+bool Disc::valid() const
+{
+ return radius >= 0.0f;
+}
+
+void Disc::invalidate()
+{
+ radius = -1;
+}
+
bool Disc::intersect(const Ray &ray, HitPoint *hit) const
{
HitPoint phit;
bool calc_bounding_sphere(Sphere *sph, const GeomObject *obj)
{
+ if(!obj->valid()) {
+ sph->invalidate();
+ return true;
+ }
+
switch(obj->type) {
case GOBJ_SPHERE:
*sph = *(Sphere*)obj;
bool calc_bounding_aabox(AABox *box, const GeomObject *obj)
{
+ if(!obj->valid()) {
+ box->invalidate();
+ return true;
+ }
+
switch(obj->type) {
case GOBJ_AABOX:
*box = *(AABox*)obj;
bool calc_bounding_box(Box *box, const GeomObject *obj)
{
+ if(!obj->valid()) {
+ box->invalidate();
+ return true;
+ }
+
switch(obj->type) {
case GOBJ_BOX:
*box = *(Box*)obj;
GOBJ_SPHERE,
GOBJ_AABOX,
GOBJ_BOX,
- GOBJ_PLANE
+ GOBJ_PLANE,
+ GOBJ_DISC
};
class GeomObject;
GeomObject();
virtual ~GeomObject();
+ virtual bool valid() const;
+ virtual void invalidate();
+
virtual bool intersect(const Ray &ray, HitPoint *hit = 0) const = 0;
virtual bool contains(const Vec3 &pt) const = 0;
Sphere();
Sphere(const Vec3 ¢er, float radius);
+ virtual bool valid() const;
+ virtual void invalidate();
+
virtual bool intersect(const Ray &ray, HitPoint *hit = 0) const;
virtual bool contains(const Vec3 &pt) const;
AABox();
AABox(const Vec3 &min, const Vec3 &max);
+ virtual bool valid() const;
+ virtual void invalidate();
+
virtual Vec3 get_corner(int idx) const;
virtual bool intersect(const Ray &ray, HitPoint *hit = 0) const;
Box(const Vec3 &pos, const Vec3 &vi, const Vec3 &vj, const Vec3 &vk);
Box(const Vec3 *varr, int vcount);
+ virtual void invalidate();
+
virtual Vec3 get_corner(int idx) const;
virtual bool intersect(const Ray &ray, HitPoint *hit = 0) const;
Disc(const Vec3 &pt, const Vec3 &normal, float rad);
Disc(const Vec3 &normal, float dist, float rad);
+ virtual bool valid() const;
+ virtual void invalidate();
+
virtual bool intersect(const Ray &ray, HitPoint *hit = 0) const;
//! true if the projection of pt to the plane is contained within the disc radius
virtual bool contains(const Vec3 &pt) const;
--- /dev/null
+#include "geomdraw.h"
+#include "opengl.h"
+#include "logger.h"
+#include "shader.h"
+
+static void draw_sphere(const Sphere *sph);
+static void draw_box(const Box *box);
+static void draw_plane(const Plane *plane);
+
+void draw_geom_object(const GeomObject *gobj)
+{
+ switch(gobj->type) {
+ case GOBJ_SPHERE:
+ draw_sphere((Sphere*)gobj);
+ break;
+
+ case GOBJ_AABOX:
+ {
+ Box box = Box(*(AABox*)gobj, Mat4::identity);
+ draw_box(&box);
+ }
+ break;
+
+ case GOBJ_BOX:
+ draw_box((Box*)gobj);
+ break;
+
+ case GOBJ_PLANE:
+ draw_plane((Plane*)gobj);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void draw_sphere(const Sphere *sph)
+{
+ // TODO
+ warning_log("draw_sphere unimplemented\n");
+}
+
+static void draw_box(const Box *box)
+{
+ static const int edges[][2] = {
+ {0, 1}, {1, 2}, {2, 3}, {3, 0},
+ {4, 5}, {5, 6}, {6, 7}, {7, 4},
+ {0, 4}, {1, 5}, {2, 6}, {3, 7}
+ };
+
+ bind_shader(0);
+
+ glPushAttrib(GL_ENABLE_BIT);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glMultMatrixf(box->xform[0]);
+
+ glBegin(GL_LINES);
+ glColor3f(1, 1, 0);
+ for(int i=0; i<12; i++) {
+ Vec3 a = box->get_corner(edges[i][0]);
+ Vec3 b = box->get_corner(edges[i][1]);
+
+ glVertex3f(a.x, a.y, a.z);
+ glVertex3f(b.x, b.y, b.z);
+ }
+ glEnd();
+
+ glPopMatrix();
+ glPopAttrib();
+}
+
+static void draw_plane(const Plane *plane)
+{
+ // TODO
+ warning_log("draw_plane unimplemented\n");
+}