Initial Patch of Auction House bot rev. 135
[auctionmangos.git] / dep / include / g3dlite / G3D / Ray.h
blob3b54f145c338396b9f9e853e746afd9de0f6f6af
1 /**
2 @file Ray.h
4 Ray class
6 @maintainer Morgan McGuire, matrix@graphics3d.com
8 @created 2002-07-12
9 @edited 2006-02-21
12 #ifndef G3D_RAY_H
13 #define G3D_RAY_H
15 #include "G3D/platform.h"
16 #include "G3D/Vector3.h"
17 #include "G3D/Triangle.h"
19 namespace G3D {
21 /**
22 A 3D Ray.
24 class Ray {
25 private:
26 Ray(const Vector3& origin, const Vector3& direction) {
27 this->origin = origin;
28 this->direction = direction;
31 public:
32 Vector3 origin;
34 /**
35 Not unit length
37 Vector3 direction;
39 Ray() : origin(Vector3::zero()), direction(Vector3::zero()) {}
41 virtual ~Ray() {}
43 /**
44 Creates a Ray from a origin and a (nonzero) direction.
46 static Ray fromOriginAndDirection(const Vector3& point, const Vector3& direction) {
47 return Ray(point, direction);
50 Ray unit() const {
51 return Ray(origin, direction.unit());
54 /**
55 Returns the closest point on the Ray to point.
57 Vector3 closestPoint(const Vector3& point) const {
58 float t = direction.dot(point - this->origin);
59 if (t < 0) {
60 return this->origin;
61 } else {
62 return this->origin + direction * t;
66 /**
67 Returns the closest distance between point and the Ray
69 float distance(const Vector3& point) const {
70 return (closestPoint(point) - point).magnitude();
73 /**
74 Returns the point where the Ray and plane intersect. If there
75 is no intersection, returns a point at infinity.
77 Planes are considered one-sided, so the ray will not intersect
78 a plane where the normal faces in the traveling direction.
80 Vector3 intersection(const class Plane& plane) const;
82 /**
83 Returns the distance until intersection with the (solid) sphere.
84 Will be 0 if inside the sphere, inf if there is no intersection.
86 The ray direction is <B>not</B> normalized. If the ray direction
87 has unit length, the distance from the origin to intersection
88 is equal to the time. If the direction does not have unit length,
89 the distance = time * direction.length().
91 See also the G3D::CollisionDetection "movingPoint" methods,
92 which give more information about the intersection.
94 float intersectionTime(const class Sphere& sphere) const;
96 float intersectionTime(const class Plane& plane) const;
98 float intersectionTime(const class Box& box) const;
100 float intersectionTime(const class AABox& box) const;
103 The three extra arguments are the weights of vertices 0, 1, and 2
104 at the intersection point; they are useful for texture mapping
105 and interpolated normals.
107 float intersectionTime(
108 const Vector3& v0, const Vector3& v1, const Vector3& v2,
109 const Vector3& edge01, const Vector3& edge02,
110 double& w0, double& w1, double& w2) const;
113 Ray-triangle intersection for a 1-sided triangle. Fastest version.
114 @cite http://www.acm.org/jgt/papers/MollerTrumbore97/
115 http://www.graphics.cornell.edu/pubs/1997/MT97.html
117 inline float intersectionTime(
118 const Vector3& vert0,
119 const Vector3& vert1,
120 const Vector3& vert2,
121 const Vector3& edge01,
122 const Vector3& edge02) const;
125 inline float intersectionTime(
126 const Vector3& vert0,
127 const Vector3& vert1,
128 const Vector3& vert2) const {
130 return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0);
134 inline float intersectionTime(
135 const Vector3& vert0,
136 const Vector3& vert1,
137 const Vector3& vert2,
138 double& w0,
139 double& w1,
140 double& w2) const {
142 return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0, w0, w1, w2);
145 /* One-sided triangle
147 inline float intersectionTime(const Triangle& triangle) const {
148 return intersectionTime(
149 triangle.vertex(0), triangle.vertex(1), triangle.vertex(2),
150 triangle.edge01, triangle.edge02);
153 inline float intersectionTime(
154 const Triangle& triangle,
155 double& w0,
156 double& w1,
157 double& w2) const {
158 return intersectionTime(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2),
159 triangle.edge01, triangle.edge02, w0, w1, w2);
162 /** Refracts about the normal
163 using G3D::Vector3::refractionDirection
164 and bumps the ray slightly from the newOrigin. */
165 Ray refract(
166 const Vector3& newOrigin,
167 const Vector3& normal,
168 float iInside,
169 float iOutside) const;
171 /** Reflects about the normal
172 using G3D::Vector3::reflectionDirection
173 and bumps the ray slightly from
174 the newOrigin. */
175 Ray reflect(
176 const Vector3& newOrigin,
177 const Vector3& normal) const;
181 #define EPSILON 0.000001
182 #define CROSS(dest,v1,v2) \
183 dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
184 dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
185 dest[2]=v1[0]*v2[1]-v1[1]*v2[0];
187 #define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
189 #define SUB(dest,v1,v2) \
190 dest[0]=v1[0]-v2[0]; \
191 dest[1]=v1[1]-v2[1]; \
192 dest[2]=v1[2]-v2[2];
194 inline float Ray::intersectionTime(
195 const Vector3& vert0,
196 const Vector3& vert1,
197 const Vector3& vert2,
198 const Vector3& edge1,
199 const Vector3& edge2) const {
201 (void)vert1;
202 (void)vert2;
204 // Barycenteric coords
205 float u, v;
207 float tvec[3], pvec[3], qvec[3];
209 // begin calculating determinant - also used to calculate U parameter
210 CROSS(pvec, direction, edge2);
212 // if determinant is near zero, ray lies in plane of triangle
213 const float det = DOT(edge1, pvec);
215 if (det < EPSILON) {
216 return (float)inf();
219 // calculate distance from vert0 to ray origin
220 SUB(tvec, origin, vert0);
222 // calculate U parameter and test bounds
223 u = DOT(tvec, pvec);
224 if ((u < 0.0f) || (u > det)) {
225 // Hit the plane outside the triangle
226 return (float)inf();
229 // prepare to test V parameter
230 CROSS(qvec, tvec, edge1);
232 // calculate V parameter and test bounds
233 v = DOT(direction, qvec);
234 if ((v < 0.0f) || (u + v > det)) {
235 // Hit the plane outside the triangle
236 return (float)inf();
240 // Case where we don't need correct (u, v):
241 const float t = DOT(edge2, qvec);
243 if (t >= 0.0f) {
244 // Note that det must be positive
245 return t / det;
246 } else {
247 // We had to travel backwards in time to intersect
248 return (float)inf();
253 inline float Ray::intersectionTime(
254 const Vector3& vert0,
255 const Vector3& vert1,
256 const Vector3& vert2,
257 const Vector3& edge1,
258 const Vector3& edge2,
259 double& w0,
260 double& w1,
261 double& w2) const {
263 (void)vert1;
264 (void)vert2;
266 // Barycenteric coords
267 float u, v;
269 float tvec[3], pvec[3], qvec[3];
271 // begin calculating determinant - also used to calculate U parameter
272 CROSS(pvec, direction, edge2);
274 // if determinant is near zero, ray lies in plane of triangle
275 const float det = DOT(edge1, pvec);
277 if (det < EPSILON) {
278 return (float)inf();
281 // calculate distance from vert0 to ray origin
282 SUB(tvec, origin, vert0);
284 // calculate U parameter and test bounds
285 u = DOT(tvec, pvec);
286 if ((u < 0.0f) || (u > det)) {
287 // Hit the plane outside the triangle
288 return (float)inf();
291 // prepare to test V parameter
292 CROSS(qvec, tvec, edge1);
294 // calculate V parameter and test bounds
295 v = DOT(direction, qvec);
296 if ((v < 0.0f) || (u + v > det)) {
297 // Hit the plane outside the triangle
298 return (float)inf();
301 float t = DOT(edge2, qvec);
303 if (t >= 0) {
304 const float inv_det = 1.0f / det;
305 t *= inv_det;
306 u *= inv_det;
307 v *= inv_det;
309 w0 = (1.0f - u - v);
310 w1 = u;
311 w2 = v;
313 return t;
314 } else {
315 // We had to travel backwards in time to intersect
316 return (float)inf();
320 #undef EPSILON
321 #undef CROSS
322 #undef DOT
323 #undef SUB
325 }// namespace
327 #endif