/* * CS5600 University of Utah * Charles McGarvey * mcgarvey@eng.utah.edu */ #ifndef _TRIANGLE_HH_ #define _TRIANGLE_HH_ #include "element.hh" namespace rt { /* * A class for a triangle object. */ class triangle : public element { vec_t a; vec_t b; vec_t c; public: triangle(vec_t a, vec_t b, vec_t c) : a(a), b(b), c(c) {} virtual ~triangle() {} virtual bool intersect(ray_t ray, contact_t& hit) const { plane p = plane(a, b, c); if (!p.intersect(ray, hit)) { return false; } scal_t bc[3]; if (!barycentric(bc, hit.p)) { return false; } #if QUIRKS if (vec_dot(p.normal(), hit.n) < S(0.0)) { hit.n = vec_neg(hit.n); } #endif return true; } /* * Calculate barycentric coordinates for the triangle. */ bool barycentric(scal_t* bc, vec_t v) const { scal_t denom = (b.y - c.y) * (a.x - c.x) + (c.x - b.x) * (a.y - c.y); bc[0] = ((b.y - c.y) * (v.x - c.x) + (c.x - b.x) * (v.y - c.y)) / denom; bc[1] = ((c.y - a.y) * (v.x - c.x) + (a.x - c.x) * (v.y - c.y)) / denom; bc[2] = S(1.0) - bc[0] - bc[1]; if (S(0.0) <= bc[0] && bc[0] <= S(1.0) && S(0.0) <= bc[1] && bc[1] <= S(1.0) && S(0.0) <= bc[2] && bc[2] <= S(1.0)) { return true; } return false; } virtual vec_t txcoord(vec_t point) const { vec_t t1 = vec_new(S(0.0), S(0.0), S(0.0)); vec_t t2 = vec_new(S(1.0), S(0.0), S(0.0)); vec_t t3 = vec_new(S(1.0), S(1.0), S(0.0)); scal_t bc[3]; barycentric(bc, point); return vec_interp(t1, t2, t3, bc); } }; /* * Destroy a new'd triangle, releasing its memory. */ INLINE_MAYBE void triangle_destroy(plane* t) { delete t; } } // namespace rt #endif // _PLANE_HH_