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 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 return (isOnSameSide(p, pointA, pointB, pointC) &&
00091 isOnSameSide(p, pointB, pointA, pointC) &&
00092 isOnSameSide(p, pointC, pointA, pointB));
00093 }
00094
00096
00102 bool isPointInsideFast(const vector3d<T>& p) const
00103 {
00104 const vector3d<T> f = pointB - pointA;
00105 const vector3d<T> g = pointC - pointA;
00106
00107 const f32 a = f.dotProduct(f);
00108 const f32 b = f.dotProduct(g);
00109 const f32 c = g.dotProduct(g);
00110
00111 const vector3d<T> vp = p - pointA;
00112 const f32 d = vp.dotProduct(f);
00113 const f32 e = vp.dotProduct(g);
00114
00115 f32 x = (d*c)-(e*b);
00116 f32 y = (e*a)-(d*b);
00117 const f32 ac_bb = (a*c)-(b*b);
00118 f32 z = x+y-ac_bb;
00119
00120
00121 return (( (IR(z)) & ~((IR(x))|(IR(y))) ) & 0x80000000)!=0;
00122 }
00123
00124
00126
00129 bool getIntersectionWithLimitedLine(const line3d<T>& line,
00130 vector3d<T>& outIntersection) const
00131 {
00132 return getIntersectionWithLine(line.start,
00133 line.getVector(), outIntersection) &&
00134 outIntersection.isBetweenPoints(line.start, line.end);
00135 }
00136
00137
00139
00147 bool getIntersectionWithLine(const vector3d<T>& linePoint,
00148 const vector3d<T>& lineVect, vector3d<T>& outIntersection) const
00149 {
00150 if (getIntersectionOfPlaneWithLine(linePoint, lineVect, outIntersection))
00151 return isPointInside(outIntersection);
00152
00153 return false;
00154 }
00155
00156
00158
00162 bool getIntersectionOfPlaneWithLine(const vector3d<T>& linePoint,
00163 const vector3d<T>& lineVect, vector3d<T>& outIntersection) const
00164 {
00165 const vector3d<T> normal = getNormal().normalize();
00166 T t2;
00167
00168 if ( core::iszero ( t2 = normal.dotProduct(lineVect) ) )
00169 return false;
00170
00171 T d = pointA.dotProduct(normal);
00172 T t = -(normal.dotProduct(linePoint) - d) / t2;
00173 outIntersection = linePoint + (lineVect * t);
00174 return true;
00175 }
00176
00177
00179
00180 vector3d<T> getNormal() const
00181 {
00182 return (pointB - pointA).crossProduct(pointC - pointA);
00183 }
00184
00186
00191 bool isFrontFacing(const vector3d<T>& lookDirection) const
00192 {
00193 const vector3d<T> n = getNormal().normalize();
00194 const f32 d = (f32)n.dotProduct(lookDirection);
00195 return F32_LOWER_EQUAL_0(d);
00196 }
00197
00199 plane3d<T> getPlane() const
00200 {
00201 return plane3d<T>(pointA, pointB, pointC);
00202 }
00203
00205 T getArea() const
00206 {
00207 return (pointB - pointA).crossProduct(pointC - pointA).getLength() * 0.5f;
00208
00209 }
00210
00212 void set(const core::vector3d<T>& a, const core::vector3d<T>& b, const core::vector3d<T>& c)
00213 {
00214 pointA = a;
00215 pointB = b;
00216 pointC = c;
00217 }
00218
00220 vector3d<T> pointA;
00221 vector3d<T> pointB;
00222 vector3d<T> pointC;
00223
00224 private:
00225 bool isOnSameSide(const vector3d<T>& p1, const vector3d<T>& p2,
00226 const vector3d<T>& a, const vector3d<T>& b) const
00227 {
00228 vector3d<T> bminusa = b - a;
00229 vector3d<T> cp1 = bminusa.crossProduct(p1 - a);
00230 vector3d<T> cp2 = bminusa.crossProduct(p2 - a);
00231 return (cp1.dotProduct(cp2) >= 0.0f);
00232 }
00233 };
00234
00235
00237 typedef triangle3d<f32> triangle3df;
00238
00240 typedef triangle3d<s32> triangle3di;
00241
00242 }
00243 }
00244
00245 #endif
00246