1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
/**
@file Triangle.h
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2003-04-05
@edited 2008-10-06
@cite Random point method by Greg Turk, Generating random points in triangles. In A. S. Glassner, ed., Graphics Gems, pp. 24-28. Academic Press, 1990
Copyright 2000-2009, Morgan McGuire.
All rights reserved.
*/
#ifndef G3D_TRIANGLE_H
#define G3D_TRIANGLE_H
#include "G3D/platform.h"
#include "G3D/g3dmath.h"
#include "G3D/Vector3.h"
#include "G3D/Plane.h"
#include "G3D/BoundsTrait.h"
#include "G3D/debugAssert.h"
#include <string>
namespace G3D {
/**
A generic triangle representation. This should not be used
as the underlying triangle for creating models; it is intended
for providing fast property queries but requires a lot of
storage and is mostly immutable.
*/
class Triangle {
private:
friend class CollisionDetection;
friend class Ray;
Vector3 _vertex[3];
/** edgeDirection[i] is the normalized vector v[i+1] - v[i] */
Vector3 edgeDirection[3];
float edgeMagnitude[3];
Plane _plane;
Vector3::Axis _primaryAxis;
/** vertex[1] - vertex[0] */
Vector3 _edge01;
/** vertex[2] - vertex[0] */
Vector3 _edge02;
float _area;
void init(const Vector3& v0, const Vector3& v1, const Vector3& v2);
public:
Triangle(class BinaryInput& b);
void serialize(class BinaryOutput& b);
void deserialize(class BinaryInput& b);
Triangle();
Triangle(const Vector3& v0, const Vector3& v1, const Vector3& v2);
~Triangle();
/** 0, 1, or 2 */
inline const Vector3& vertex(int n) const {
debugAssert((n >= 0) && (n < 3));
return _vertex[n];
}
/** vertex[1] - vertex[0] */
inline const Vector3& edge01() const {
return _edge01;
}
/** vertex[2] - vertex[0] */
inline const Vector3& edge02() const {
return _edge02;
}
float area() const;
Vector3::Axis primaryAxis() const {
return _primaryAxis;
}
const Vector3& normal() const;
/** Barycenter */
Vector3 center() const;
const Plane& plane() const;
/** Returns a random point in the triangle. */
Vector3 randomPoint() const;
inline void getRandomSurfacePoint
(Vector3& P,
Vector3& N = Vector3::ignore()) const {
P = randomPoint();
N = normal();
}
/**
For two triangles to be equal they must have
the same vertices <I>in the same order</I>.
That is, vertex[0] == vertex[0], etc.
*/
inline bool operator==(const Triangle& other) const {
for (int i = 0; i < 3; ++i) {
if (_vertex[i] != other._vertex[i]) {
return false;
}
}
return true;
}
inline size_t hashCode() const {
return
_vertex[0].hashCode() +
(_vertex[1].hashCode() >> 2) +
(_vertex[2].hashCode() >> 3);
}
void getBounds(class AABox&) const;
/**
@brief Intersect the ray at distance less than @a distance.
@param distance Set to the maximum distance (can be G3D::inf())
to search for an intersection. On return, this is the smaller
of the distance to the intersection, if one exists, and the original
value.
@param baryCoord If a triangle is hit before @a distance, a
the barycentric coordinates of the hit location on the triangle.
Otherwise, unmodified.
@return True if there was an intersection before the original distance.
*/
bool intersect(const class Ray& ray, float& distance, float baryCoord[3]) const;
};
} // namespace G3D
template <> struct HashTrait<G3D::Triangle> {
static size_t hashCode(const G3D::Triangle& key) { return key.hashCode(); }
};
template<> struct BoundsTrait<class G3D::Triangle> {
static void getBounds(const G3D::Triangle& t, G3D::AABox& out) { t.getBounds(out); }
};
#endif
|