Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

triboxoverlap.cpp

Go to the documentation of this file.
00001 /*
00002     toxic - A Global Illumination Renderer
00003     Copyright (C) 2003-2004 Francois Beaune
00004     Contact: http://toxicengine.sourceforge.net/
00005 
00006     This file is part of toxic.
00007 
00008     toxic is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     toxic is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License
00019     along with toxic; if not, write to the Free Software
00020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 /********************************************************/
00024 /* AABB-triangle overlap test code                      */
00025 /* by Tomas Akenine-Möller                              */
00026 /* Function: int triBoxOverlap(float boxcenter[3],      */
00027 /*          float boxhalfsize[3],float triverts[3][3]); */
00028 /* History:                                             */
00029 /*   2001-03-05: released the code in its first version */
00030 /*   2001-06-18: changed the order of the tests, faster */
00031 /*                                                      */
00032 /* Acknowledgement: Many thanks to Pierre Terdiman for  */
00033 /* suggestions and discussions on how to optimize code. */
00034 /* Thanks to David Hunt for finding a ">="-bug!         */
00035 /********************************************************/
00036 
00037 #include "triboxoverlap.h"  // include first
00038 
00039 #include <cmath>
00040 
00041 using namespace sheep;
00042 using namespace toxic;
00043 
00044 #define FINDMINMAX(x0, x1, x2, min, max) \
00045     min = max = x0; \
00046     if(x1 < min) min = x1; \
00047     if(x1 > max) max = x1; \
00048     if(x2 < min) min = x2; \
00049     if(x2 > max) max = x2;
00050 
00051 namespace {
00052     bool plane_box_overlap(const Vector3 &normal, Real d, const Vector3 &maxbox) {
00053         Vector3 vmin, vmax;
00054 
00055         if(normal.m_x > 0.0) {
00056             vmin.m_x = -maxbox.m_x;
00057             vmax.m_x = maxbox.m_x;
00058         } else {
00059             vmin.m_x = maxbox.m_x;
00060             vmax.m_x = -maxbox.m_x;
00061         }
00062 
00063         if(normal.m_y > 0.0) {
00064             vmin.m_y = -maxbox.m_y;
00065             vmax.m_y = maxbox.m_y;
00066         } else {
00067             vmin.m_y = maxbox.m_y;
00068             vmax.m_y = -maxbox.m_y;
00069         }
00070 
00071         if(normal.m_z > 0.0) {
00072             vmin.m_z = -maxbox.m_z;
00073             vmax.m_z = maxbox.m_z;
00074         } else {
00075             vmin.m_z = maxbox.m_z;
00076             vmax.m_z = -maxbox.m_z;
00077         }
00078 
00079         if(normal * vmin + d > 0.0) return false;
00080         if(normal * vmax + d >= 0.0) return true;
00081 
00082         return false;
00083     }
00084 }
00085 
00086 //======================== X-tests ========================
00087 
00088 #define AXISTEST_X01(a, b, fa, fb) \
00089     p0 = a * v0.m_y - b * v0.m_z; \
00090     p2 = a * v2.m_y - b * v2.m_z; \
00091     if(p0 < p2) { min = p0; max = p2; } else { min = p2; max = p0; } \
00092     rad = fa * boxhalfsize.m_y + fb * boxhalfsize.m_z; \
00093     if(min > rad || max < -rad) return false;
00094 
00095 #define AXISTEST_X2(a, b, fa, fb) \
00096     p0 = a * v0.m_y - b * v0.m_z; \
00097     p1 = a * v1.m_y - b * v1.m_z; \
00098     if(p0 < p1) { min = p0; max = p1; } else { min = p1; max = p0; } \
00099     rad = fa * boxhalfsize.m_y + fb * boxhalfsize.m_z; \
00100     if(min > rad || max < -rad) return false;
00101 
00102 //======================== Y-tests ========================
00103 
00104 #define AXISTEST_Y02(a, b, fa, fb) \
00105     p0 = -a * v0.m_x + b * v0.m_z; \
00106     p2 = -a * v2.m_x + b * v2.m_z; \
00107     if(p0 < p2) { min = p0; max = p2; } else { min = p2; max = p0; } \
00108     rad = fa * boxhalfsize.m_x + fb * boxhalfsize.m_z; \
00109     if(min > rad || max < -rad) return false;
00110 
00111 #define AXISTEST_Y1(a, b, fa, fb) \
00112     p0 = -a * v0.m_x + b * v0.m_z; \
00113     p1 = -a * v1.m_x + b * v1.m_z; \
00114     if(p0 < p1) { min = p0; max = p1; } else { min = p1; max = p0; } \
00115     rad = fa * boxhalfsize.m_x + fb * boxhalfsize.m_z; \
00116     if(min > rad || max < -rad) return false;
00117 
00118 //======================== Z-tests ========================
00119 
00120 #define AXISTEST_Z12(a, b, fa, fb) \
00121     p1 = a * v1.m_x - b * v1.m_y; \
00122     p2 = a * v2.m_x - b * v2.m_y; \
00123     if(p2 < p1) { min = p2; max = p1; } else { min = p1; max = p2; } \
00124     rad = fa * boxhalfsize.m_x + fb * boxhalfsize.m_y; \
00125     if(min > rad || max < -rad) return false;
00126 
00127 #define AXISTEST_Z0(a, b, fa, fb) \
00128     p0 = a * v0.m_x - b * v0.m_y; \
00129     p1 = a * v1.m_x - b * v1.m_y; \
00130     if(p0 < p1) { min = p0; max = p1; } else { min = p1; max = p0; } \
00131     rad = fa * boxhalfsize.m_x + fb * boxhalfsize.m_y; \
00132     if(min > rad || max < -rad) return false;
00133 
00134 bool toxic::tri_box_overlap(const Point3 &boxcenter,
00135                             const Vector3 &boxhalfsize,
00136                             const Point3 &vert0,
00137                             const Point3 &vert1,
00138                             const Point3 &vert2)
00139 {
00140     // Use separating axis theorem to test overlap between triangle and box.
00141     // Need to test for overlap in these directions:
00142     // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
00143     //    we do not even need to test these)
00144     // 2) normal of the triangle
00145     // 3) crossproduct(edge from tri, {x,y,z}-directin).
00146     //    This gives 3x3=9 more tests.
00147     Real min, max, p0, p1, p2, rad, fex, fey, fez;
00148 
00149     // This is the fastest branch on Sun.
00150     // Move everything so that the boxcenter is in (0,0,0).
00151     const Vector3 v0 = vert0 - boxcenter;
00152     const Vector3 v1 = vert1 - boxcenter;
00153     const Vector3 v2 = vert2 - boxcenter;
00154 
00155     // Compute triangle edges.
00156     const Vector3 e0 = v1 - v0; // tri edge 0
00157     const Vector3 e1 = v2 - v1; // tri edge 1
00158     const Vector3 e2 = v0 - v2; // tri edge 2
00159 
00160     // Bullet 3:
00161     //   Test the 9 tests first (this was faster).
00162     fex = fabs(e0.m_x);
00163     fey = fabs(e0.m_y);
00164     fez = fabs(e0.m_z);
00165     AXISTEST_X01(e0.m_z, e0.m_y, fez, fey);
00166     AXISTEST_Y02(e0.m_z, e0.m_x, fez, fex);
00167     AXISTEST_Z12(e0.m_y, e0.m_x, fey, fex);
00168 
00169     fex = fabs(e1.m_x);
00170     fey = fabs(e1.m_y);
00171     fez = fabs(e1.m_z);
00172     AXISTEST_X01(e1.m_z, e1.m_y, fez, fey);
00173     AXISTEST_Y02(e1.m_z, e1.m_x, fez, fex);
00174     AXISTEST_Z0(e1.m_y, e1.m_x, fey, fex);
00175 
00176     fex = fabs(e2.m_x);
00177     fey = fabs(e2.m_y);
00178     fez = fabs(e2.m_z);
00179     AXISTEST_X2(e2.m_z, e2.m_y, fez, fey);
00180     AXISTEST_Y1(e2.m_z, e2.m_x, fez, fex);
00181     AXISTEST_Z12(e2.m_y, e2.m_x, fey, fex);
00182 
00183     // Bullet 1:
00184     //   First test overlap in the {x,y,z}-directions.
00185     //   Find min, max of the triangle each direction, and test for overlap in that
00186     //   direction -- this is equivalent to testing a minimal AABB around the triangle
00187     //   against the AABB.
00188 
00189     // Test in X-direction.
00190     FINDMINMAX(v0.m_x, v1.m_x, v2.m_x, min, max);
00191     if(min > boxhalfsize.m_x || max < -boxhalfsize.m_x)
00192         return false;
00193 
00194     // Test in Y-direction.
00195     FINDMINMAX(v0.m_y, v1.m_y, v2.m_y, min, max);
00196     if(min > boxhalfsize.m_y || max < -boxhalfsize.m_y)
00197         return false;
00198 
00199     // Test in Z-direction.
00200     FINDMINMAX(v0.m_z, v1.m_z, v2.m_z, min, max);
00201     if(min > boxhalfsize.m_z || max < -boxhalfsize.m_z)
00202         return false;
00203 
00204     // Bullet 2:
00205     //   Test if the box intersects the plane of the triangle.
00206     //   Compute plane equation of triangle: normal*x+d=0.
00207     const Vector3 normal = e0 ^ e1;
00208     const Real d = -(normal * v0);  // plane eq: normal.x+d=0
00209     if(!plane_box_overlap(normal, d, boxhalfsize))
00210         return false;
00211 
00212     return true;    // box and triangle overlaps
00213 }

Generated on Tue May 11 01:31:52 2004 for toxic by doxygen 1.3.6