Triangle.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 
00022 // Triangle.cpp: implementation of the Triangle class.
00023 //
00024 //////////////////////////////////////////////////////////////////////
00025 
00026 #include <math.h>
00027 #include <common/Triangle.h>
00028 #include <common/Defines.h>
00029 
00030 //////////////////////////////////////////////////////////////////////
00031 // Construction/Destruction
00032 //////////////////////////////////////////////////////////////////////
00033 
00034 Triangle::Triangle()
00035 {
00036 
00037 }
00038 
00039 Triangle::~Triangle()
00040 {
00041 
00042 }
00043 
00044 void Triangle::setPointComponents(const float ptA1, const float ptA2, const float ptA3, 
00045         Vector &normalA,
00046         const float ptB1, const float ptB2, const float ptB3, 
00047         Vector &normalB,
00048         const float ptC1, const float ptC2, const float ptC3,
00049         Vector &normalC)
00050 {
00051         ptA_.initialise(ptA1, ptA2, ptA3);
00052         ptB_.initialise(ptB1, ptB2, ptB3);
00053         ptC_.initialise(ptC1, ptC2, ptC3);
00054 
00055         faceN_ += normalA;
00056         faceN_ += normalB;
00057         faceN_ += normalC;
00058         faceN_ /= 3.0f;
00059         calcLargest();
00060 }
00061 
00062 void Triangle::calcLargest()
00063 {
00064         largest_ = scalarZ;
00065         float f0 = fabsf(faceN_[0]);
00066         float f1 = fabsf(faceN_[1]);
00067         float f2 = fabsf(faceN_[2]);
00068         if (f0 >= f1)
00069         {
00070                 if (f0 >= f2) largest_ = scalarX;
00071         }
00072         else 
00073         {
00074                 if (f1 >= f2) largest_ = scalarY;
00075         }
00076 }
00077 
00078 bool Triangle::pointInBoundingBox(const Vector &pt)
00079 {
00080         float max0 = MAX(ptA_[0], MAX(ptB_[0], ptC_[0]));
00081         float max1 = MAX(ptA_[1], MAX(ptB_[1], ptC_[1]));
00082         float max2 = MAX(ptA_[2], MAX(ptB_[2], ptC_[2]));
00083         float min0 = MIN(ptA_[0], MIN(ptB_[0], ptC_[0]));
00084         float min1 = MIN(ptA_[1], MIN(ptB_[1], ptC_[1]));
00085         float min2 = MIN(ptA_[2], MIN(ptB_[2], ptC_[2]));
00086 
00087         Vector &Pt = (Vector &) pt;
00088         if (Pt[0] < min0-0.1f || Pt[0] > max0+0.1f) return false;
00089         if (Pt[1] < min1-0.1f || Pt[1] > max1+0.1f) return false;
00090         if (Pt[2] < min2-0.1f || Pt[2] > max2+0.1f) return false;
00091 
00092         return true;
00093 }
00094 
00095 bool Triangle::pointInTriangle(const Vector &pt)
00096 {
00097         Vector u, v;
00098         switch (largest_)
00099         {
00100         case scalarX:
00101                 u[0] = pt[1] - ptA_[1];
00102                 v[0] = pt[2] - ptA_[2];
00103                 u[1] = ptB_[1] - ptA_[1];
00104                 v[1] = ptB_[2] - ptA_[2];
00105                 u[2] = ptC_[1] - ptA_[1];
00106                 v[2] = ptC_[2] - ptA_[2];
00107                 break;
00108         case scalarY:
00109                 u[0] = pt[0] - ptA_[0];
00110                 v[0] = pt[2] - ptA_[2];
00111                 u[1] = ptB_[0] - ptA_[0];
00112                 v[1] = ptB_[2] - ptA_[2];
00113                 u[2] = ptC_[0] - ptA_[0];
00114                 v[2] = ptC_[2] - ptA_[2];
00115                 break;
00116         case scalarZ:
00117                 u[0] = pt[0] - ptA_[0];
00118                 v[0] = pt[1] - ptA_[1];
00119                 u[1] = ptB_[0] - ptA_[0];
00120                 v[1] = ptB_[1] - ptA_[1];
00121                 u[2] = ptC_[0] - ptA_[0];
00122                 v[2] = ptC_[1] - ptA_[1];
00123                 break;
00124         default:
00125                 return false;
00126                 break;
00127         }
00128 
00129         float alpha, beta;
00130         if (u[1] == 0.0) 
00131         {
00132                 if (u[2] != 0.0) beta = u[0] / u[2];
00133                 else return false;
00134                 if (beta>=0.0 && beta<=1.0) 
00135                 {
00136                         alpha = (v[0] - beta * v[2]) / v[1];
00137                         if (alpha<0.0 || alpha>1.0) return false;
00138                 }
00139                 else return false;
00140         }
00141         else 
00142         {
00143                 beta=(v[0] * u[1] - u[0] * v[1]) / (v[2] * u[1] - u[2] * v[1]);
00144                 if (beta>=0.0 && beta<=1.0) 
00145                 {
00146                         alpha = (u[0] - beta * u[2]) / u[1];
00147                         if (alpha<0.0 || alpha>1.0) return false;
00148                 }
00149                 else return false;
00150         }
00151 
00152         if (alpha+beta > 1.0) return false;
00153         return true;
00154 }
00155 
00156 bool Triangle::rayIntersect(const Line &ray, 
00157                                                         Vector &intersectPt, 
00158                                                         Vector &intersectN,
00159                                                         float &intersectDist,
00160                                                         const bool checkPtOnLine)
00161 {
00162         // Remove const
00163         Line &Ray = (Line &) ray;
00164 
00165         // Only do intersections for triangles facing the ray
00166         float sd = faceN_.dotP((Vector &) Ray.getDirection());
00167         if (sd == 0.0f) return false;
00168 
00169         // Get the intersection point of the ray and the triangles
00170         // plane
00171         // Expand all vector maths so we create as few tmp vector
00172         // objects as possible, reuse intersectPt as temporary
00173         intersectPt = ptA_;
00174         intersectPt -= Ray.getStart();
00175         float si = -intersectPt.dotP(faceN_) / sd;
00176 
00177         intersectPt = (Vector &) Ray.getDirection();
00178         intersectPt *= - si;
00179         intersectPt += Ray.getStart();
00180         intersectDist = -si;
00181         intersectN = faceN_;
00182 
00183         // Check the intersection point is in the ray
00184         if (checkPtOnLine)
00185         {
00186                 if (si > 0.0f || si < -1.0) return false;
00187         }
00188 
00189         // Check the intersection point is in the triangle
00190         if (!pointInBoundingBox(intersectPt)) return false;
00191         if (!pointInTriangle(intersectPt)) return false;
00192         return true;
00193 }
00194 
00195 bool Triangle::sphereIntersect(
00196                 Vector &sphereCentre, 
00197                 float &sphereRadius,
00198                 Vector &intersectPt,
00199                 Vector &intersectN,
00200                 float &intersectDist)
00201 {
00202         Vector actualPosition = sphereCentre + (faceN_ * sphereRadius);
00203         Vector destPosition = sphereCentre - (faceN_ * sphereRadius);
00204         Line direction(actualPosition, destPosition);
00205 
00206         if (rayIntersect(direction, intersectPt, intersectN, intersectDist, true))
00207         {
00208                 float diameter = sphereRadius + sphereRadius;
00209 
00210                 intersectDist = (diameter) - (intersectDist * diameter);
00211                 return true;
00212         }
00213         return false;
00214 }

Generated on Mon Feb 16 15:14:49 2009 for Scorched3D by  doxygen 1.5.3