|
IrrlichtEngine
|
00001 // Copyright (C) 2002-2011 Nikolaus Gebhardt 00002 // This file is part of the "Irrlicht Engine". 00003 // For conditions of distribution and use, see copyright notice in irrlicht.h 00004 00005 #ifndef __IRR_TRIANGLE_3D_H_INCLUDED__ 00006 #define __IRR_TRIANGLE_3D_H_INCLUDED__ 00007 00008 #include "vector3d.h" 00009 #include "line3d.h" 00010 #include "plane3d.h" 00011 #include "aabbox3d.h" 00012 00013 namespace irr 00014 { 00015 namespace core 00016 { 00017 00019 template <class T> 00020 class triangle3d 00021 { 00022 public: 00023 00025 triangle3d() {} 00027 triangle3d(vector3d<T> v1, vector3d<T> v2, vector3d<T> v3) : pointA(v1), pointB(v2), pointC(v3) {} 00028 00030 bool operator==(const triangle3d<T>& other) const 00031 { 00032 return other.pointA==pointA && other.pointB==pointB && other.pointC==pointC; 00033 } 00034 00036 bool operator!=(const triangle3d<T>& other) const 00037 { 00038 return !(*this==other); 00039 } 00040 00042 00044 bool isTotalInsideBox(const aabbox3d<T>& box) const 00045 { 00046 return (box.isPointInside(pointA) && 00047 box.isPointInside(pointB) && 00048 box.isPointInside(pointC)); 00049 } 00050 00052 00054 bool isTotalOutsideBox(const aabbox3d<T>& box) const 00055 { 00056 return ((pointA.X > box.MaxEdge.X && pointB.X > box.MaxEdge.X && pointC.X > box.MaxEdge.X) || 00057 00058 (pointA.Y > box.MaxEdge.Y && pointB.Y > box.MaxEdge.Y && pointC.Y > box.MaxEdge.Y) || 00059 (pointA.Z > box.MaxEdge.Z && pointB.Z > box.MaxEdge.Z && pointC.Z > box.MaxEdge.Z) || 00060 (pointA.X < box.MinEdge.X && pointB.X < box.MinEdge.X && pointC.X < box.MinEdge.X) || 00061 (pointA.Y < box.MinEdge.Y && pointB.Y < box.MinEdge.Y && pointC.Y < box.MinEdge.Y) || 00062 (pointA.Z < box.MinEdge.Z && pointB.Z < box.MinEdge.Z && pointC.Z < box.MinEdge.Z)); 00063 } 00064 00066 00068 core::vector3d<T> closestPointOnTriangle(const core::vector3d<T>& p) const 00069 { 00070 const core::vector3d<T> rab = line3d<T>(pointA, pointB).getClosestPoint(p); 00071 const core::vector3d<T> rbc = line3d<T>(pointB, pointC).getClosestPoint(p); 00072 const core::vector3d<T> rca = line3d<T>(pointC, pointA).getClosestPoint(p); 00073 00074 const T d1 = rab.getDistanceFrom(p); 00075 const T d2 = rbc.getDistanceFrom(p); 00076 const T d3 = rca.getDistanceFrom(p); 00077 00078 if (d1 < d2) 00079 return d1 < d3 ? rab : rca; 00080 00081 return d2 < d3 ? rbc : rca; 00082 } 00083 00085 00088 bool isPointInside(const vector3d<T>& p) const 00089 { 00090 const vector3d<T> a = pointC - pointA; 00091 const vector3d<T> b = pointB - pointA; 00092 const vector3d<T> c = p - pointA; 00093 00094 const f64 dotAA = a.dotProduct( a); 00095 const f64 dotAB = a.dotProduct( b); 00096 const f64 dotAC = a.dotProduct( c); 00097 const f64 dotBB = b.dotProduct( b); 00098 const f64 dotBC = b.dotProduct( c); 00099 00100 // get coordinates in barycentric coordinate system 00101 const f64 invDenom = 1/(dotAA * dotBB - dotAB * dotAB); 00102 const f64 u = (dotBB * dotAC - dotAB * dotBC) * invDenom; 00103 const f64 v = (dotAA * dotBC - dotAB * dotAC ) * invDenom; 00104 00105 // We count border-points as inside to keep downward compatibility. 00106 // That's why we use >= and <= instead of > and < as more commonly seen on the web. 00107 return (u >= 0) && (v >= 0) && (u + v <= 1); 00108 } 00109 00111 00120 bool isPointInsideFast(const vector3d<T>& p) const 00121 { 00122 const vector3d<T> f = pointB - pointA; 00123 const vector3d<T> g = pointC - pointA; 00124 00125 const f32 a = f.dotProduct(f); 00126 const f32 b = f.dotProduct(g); 00127 const f32 c = g.dotProduct(g); 00128 00129 const vector3d<T> vp = p - pointA; 00130 const f32 d = vp.dotProduct(f); 00131 const f32 e = vp.dotProduct(g); 00132 00133 f32 x = (d*c)-(e*b); 00134 f32 y = (e*a)-(d*b); 00135 const f32 ac_bb = (a*c)-(b*b); 00136 f32 z = x+y-ac_bb; 00137 00138 // return sign(z) && !(sign(x)||sign(y)) 00139 return (( (IR(z)) & ~((IR(x))|(IR(y))) ) & 0x80000000)!=0; 00140 } 00141 00142 00144 00147 bool getIntersectionWithLimitedLine(const line3d<T>& line, 00148 vector3d<T>& outIntersection) const 00149 { 00150 return getIntersectionWithLine(line.start, 00151 line.getVector(), outIntersection) && 00152 outIntersection.isBetweenPoints(line.start, line.end); 00153 } 00154 00155 00157 00165 bool getIntersectionWithLine(const vector3d<T>& linePoint, 00166 const vector3d<T>& lineVect, vector3d<T>& outIntersection) const 00167 { 00168 if (getIntersectionOfPlaneWithLine(linePoint, lineVect, outIntersection)) 00169 return isPointInside(outIntersection); 00170 00171 return false; 00172 } 00173 00174 00176 00180 bool getIntersectionOfPlaneWithLine(const vector3d<T>& linePoint, 00181 const vector3d<T>& lineVect, vector3d<T>& outIntersection) const 00182 { 00183 const vector3d<T> normal = getNormal().normalize(); 00184 T t2; 00185 00186 if ( core::iszero ( t2 = normal.dotProduct(lineVect) ) ) 00187 return false; 00188 00189 T d = pointA.dotProduct(normal); 00190 T t = -(normal.dotProduct(linePoint) - d) / t2; 00191 outIntersection = linePoint + (lineVect * t); 00192 return true; 00193 } 00194 00195 00197 00198 vector3d<T> getNormal() const 00199 { 00200 return (pointB - pointA).crossProduct(pointC - pointA); 00201 } 00202 00204 00209 bool isFrontFacing(const vector3d<T>& lookDirection) const 00210 { 00211 const vector3d<T> n = getNormal().normalize(); 00212 const f32 d = (f32)n.dotProduct(lookDirection); 00213 return F32_LOWER_EQUAL_0(d); 00214 } 00215 00217 plane3d<T> getPlane() const 00218 { 00219 return plane3d<T>(pointA, pointB, pointC); 00220 } 00221 00223 T getArea() const 00224 { 00225 return (pointB - pointA).crossProduct(pointC - pointA).getLength() * 0.5f; 00226 00227 } 00228 00230 void set(const core::vector3d<T>& a, const core::vector3d<T>& b, const core::vector3d<T>& c) 00231 { 00232 pointA = a; 00233 pointB = b; 00234 pointC = c; 00235 } 00236 00238 vector3d<T> pointA; 00239 vector3d<T> pointB; 00240 vector3d<T> pointC; 00241 00242 private: 00243 bool isOnSameSide(const vector3d<T>& p1, const vector3d<T>& p2, 00244 const vector3d<T>& a, const vector3d<T>& b) const 00245 { 00246 vector3d<T> bminusa = b - a; 00247 vector3d<T> cp1 = bminusa.crossProduct(p1 - a); 00248 vector3d<T> cp2 = bminusa.crossProduct(p2 - a); 00249 return (cp1.dotProduct(cp2) >= 0.0f); 00250 } 00251 }; 00252 00253 00255 typedef triangle3d<f32> triangle3df; 00256 00258 typedef triangle3d<s32> triangle3di; 00259 00260 } // end namespace core 00261 } // end namespace irr 00262 00263 #endif 00264