00001
00002
00003
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 core::vector3d<T> closestPointOnTriangle(const core::vector3d<T>& p) const
00055 {
00056 const core::vector3d<T> rab = line3d<T>(pointA, pointB).getClosestPoint(p);
00057 const core::vector3d<T> rbc = line3d<T>(pointB, pointC).getClosestPoint(p);
00058 const core::vector3d<T> rca = line3d<T>(pointC, pointA).getClosestPoint(p);
00059
00060 const T d1 = rab.getDistanceFrom(p);
00061 const T d2 = rbc.getDistanceFrom(p);
00062 const T d3 = rca.getDistanceFrom(p);
00063
00064 if (d1 < d2)
00065 return d1 < d3 ? rab : rca;
00066
00067 return d2 < d3 ? rbc : rca;
00068 }
00069
00071
00074 bool isPointInside(const vector3d<T>& p) const
00075 {
00076 return (isOnSameSide(p, pointA, pointB, pointC) &&
00077 isOnSameSide(p, pointB, pointA, pointC) &&
00078 isOnSameSide(p, pointC, pointA, pointB));
00079 }
00080
00082
00088 bool isPointInsideFast(const vector3d<T>& p) const
00089 {
00090 const vector3d<T> f = pointB - pointA;
00091 const vector3d<T> g = pointC - pointA;
00092
00093 const f32 a = f.dotProduct(f);
00094 const f32 b = f.dotProduct(g);
00095 const f32 c = g.dotProduct(g);
00096
00097 const vector3d<T> vp = p - pointA;
00098 const f32 d = vp.dotProduct(f);
00099 const f32 e = vp.dotProduct(g);
00100
00101 f32 x = (d*c)-(e*b);
00102 f32 y = (e*a)-(d*b);
00103 const f32 ac_bb = (a*c)-(b*b);
00104 f32 z = x+y-ac_bb;
00105
00106
00107 return (( (IR(z)) & ~((IR(x))|(IR(y))) ) & 0x80000000)!=0;
00108 }
00109
00110
00112
00115 bool getIntersectionWithLimitedLine(const line3d<T>& line,
00116 vector3d<T>& outIntersection) const
00117 {
00118 return getIntersectionWithLine(line.start,
00119 line.getVector(), outIntersection) &&
00120 outIntersection.isBetweenPoints(line.start, line.end);
00121 }
00122
00123
00125
00133 bool getIntersectionWithLine(const vector3d<T>& linePoint,
00134 const vector3d<T>& lineVect, vector3d<T>& outIntersection) const
00135 {
00136 if (getIntersectionOfPlaneWithLine(linePoint, lineVect, outIntersection))
00137 return isPointInside(outIntersection);
00138
00139 return false;
00140 }
00141
00142
00144
00148 bool getIntersectionOfPlaneWithLine(const vector3d<T>& linePoint,
00149 const vector3d<T>& lineVect, vector3d<T>& outIntersection) const
00150 {
00151 const vector3d<T> normal = getNormal().normalize();
00152 T t2;
00153
00154 if ( core::iszero ( t2 = normal.dotProduct(lineVect) ) )
00155 return false;
00156
00157 T d = pointA.dotProduct(normal);
00158 T t = -(normal.dotProduct(linePoint) - d) / t2;
00159 outIntersection = linePoint + (lineVect * t);
00160 return true;
00161 }
00162
00163
00165
00166 vector3d<T> getNormal() const
00167 {
00168 return (pointB - pointA).crossProduct(pointC - pointA);
00169 }
00170
00172
00177 bool isFrontFacing(const vector3d<T>& lookDirection) const
00178 {
00179 const vector3d<T> n = getNormal().normalize();
00180 const f32 d = (f32)n.dotProduct(lookDirection);
00181 return F32_LOWER_EQUAL_0(d);
00182 }
00183
00185 plane3d<T> getPlane() const
00186 {
00187 return plane3d<T>(pointA, pointB, pointC);
00188 }
00189
00191 T getArea() const
00192 {
00193 return (pointB - pointA).crossProduct(pointC - pointA).getLength() * 0.5;
00194
00195 }
00196
00198 void set(const core::vector3d<T>& a, const core::vector3d<T>& b, const core::vector3d<T>& c)
00199 {
00200 pointA = a;
00201 pointB = b;
00202 pointC = c;
00203 }
00204
00206 vector3d<T> pointA;
00207 vector3d<T> pointB;
00208 vector3d<T> pointC;
00209
00210 private:
00211 bool isOnSameSide(const vector3d<T>& p1, const vector3d<T>& p2,
00212 const vector3d<T>& a, const vector3d<T>& b) const
00213 {
00214 vector3d<T> bminusa = b - a;
00215 vector3d<T> cp1 = bminusa.crossProduct(p1 - a);
00216 vector3d<T> cp2 = bminusa.crossProduct(p2 - a);
00217 return (cp1.dotProduct(cp2) >= 0.0f);
00218 }
00219 };
00220
00221
00223 typedef triangle3d<f32> triangle3df;
00224
00226 typedef triangle3d<s32> triangle3di;
00227
00228 }
00229 }
00230
00231 #endif
00232