Nirtcpp 2.1.0
Nirtcpp is a high-performance c++ graphics engine.
Loading...
Searching...
No Matches
triangle3d.hpp
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 nirtcpp/nirtcpp.hpp
4
5#ifndef NIRT_TRIANGLE_3D_HPP_INCLUDED
6#define NIRT_TRIANGLE_3D_HPP_INCLUDED
7
8#include <nirtcpp/core/engine/vector3d.hpp>
9#include <nirtcpp/core/engine/line3d.hpp>
10#include <nirtcpp/core/engine/plane3d.hpp>
11#include <nirtcpp/core/engine/aabbox3d.hpp>
12
13namespace nirt
14{
15namespace core
16{
17
19 template <class T>
21 {
22 public:
23
27 triangle3d(const vector3d<T>& v1, const vector3d<T>& v2, const vector3d<T>& v3) : pointA(v1), pointB(v2), pointC(v3) {}
28
30 bool operator==(const triangle3d<T>& other) const
31 {
32 return other.pointA==pointA && other.pointB==pointB && other.pointC==pointC;
33 }
34
36 bool operator!=(const triangle3d<T>& other) const
37 {
38 return !(*this==other);
39 }
40
42
44 bool isTotalInsideBox(const aabbox3d<T>& box) const
45 {
46 return (box.isPointInside(pointA) &&
47 box.isPointInside(pointB) &&
48 box.isPointInside(pointC));
49 }
50
52
55 {
56 return ((pointA.X > box.MaxEdge.X && pointB.X > box.MaxEdge.X && pointC.X > box.MaxEdge.X) ||
57
58 (pointA.Y > box.MaxEdge.Y && pointB.Y > box.MaxEdge.Y && pointC.Y > box.MaxEdge.Y) ||
59 (pointA.Z > box.MaxEdge.Z && pointB.Z > box.MaxEdge.Z && pointC.Z > box.MaxEdge.Z) ||
60 (pointA.X < box.MinEdge.X && pointB.X < box.MinEdge.X && pointC.X < box.MinEdge.X) ||
61 (pointA.Y < box.MinEdge.Y && pointB.Y < box.MinEdge.Y && pointC.Y < box.MinEdge.Y) ||
62 (pointA.Z < box.MinEdge.Z && pointB.Z < box.MinEdge.Z && pointC.Z < box.MinEdge.Z));
63 }
64
66
69 {
70 const core::vector3d<T> rab = line3d<T>(pointA, pointB).getClosestPoint(p);
71 const core::vector3d<T> rbc = line3d<T>(pointB, pointC).getClosestPoint(p);
72 const core::vector3d<T> rca = line3d<T>(pointC, pointA).getClosestPoint(p);
73
74 const T d1 = rab.getDistanceFrom(p);
75 const T d2 = rbc.getDistanceFrom(p);
76 const T d3 = rca.getDistanceFrom(p);
77
78 if (d1 < d2)
79 return d1 < d3 ? rab : rca;
80
81 return d2 < d3 ? rbc : rca;
82 }
83
85 /*
86 \param p Point to test. Assumes that this point is already
87 on the plane of the triangle.
88 \return True if the point is inside the triangle, otherwise false. */
89 bool isPointInside(const vector3d<T>& p) const
90 {
92 vector3d<f64> bf64((f64)pointB.X, (f64)pointB.Y, (f64)pointB.Z);
93 vector3d<f64> cf64((f64)pointC.X, (f64)pointC.Y, (f64)pointC.Z);
94 vector3d<f64> pf64((f64)p.X, (f64)p.Y, (f64)p.Z);
95 return (isOnSameSide(pf64, af64, bf64, cf64) &&
96 isOnSameSide(pf64, bf64, af64, cf64) &&
97 isOnSameSide(pf64, cf64, af64, bf64));
98 }
99
101
108 bool isPointInsideFast(const vector3d<T>& p) const
109 {
110 const vector3d<T> a = pointC - pointA;
111 const vector3d<T> b = pointB - pointA;
112 const vector3d<T> c = p - pointA;
113
114 const f64 dotAA = a.dotProduct( a);
115 const f64 dotAB = a.dotProduct( b);
116 const f64 dotAC = a.dotProduct( c);
117 const f64 dotBB = b.dotProduct( b);
118 const f64 dotBC = b.dotProduct( c);
119
120 // get coordinates in barycentric coordinate system
121 const f64 invDenom = 1/(dotAA * dotBB - dotAB * dotAB);
122 const f64 u = (dotBB * dotAC - dotAB * dotBC) * invDenom;
123 const f64 v = (dotAA * dotBC - dotAB * dotAC ) * invDenom;
124
125 // We count border-points as inside to keep downward compatibility.
126 // Rounding-error also needed for some test-cases.
127 return (u > -ROUNDING_ERROR_f32) && (v >= 0) && (u + v < 1+ROUNDING_ERROR_f32);
128
129 }
130
131
133
138 {
139 return getIntersectionWithLine(line.start,
140 line.getVector(), outIntersection) &&
141 outIntersection.isBetweenPoints(line.start, line.end);
142 }
143
144
146
162
163
165
171 {
172 // Work with f64 to get more precise results (makes enough difference to be worth the casts).
176
178 ,vector3d<f64>((f64)pointB.X, (f64)pointB.Y, (f64)pointB.Z)
179 , vector3d<f64>((f64)pointC.X, (f64)pointC.Y, (f64)pointC.Z));
180 const vector3d<nirt::f64> normalf64 = trianglef64.getNormal().normalize();
181 f64 t2;
182
183 if ( core::iszero ( t2 = normalf64.dotProduct(lineVectf64) ) )
184 return false;
185
186 f64 d = trianglef64.pointA.dotProduct(normalf64);
187 f64 t = -(normalf64.dotProduct(linePointf64) - d) / t2;
189
193 return true;
194 }
195
196
198
200 {
201 return (pointB - pointA).crossProduct(pointC - pointA);
202 }
203
205
211 {
212 const vector3d<T> n = getNormal().normalize();
213 const f32 d = (f32)n.dotProduct(lookDirection);
214 return F32_LOWER_EQUAL_0(d);
215 }
216
219 {
220 return plane3d<T>(pointA, pointB, pointC);
221 }
222
224 T getArea() const
225 {
226 return (pointB - pointA).crossProduct(pointC - pointA).getLength() * 0.5f;
227
228 }
229
231 void set(const core::vector3d<T>& a, const core::vector3d<T>& b, const core::vector3d<T>& c)
232 {
233 pointA = a;
234 pointB = b;
235 pointC = c;
236 }
237
240 vector3d<T> pointB;
241 vector3d<T> pointC;
242
243 private:
244 // Using f64 instead of <T> to avoid integer overflows when T=int (maybe also less floating point troubles).
245 bool isOnSameSide(const vector3d<f64>& p1, const vector3d<f64>& p2,
246 const vector3d<f64>& a, const vector3d<f64>& b) const
247 {
248 vector3d<f64> bminusa = b - a;
249 vector3d<f64> cp1 = bminusa.crossProduct(p1 - a);
250 vector3d<f64> cp2 = bminusa.crossProduct(p2 - a);
251 f64 res = cp1.dotProduct(cp2);
252 if ( res < 0 )
253 {
254 // This catches some floating point troubles.
255 // Unfortunately slightly expensive and we don't really know the best epsilon for iszero.
256 vector3d<f64> cp1n = bminusa.normalize().crossProduct((p1 - a).normalize());
257 if (core::iszero(cp1n.X, (f64)ROUNDING_ERROR_f32)
258 && core::iszero(cp1n.Y, (f64)ROUNDING_ERROR_f32)
259 && core::iszero(cp1n.Z, (f64)ROUNDING_ERROR_f32) )
260 {
261 res = 0.f;
262 }
263 }
264 return (res >= 0.0f);
265 }
266 };
267
268
271
274
275} // end namespace core
276} // end namespace nirt
277
278#endif
Axis aligned bounding box in 3d dimensional space.
Definition aabbox3d.hpp:22
bool isPointInside(const vector3d< T > &p) const
Determines if a point is within this box.
Definition aabbox3d.hpp:219
vector3d< T > MinEdge
The near edge.
Definition aabbox3d.hpp:354
vector3d< T > MaxEdge
The far edge.
Definition aabbox3d.hpp:357
3d triangle template class for doing collision detection and other things.
Definition triangle3d.hpp:21
T getArea() const
Get the area of the triangle.
Definition triangle3d.hpp:224
vector3d< T > getNormal() const
Get the normal of the triangle.
Definition triangle3d.hpp:199
void set(const core::vector3d< T > &a, const core::vector3d< T > &b, const core::vector3d< T > &c)
sets the triangle's points
Definition triangle3d.hpp:231
bool isFrontFacing(const vector3d< T > &lookDirection) const
Test if the triangle would be front or backfacing from any point.
Definition triangle3d.hpp:210
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.hpp:68
bool isTotalOutsideBox(const aabbox3d< T > &box) const
Determines if the triangle is totally outside a bounding box.
Definition triangle3d.hpp:54
bool getIntersectionWithLimitedLine(const line3d< T > &line, vector3d< T > &outIntersection) const
Get an intersection with a 3d line.
Definition triangle3d.hpp:136
bool isTotalInsideBox(const aabbox3d< T > &box) const
Determines if the triangle is totally inside a bounding box.
Definition triangle3d.hpp:44
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.hpp:169
bool operator==(const triangle3d< T > &other) const
Equality operator.
Definition triangle3d.hpp:30
vector3d< T > pointA
the three points of the triangle
Definition triangle3d.hpp:239
triangle3d(const vector3d< T > &v1, const vector3d< T > &v2, const vector3d< T > &v3)
Constructor for triangle with given three vertices.
Definition triangle3d.hpp:27
triangle3d()
Constructor for an all 0 triangle.
Definition triangle3d.hpp:25
bool getIntersectionWithLine(const vector3d< T > &linePoint, const vector3d< T > &lineVect, vector3d< T > &outIntersection) const
Get an intersection with a 3d line.
Definition triangle3d.hpp:154
plane3d< T > getPlane() const
Get the plane of this triangle.
Definition triangle3d.hpp:218
bool isPointInsideFast(const vector3d< T > &p) const
Check if a point is inside the triangle (border-points count also as inside)
Definition triangle3d.hpp:108
bool isPointInside(const vector3d< T > &p) const
Check if a point is inside the triangle (border-points count also as inside)
Definition triangle3d.hpp:89
bool operator!=(const triangle3d< T > &other) const
Inequality operator.
Definition triangle3d.hpp:36
bool iszero(const f64 a, const f64 tolerance=ROUNDING_ERROR_f64)
returns if a equals zero, taking rounding errors into account
Definition irrMath.hpp:304
As of Nirtcpp 1.6, position2d is a synonym for vector2d.
Definition vector3d.hpp:11
double f64
64 bit floating point variable.
Definition irrTypes.hpp:114
float f32
32 bit floating point variable.
Definition irrTypes.hpp:110

Nirtcpp    @cppfx.xyz

Esvcpp    esv::print