Skylicht Engine
Loading...
Searching...
No Matches
triangle3d.h
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4
5#ifndef __IRR_TRIANGLE_3D_H_INCLUDED__
6#define __IRR_TRIANGLE_3D_H_INCLUDED__
7
8#include "vector3d.h"
9#include "line3d.h"
10#include "plane3d.h"
11#include "aabbox3d.h"
12
13namespace irr
14{
15namespace core
16{
17
18 #define INLINE_CROSSPRODUCT(ret, a, b) ret.X = a.Y * b.Z - a.Z * b.Y; ret.Y = a.Z * b.X - a.X * b.Z; ret.Z = a.X * b.Y - a.Y * b.X
19
21 template <class T>
23 {
24 public:
25
29 triangle3d(vector3d<T> v1, vector3d<T> v2, vector3d<T> v3) : pointA(v1), pointB(v2), pointC(v3) {}
30
32 bool operator==(const triangle3d<T>& other) const
33 {
34 return other.pointA==pointA && other.pointB==pointB && other.pointC==pointC;
35 }
36
38 bool operator!=(const triangle3d<T>& other) const
39 {
40 return !(*this==other);
41 }
42
44
46 bool isTotalInsideBox(const aabbox3d<T>& box) const
47 {
48 return (box.isPointInside(pointA) &&
49 box.isPointInside(pointB) &&
50 box.isPointInside(pointC));
51 }
52
54
56 bool isTotalOutsideBox(const aabbox3d<T>& box) const
57 {
58 return ((pointA.X > box.MaxEdge.X && pointB.X > box.MaxEdge.X && pointC.X > box.MaxEdge.X) ||
59
60 (pointA.Y > box.MaxEdge.Y && pointB.Y > box.MaxEdge.Y && pointC.Y > box.MaxEdge.Y) ||
61 (pointA.Z > box.MaxEdge.Z && pointB.Z > box.MaxEdge.Z && pointC.Z > box.MaxEdge.Z) ||
62 (pointA.X < box.MinEdge.X && pointB.X < box.MinEdge.X && pointC.X < box.MinEdge.X) ||
63 (pointA.Y < box.MinEdge.Y && pointB.Y < box.MinEdge.Y && pointC.Y < box.MinEdge.Y) ||
64 (pointA.Z < box.MinEdge.Z && pointB.Z < box.MinEdge.Z && pointC.Z < box.MinEdge.Z));
65 }
66
68
71 {
72 const core::vector3d<T> rab = line3d<T>(pointA, pointB).getClosestPoint(p);
73 const core::vector3d<T> rbc = line3d<T>(pointB, pointC).getClosestPoint(p);
74 const core::vector3d<T> rca = line3d<T>(pointC, pointA).getClosestPoint(p);
75
76 const T d1 = rab.getDistanceFrom(p);
77 const T d2 = rbc.getDistanceFrom(p);
78 const T d3 = rca.getDistanceFrom(p);
79
80 if (d1 < d2)
81 return d1 < d3 ? rab : rca;
82
83 return d2 < d3 ? rbc : rca;
84 }
85
87 /*
88 \param p Point to test. Assumes that this point is already
89 on the plane of the triangle.
90 \return True if the point is inside the triangle, otherwise false. */
91 bool isPointInside(const vector3d<T>& p) const
92 {
93 static vector3d<f64> af64;
94 af64.X = (f64)pointA.X;
95 af64.Y = (f64)pointA.Y;
96 af64.Z = (f64)pointA.Z;
97
98 static vector3d<f64> bf64;
99 bf64.X = (f64)pointB.X;
100 bf64.Y = (f64)pointB.Y;
101 bf64.Z = (f64)pointB.Z;
102
103 static vector3d<f64> cf64;
104 cf64.X = (f64)pointC.X;
105 cf64.Y = (f64)pointC.Y;
106 cf64.Z = (f64)pointC.Z;
107
108 static vector3d<f64> pf64;
109 pf64.X = (f64)p.X;
110 pf64.Y = (f64)p.Y;
111 pf64.Z = (f64)p.Z;
112
113 return (isOnSameSide(pf64, af64, bf64, cf64) &&
114 isOnSameSide(pf64, bf64, af64, cf64) &&
115 isOnSameSide(pf64, cf64, af64, bf64));
116 }
117
119
126 bool isPointInsideFast(const vector3d<T>& p) const
127 {
128 const vector3d<T> a = pointC - pointA;
129 const vector3d<T> b = pointB - pointA;
130 const vector3d<T> c = p - pointA;
131
132 const f64 dotAA = a.dotProduct( a);
133 const f64 dotAB = a.dotProduct( b);
134 const f64 dotAC = a.dotProduct( c);
135 const f64 dotBB = b.dotProduct( b);
136 const f64 dotBC = b.dotProduct( c);
137
138 // get coordinates in barycentric coordinate system
139 const f64 invDenom = 1/(dotAA * dotBB - dotAB * dotAB);
140 const f64 u = (dotBB * dotAC - dotAB * dotBC) * invDenom;
141 const f64 v = (dotAA * dotBC - dotAB * dotAC ) * invDenom;
142
143 // We count border-points as inside to keep downward compatibility.
144 // Rounding-error also needed for some test-cases.
145 return (u > -ROUNDING_ERROR_f32) && (v >= 0) && (u + v < 1+ROUNDING_ERROR_f32);
146
147 }
148
149
151
155 vector3d<T>& outIntersection) const
156 {
157 return getIntersectionWithLine(line.start,
158 line.getVector(), outIntersection) &&
159 outIntersection.isBetweenPoints(line.start, line.end);
160 }
161
162
164
173 const vector3d<T>& lineVect, vector3d<T>& outIntersection) const
174 {
175 if (getIntersectionOfPlaneWithLine(linePoint, lineVect, outIntersection))
176 return isPointInside(outIntersection);
177
178 return false;
179 }
180
181
183
188 const vector3d<T>& lineVect, vector3d<T>& outIntersection) const
189 {
190 // Work with f64 to get more precise results (makes enough difference to be worth the casts).
191 static vector3d<f64> linePointf64;
192 linePointf64.X = linePoint.X;
193 linePointf64.Y = linePoint.Y;
194 linePointf64.Z = linePoint.Z;
195
196 // Fix error build
197 // Setting: C++/All Options/Conformance Mode: OFF
198 static vector3d<f64> lineVectf64;
199 lineVectf64.X = lineVect.X;
200 lineVectf64.Y = lineVect.Y;
201 lineVectf64.Z = lineVect.Z;
202
203 static vector3d<f64> outIntersectionf64;
204
205 static core::triangle3d<irr::f64> trianglef64;
206
207 trianglef64.pointA.X = (f64)pointA.X;
208 trianglef64.pointA.Y = (f64)pointA.Y;
209 trianglef64.pointA.Z = (f64)pointA.Z;
210
211 trianglef64.pointB.X = (f64)pointB.X;
212 trianglef64.pointB.Y = (f64)pointB.Y;
213 trianglef64.pointB.Z = (f64)pointB.Z;
214
215 trianglef64.pointC.X = (f64)pointC.X;
216 trianglef64.pointC.Y = (f64)pointC.Y;
217 trianglef64.pointC.Z = (f64)pointC.Z;
218
219 const vector3d<irr::f64> normalf64 = trianglef64.getNormal().normalize();
220 f64 t2;
221
222 if ( core::iszero ( t2 = normalf64.dotProduct(lineVectf64) ) )
223 return false;
224
225 f64 d = trianglef64.pointA.dotProduct(normalf64);
226 f64 t = -(normalf64.dotProduct(linePointf64) - d) / t2;
227
228 outIntersectionf64.X = linePointf64.X + (lineVectf64.X * t);
229 outIntersectionf64.Y = linePointf64.Y + (lineVectf64.Y * t);
230 outIntersectionf64.Z = linePointf64.Z + (lineVectf64.Z * t);
231
232 outIntersection.X = (T)outIntersectionf64.X;
233 outIntersection.Y = (T)outIntersectionf64.Y;
234 outIntersection.Z = (T)outIntersectionf64.Z;
235
236 return true;
237 }
238
239
241
243 {
244 return (pointB - pointA).crossProduct(pointC - pointA);
245 }
246
248
253 bool isFrontFacing(const vector3d<T>& lookDirection) const
254 {
255 const vector3d<T> n = getNormal().normalize();
256 const f32 d = (f32)n.dotProduct(lookDirection);
257 return F32_LOWER_EQUAL_0(d);
258 }
259
262 {
263 return plane3d<T>(pointA, pointB, pointC);
264 }
265
267 T getArea() const
268 {
269 return (pointB - pointA).crossProduct(pointC - pointA).getLength() * 0.5f;
270
271 }
272
274 void set(const core::vector3d<T>& a, const core::vector3d<T>& b, const core::vector3d<T>& c)
275 {
276 pointA = a;
277 pointB = b;
278 pointC = c;
279 }
280
283 vector3d<T> pointB;
284 vector3d<T> pointC;
285
286 private:
287 // Using f64 instead of <T> to avoid integer overflows when T=int (maybe also less floating point troubles).
288 bool isOnSameSide(const vector3d<f64>& p1, const vector3d<f64>& p2,
289 const vector3d<f64>& a, const vector3d<f64>& b) const
290 {
291 static vector3d<f64> bminusa;
292 bminusa.X = b.X - a.X;
293 bminusa.Y = b.Y - a.Y;
294 bminusa.Z = b.Z - a.Z;
295
296 static vector3d<f64> p1minusa;
297 p1minusa.X = p1.X - a.X;
298 p1minusa.Y = p1.Y - a.Y;
299 p1minusa.Z = p1.Z - a.Z;
300
301 static vector3d<f64> p2minusa;
302 p2minusa.X = p2.X - a.X;
303 p2minusa.Y = p2.Y - a.Y;
304 p2minusa.Z = p2.Z - a.Z;
305
306 static vector3d<f64> cp1;
307 INLINE_CROSSPRODUCT(cp1, bminusa, p1minusa);
308
309 static vector3d<f64> cp2;
310 INLINE_CROSSPRODUCT(cp2, bminusa, p2minusa);
311
312 f64 res = cp1.dotProduct(cp2);
313
314 if ( res < 0 )
315 {
316 // This catches some floating point troubles.
317 // Unfortunately slightly expensive and we don't really know the best epsilon for iszero.
318 bminusa.normalize();
319 p1minusa.normalize();
320 INLINE_CROSSPRODUCT(cp1, bminusa, p1minusa);
321
322 if ( core::iszero(cp1.X, (f64)ROUNDING_ERROR_f32)
323 && core::iszero(cp1.Y, (f64)ROUNDING_ERROR_f32)
324 && core::iszero(cp1.Z, (f64)ROUNDING_ERROR_f32) )
325 {
326 res = 0.f;
327 }
328 }
329 return (res >= 0.0f);
330 }
331 };
332
333
336
339
340} // end namespace core
341} // end namespace irr
342
343#endif
344
Axis aligned bounding box in 3d dimensional space.
Definition aabbox3d.h:22
vector3d< T > MaxEdge
The far edge.
Definition aabbox3d.h:347
vector3d< T > MinEdge
The near edge.
Definition aabbox3d.h:344
bool isPointInside(const vector3d< T > &p) const
Determines if a point is within this box.
Definition aabbox3d.h:209
3D line between two points with intersection methods.
Definition line3d.h:19
vector3d< T > start
Start point of line.
Definition line3d.h:130
vector3d< T > getClosestPoint(const vector3d< T > &point) const
Get the closest point on this line to a point.
Definition line3d.h:89
vector3d< T > getVector() const
Get vector of line.
Definition line3d.h:71
vector3d< T > end
End point of line.
Definition line3d.h:132
Template plane class with some intersection testing methods.
Definition plane3d.h:34
3d triangle template class for doing collision detection and other things.
Definition triangle3d.h:23
bool getIntersectionWithLimitedLine(const line3d< T > &line, vector3d< T > &outIntersection) const
Get an intersection with a 3d line.
Definition triangle3d.h:154
triangle3d()
Constructor for an all 0 triangle.
Definition triangle3d.h:27
triangle3d(vector3d< T > v1, vector3d< T > v2, vector3d< T > v3)
Constructor for triangle with given three vertices.
Definition triangle3d.h:29
plane3d< T > getPlane() const
Get the plane of this triangle.
Definition triangle3d.h:261
bool getIntersectionWithLine(const vector3d< T > &linePoint, const vector3d< T > &lineVect, vector3d< T > &outIntersection) const
Get an intersection with a 3d line.
Definition triangle3d.h:172
bool getIntersectionOfPlaneWithLine(const vector3d< T > &linePoint, const vector3d< T > &lineVect, vector3d< T > &outIntersection) const
Calculates the intersection between a 3d line and the plane the triangle is on.
Definition triangle3d.h:187
bool isPointInsideFast(const vector3d< T > &p) const
Check if a point is inside the triangle (border-points count also as inside).
Definition triangle3d.h:126
bool operator!=(const triangle3d< T > &other) const
Inequality operator.
Definition triangle3d.h:38
bool isTotalInsideBox(const aabbox3d< T > &box) const
Determines if the triangle is totally inside a bounding box.
Definition triangle3d.h:46
bool isFrontFacing(const vector3d< T > &lookDirection) const
Test if the triangle would be front or backfacing from any point.
Definition triangle3d.h:253
core::vector3d< T > closestPointOnTriangle(const core::vector3d< T > &p) const
Get the closest point on a triangle to a point on the same plane.
Definition triangle3d.h:70
bool operator==(const triangle3d< T > &other) const
Equality operator.
Definition triangle3d.h:32
bool isPointInside(const vector3d< T > &p) const
Check if a point is inside the triangle (border-points count also as inside).
Definition triangle3d.h:91
bool isTotalOutsideBox(const aabbox3d< T > &box) const
Determines if the triangle is totally outside a bounding box.
Definition triangle3d.h:56
vector3d< f32 > pointA
Definition triangle3d.h:282
vector3d< T > getNormal() const
Get the normal of the triangle.
Definition triangle3d.h:242
void set(const core::vector3d< T > &a, const core::vector3d< T > &b, const core::vector3d< T > &c)
sets the triangle's points
Definition triangle3d.h:274
T getArea() const
Get the area of the triangle.
Definition triangle3d.h:267
3d vector template class with lots of operators and methods.
Definition vector3d.h:23
vector3d< T > crossProduct(const vector3d< T > &p) const
Calculates the cross product with another vector.
Definition vector3d.h:147
T X
X coordinate of the vector.
Definition vector3d.h:408
vector3d< T > & normalize()
Normalizes the vector.
Definition vector3d.h:168
T getDistanceFrom(const vector3d< T > &other) const
Get distance from another point.
Definition vector3d.h:132
bool isBetweenPoints(const vector3d< T > &begin, const vector3d< T > &end) const
Returns if this vector interpreted as a point is on a line between two other points.
Definition vector3d.h:157
T Z
Z coordinate of the vector.
Definition vector3d.h:414
T dotProduct(const vector3d< T > &other) const
Get the dot product with another vector.
Definition vector3d.h:125
T Y
Y coordinate of the vector.
Definition vector3d.h:411
Basic classes such as vectors, planes, arrays, lists, and so on can be found in this namespace.
Definition aabbox3d.h:15
triangle3d< f32 > triangle3df
Typedef for a f32 3d triangle.
Definition triangle3d.h:335
triangle3d< s32 > triangle3di
Typedef for an integer 3d triangle.
Definition triangle3d.h:338
bool iszero(const f64 a, const f64 tolerance=ROUNDING_ERROR_f64)
returns if a equals zero, taking rounding errors into account
Definition irrMath.h:270
Everything in the Irrlicht Engine can be found in this namespace.
Definition Skylicht.h:33
float f32
32 bit floating point variable.
Definition irrTypes.h:104
double f64
64 bit floating point variable.
Definition irrTypes.h:108