Go to the documentation of this file.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
00090 bool isPointInside(const vector3d<T>& p) const
00091 {
00092 return (isOnSameSide(p, pointA, pointB, pointC) &&
00093 isOnSameSide(p, pointB, pointA, pointC) &&
00094 isOnSameSide(p, pointC, pointA, pointB));
00095 }
00096
00098
00105 bool isPointInsideFast(const vector3d<T>& p) const
00106 {
00107 const vector3d<T> a = pointC - pointA;
00108 const vector3d<T> b = pointB - pointA;
00109 const vector3d<T> c = p - pointA;
00110
00111 const f64 dotAA = a.dotProduct( a);
00112 const f64 dotAB = a.dotProduct( b);
00113 const f64 dotAC = a.dotProduct( c);
00114 const f64 dotBB = b.dotProduct( b);
00115 const f64 dotBC = b.dotProduct( c);
00116
00117
00118 const f64 invDenom = 1/(dotAA * dotBB - dotAB * dotAB);
00119 const f64 u = (dotBB * dotAC - dotAB * dotBC) * invDenom;
00120 const f64 v = (dotAA * dotBC - dotAB * dotAC ) * invDenom;
00121
00122
00123
00124 return (u >= 0) && (v >= 0) && (u + v <= 1);
00125
00126 }
00127
00128
00130
00133 bool getIntersectionWithLimitedLine(const line3d<T>& line,
00134 vector3d<T>& outIntersection) const
00135 {
00136 return getIntersectionWithLine(line.start,
00137 line.getVector(), outIntersection) &&
00138 outIntersection.isBetweenPoints(line.start, line.end);
00139 }
00140
00141
00143
00151 bool getIntersectionWithLine(const vector3d<T>& linePoint,
00152 const vector3d<T>& lineVect, vector3d<T>& outIntersection) const
00153 {
00154 if (getIntersectionOfPlaneWithLine(linePoint, lineVect, outIntersection))
00155 return isPointInside(outIntersection);
00156
00157 return false;
00158 }
00159
00160
00162
00166 bool getIntersectionOfPlaneWithLine(const vector3d<T>& linePoint,
00167 const vector3d<T>& lineVect, vector3d<T>& outIntersection) const
00168 {
00169 const vector3d<T> normal = getNormal().normalize();
00170 T t2;
00171
00172 if ( core::iszero ( t2 = normal.dotProduct(lineVect) ) )
00173 return false;
00174
00175 T d = pointA.dotProduct(normal);
00176 T t = -(normal.dotProduct(linePoint) - d) / t2;
00177 outIntersection = linePoint + (lineVect * t);
00178 return true;
00179 }
00180
00181
00183
00184 vector3d<T> getNormal() const
00185 {
00186 return (pointB - pointA).crossProduct(pointC - pointA);
00187 }
00188
00190
00195 bool isFrontFacing(const vector3d<T>& lookDirection) const
00196 {
00197 const vector3d<T> n = getNormal().normalize();
00198 const f32 d = (f32)n.dotProduct(lookDirection);
00199 return F32_LOWER_EQUAL_0(d);
00200 }
00201
00203 plane3d<T> getPlane() const
00204 {
00205 return plane3d<T>(pointA, pointB, pointC);
00206 }
00207
00209 T getArea() const
00210 {
00211 return (pointB - pointA).crossProduct(pointC - pointA).getLength() * 0.5f;
00212
00213 }
00214
00216 void set(const core::vector3d<T>& a, const core::vector3d<T>& b, const core::vector3d<T>& c)
00217 {
00218 pointA = a;
00219 pointB = b;
00220 pointC = c;
00221 }
00222
00224 vector3d<T> pointA;
00225 vector3d<T> pointB;
00226 vector3d<T> pointC;
00227
00228 private:
00229 bool isOnSameSide(const vector3d<T>& p1, const vector3d<T>& p2,
00230 const vector3d<T>& a, const vector3d<T>& b) const
00231 {
00232 vector3d<T> bminusa = b - a;
00233 vector3d<T> cp1 = bminusa.crossProduct(p1 - a);
00234 vector3d<T> cp2 = bminusa.crossProduct(p2 - a);
00235 return (cp1.dotProduct(cp2) >= 0.0f);
00236 }
00237 };
00238
00239
00241 typedef triangle3d<f32> triangle3df;
00242
00244 typedef triangle3d<s32> triangle3di;
00245
00246 }
00247 }
00248
00249 #endif
00250