/* * Ray++ - Object-oriented ray tracing library * Copyright (C) 1998-2001 Martin Reinecke and others. * See the AUTHORS file for more information. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * See the README file for more information. */ /* * A two-sided triangle (no backface culling) * * See * Moeller, Trumbore: "Fast, Minimum Storage Ray/Triangle Intersection", * Journal of Graphics Tools, 2(1):21-28, 1997. * for details. */ #include "shapes/triangle.h" namespace RAYPP { inline bool TRIANGLE::Find_Intersection (const GEOM_RAY &Ray, float8 &dist) const { VECTOR TVec, PVec, QVec; float8 det, inv_det; float8 u, v; /* begin calculating determinant - also used to calculate U parameter */ PVec = Cross (Ray.dir, Edge2); /* if determinant is near zero, ray lies in plane of triangle */ det = Dot (Edge1, PVec); if (abs (det) < Small_float4) return false; inv_det = 1.0 / det; /* calculate distance from vert1 to ray origin */ TVec = Ray.start - Vert1; /* calculate U parameter and test bounds */ u = Dot (TVec, PVec) * inv_det; if (u < 0.0 || u > 1.0) return false; /* prepare to test V parameter */ QVec = Cross (TVec, Edge1); /* calculate V parameter and test bounds */ v = Dot (Ray.dir, QVec) * inv_det; if (v < 0.0 || u + v > 1.0) return false; /* calculate t, ray intersects triangle */ dist = Dot (Edge2, QVec) * inv_det; return ((dist > Ray.mindist) && (dist < Ray.maxdist)); } TRIANGLE::TRIANGLE (const VECTOR &Vertex1, const VECTOR &Vertex2, const VECTOR &Vertex3) : Vert1 (Vertex1), Edge1 (Vertex2-Vertex1), Edge2 (Vertex3-Vertex1) {} //virtual void TRIANGLE::Init () { if (initialized) return; Normal_Vector = Cross (Edge1, Edge2).Norm(); initialized = true; } //virtual void TRIANGLE::Transform (const TRANSFORM &Trans) { cni(); Vert1 = Trans.TransPoint (Vert1); Edge1 = Trans.TransDirection (Edge1); Edge2 = Trans.TransDirection (Edge2); } //virtual AXISBOX TRIANGLE::BBox () const { ci(); AXISBOX Box; Box.Include(Vert1); Box.Include(Vert1+Edge1); Box.Include(Vert1+Edge2); return Box; } //virtual bool TRIANGLE::Test (const GEOM_RAY &Ray, float8 &dist, bool &realhit) const { ci(); realhit = true; return Find_Intersection (Ray, dist); } //virtual bool TRIANGLE::Intersect (const GEOM_RAY &Ray, float8 &dist, VECTOR &Normal) const { ci(); Normal = Normal_Vector; return Find_Intersection (Ray, dist); } //virtual void TRIANGLE::All_Intersections (const GEOM_RAY &Ray, vector &Inter) const { ci(); float8 depth; if (Find_Intersection (Ray, depth)) Inter.push_back (INTER (depth, Normal_Vector)); } } // namespace RAYPP