00001 /************************************************************** ggt-head beg 00002 * 00003 * GGT: Generic Graphics Toolkit 00004 * 00005 * Original Authors: 00006 * Allen Bierbaum 00007 * 00008 * ----------------------------------------------------------------- 00009 * File: $RCSfile: Tri.h,v $ 00010 * Date modified: $Date: 2003/03/06 15:36:48 $ 00011 * Version: $Revision: 1.10 $ 00012 * ----------------------------------------------------------------- 00013 * 00014 *********************************************************** ggt-head end */ 00015 /*************************************************************** ggt-cpr beg 00016 * 00017 * GGT: The Generic Graphics Toolkit 00018 * Copyright (C) 2001,2002 Allen Bierbaum 00019 * 00020 * This library is free software; you can redistribute it and/or 00021 * modify it under the terms of the GNU Lesser General Public 00022 * License as published by the Free Software Foundation; either 00023 * version 2.1 of the License, or (at your option) any later version. 00024 * 00025 * This library is distributed in the hope that it will be useful, 00026 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00027 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00028 * Lesser General Public License for more details. 00029 * 00030 * You should have received a copy of the GNU Lesser General Public 00031 * License along with this library; if not, write to the Free Software 00032 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00033 * 00034 ************************************************************ ggt-cpr end */ 00035 #ifndef _GMTL_TRI_H_ 00036 #define _GMTL_TRI_H_ 00037 00038 #include <gmtl/Point.h> 00039 #include <gmtl/Vec.h> 00040 #include <gmtl/VecOps.h> 00041 00042 namespace gmtl 00043 { 00051 template< class DATA_TYPE > 00052 class Tri 00053 { 00054 public: 00058 Tri() {} 00059 00070 Tri( const Point<DATA_TYPE, 3>& p1, const Point<DATA_TYPE, 3>& p2, 00071 const Point<DATA_TYPE, 3>& p3) 00072 { 00073 mVerts[0] = p1; 00074 mVerts[1] = p2; 00075 mVerts[2] = p3; 00076 } 00077 00083 Tri( const Tri<DATA_TYPE>& tri ) 00084 { 00085 mVerts[0] = tri[0]; 00086 mVerts[1] = tri[1]; 00087 mVerts[2] = tri[2]; 00088 } 00089 00099 Point<DATA_TYPE, 3>& operator[]( int idx ) 00100 { 00101 gmtlASSERT( (0 <= idx) && (idx <= 2) ); 00102 return mVerts[idx]; 00103 } 00104 const Point<DATA_TYPE, 3>& operator[]( int idx ) const 00105 { 00106 gmtlASSERT( (0 <= idx) && (idx <= 2) ); 00107 return mVerts[idx]; 00108 } 00110 00121 Vec<DATA_TYPE, 3> edge( int idx ) const 00122 { 00123 gmtlASSERT( (0 <= idx) && (idx <= 2) ); 00124 int idx2 = ( idx == 2 ) ? 0 : idx + 1; 00125 return (mVerts[idx2] - mVerts[idx]); 00126 } 00127 00138 void set( const Point<DATA_TYPE, 3>& p1, const Point<DATA_TYPE, 3>& p2, 00139 const Point<DATA_TYPE, 3>& p3 ) 00140 { 00141 mVerts[0] = p1; 00142 mVerts[1] = p2; 00143 mVerts[2] = p3; 00144 } 00145 00146 private: 00150 Point<DATA_TYPE, 3> mVerts[3]; 00151 }; 00152 00153 // convenience typedefs 00154 typedef Tri<float> Trif; 00155 typedef Tri<double> Trid; 00156 typedef Tri<int> Trii; 00157 } 00158 00159 /* 00160 // Finds the point on the seg nearest to pt. 00161 // on the perimeter of the triangle. 00162 // Returns the nearest point in nearPt 00163 inline 00164 void sgTri::findNearestEdgePt(const sgVec3& pt, sgVec3& nearPt) const 00165 { 00166 // find all the closest pts on the segs that make the tri 00167 // return the closest one 00168 00169 sgSeg seg1; seg1.makePts(_v1, _v2); 00170 sgSeg seg2; seg2.makePts(_v2, _v3); 00171 sgSeg seg3; seg3.makePts(_v3, _v1); 00172 00173 sgVec3 pt1; seg1.findNearestPt(pt, pt1); 00174 sgVec3 pt2; seg2.findNearestPt(pt, pt2); 00175 sgVec3 pt3; seg3.findNearestPt(pt, pt3); 00176 00177 float dist1 = SG_SQUARE(pt1[0]-pt[0]) + SG_SQUARE(pt1[1]-pt[1]) + SG_SQUARE(pt1[2]-pt[2]); 00178 float dist2 = SG_SQUARE(pt2[0]-pt[0]) + SG_SQUARE(pt2[1]-pt[1]) + SG_SQUARE(pt2[2]-pt[2]); 00179 float dist3 = SG_SQUARE(pt3[0]-pt[0]) + SG_SQUARE(pt3[1]-pt[1]) + SG_SQUARE(pt3[2]-pt[2]); 00180 00181 if((dist1 < dist2) && (dist1 < dist3)) // dist1 is min 00182 nearPt = pt1; 00183 else if(dist2 < dist3) // dist2 is min 00184 nearPt = pt2; 00185 else 00186 nearPt = pt3; // dist3 is min 00187 } 00188 00189 00190 00191 // Returns wether the pt is in the triangle 00192 inline 00193 int sgTri::ptIn(const sgVec3& pt) const 00194 { 00195 // Graphic Gems I: Page 392 00196 int i0, i1, i2; // Axis indices 00197 float u0, u1, u2, v0, v1, v2, alpha, beta; 00198 i0 = 0; 00199 00200 sgVec3 triNormal = (_v2-_v1).cross((_v3-_v1)); 00201 //sgPlane triPlane; 00202 //triPlane.makePts(_v1, _v2, _v3); 00203 00204 // Find max index 00205 // NOTE: note the fabs. I added because of bug in GG code with negative normals 00206 for(int index=0;index<3;index++) 00207 if (fabs(triNormal.vec[index]) > fabs(triNormal.vec[i0])) 00208 i0 = index; 00209 00210 if(i0 == 0) 00211 { i1 = 1; i2 = 2; } 00212 else if (i0 == 1) 00213 { i1 = 2; i2 = 0; } 00214 else 00215 { i1 =0; i2 = 1; } 00216 00217 u0 = pt[i1] - _v1[i1]; 00218 v0 = pt[i2] - _v1[i2]; 00219 u1 = _v2[i1] - _v1[i1]; 00220 u2 = _v3[i1] - _v1[i1]; 00221 v1 = _v2[i2] - _v1[i2]; 00222 v2 = _v3[i2] - _v1[i2]; 00223 if(u1 == 0) 00224 { 00225 beta = (u0/u2); 00226 if((beta >= 0) && (beta<= 1)) 00227 alpha = (v0 - (beta*v2))/v1; 00228 } 00229 else 00230 { 00231 beta = ((v0*u1) - (u0*v1))/((v2*u1) - (u2*v1)); 00232 if((beta >= 0) && (beta<= 1)) 00233 alpha = (u0 - (beta*u2))/u1; 00234 } 00235 00236 return ((alpha >= 0) && (beta >= 0) && ((alpha+beta) <= 1)); 00237 } 00238 00239 00240 00241 // Finds the point on the seg nearest to pt. 00242 // Returns the nearest point in nearPt 00243 void sgTri::findNearestPt(const sgVec3& pt, sgVec3& nearPt) const 00244 { 00245 // find nearest pt on plaane. 00246 // if it is in the tri, return it. 00247 // Otherwise return the pt closest on the edge of the tri 00248 00249 sgPlane triPlane; 00250 triPlane.makePts(_v1, _v2, _v3); 00251 triPlane.findNearestPt(pt, nearPt); 00252 00253 if(!ptIn(nearPt)) 00254 findNearestEdgePt(pt, nearPt); 00255 } 00256 */ 00257 00258 #endif 00259