1 /* Copyright 2011 Jukka Jyl�nki
2
3    Licensed under the Apache License, Version 2.0 (the "License");
4    you may not use this file except in compliance with the License.
5    You may obtain a copy of the License at
6
7        http://www.apache.org/licenses/LICENSE-2.0
8
9    Unless required by applicable law or agreed to in writing, software
10    distributed under the License is distributed on an "AS IS" BASIS,
11    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    See the License for the specific language governing permissions and
13    limitations under the License. */
14
15 /** @file Ray.cpp
16         @author Jukka Jyl�nki
17         @brief Implementation for the Ray geometry object. */
18 #include "Geometry/AABB.h"
19 #include "Geometry/Line.h"
20 #include "Geometry/Ray.h"
21 #include "Geometry/LineSegment.h"
22 #include "Math/float3x3.h"
23 #include "Math/float3x4.h"
24 #include "Math/float4x4.h"
25 #include "Geometry/OBB.h"
26 #include "Geometry/Plane.h"
27 #include "Geometry/Polygon.h"
28 #include "Geometry/Polyhedron.h"
29 #include "Geometry/Frustum.h"
30 #include "Math/Quat.h"
31 #include "Geometry/Sphere.h"
32 #include "Geometry/Capsule.h"
33 #include "Geometry/Triangle.h"
34 #include "Geometry/Circle.h"
35 #include "Math/MathFunc.h"
36
37 MATH_BEGIN_NAMESPACE
38
39 Ray::Ray(const float3 &pos_, const float3 &dir_)
40 :pos(pos_), dir(dir_)
41 {
42         assume(dir.IsNormalized());
43 }
44
45 Ray::Ray(const Line &line)
46 :pos(line.pos), dir(line.dir)
47 {
48         assume(dir.IsNormalized());
49 }
50
51 Ray::Ray(const LineSegment &lineSegment)
52 :pos(lineSegment.a), dir(lineSegment.Dir())
53 {
54 }
55
56 float3 Ray::GetPoint(float d) const
57 {
58         assert(dir.IsNormalized());
59         return pos + d * dir;
60 }
61
62 void Ray::Transform(const float3x3 &transform)
63 {
64         pos = transform.Transform(pos);
65         dir = transform.Transform(dir);
66 }
67
68 void Ray::Transform(const float3x4 &transform)
69 {
70         pos = transform.TransformPos(pos);
71         dir = transform.TransformDir(dir);
72 }
73
74 void Ray::Transform(const float4x4 &transform)
75 {
76         pos = transform.TransformPos(pos);
77         dir = transform.TransformDir(dir);
78 }
79
80 void Ray::Transform(const Quat &transform)
81 {
82         pos = transform.Transform(pos);
83         dir = transform.Transform(dir);
84 }
85
86 bool Ray::Contains(const float3 &point, float distanceThreshold) const
87 {
88         return ClosestPoint(point).DistanceSq(point) <= distanceThreshold;
89 }
90
91 bool Ray::Contains(const LineSegment &lineSegment, float distanceThreshold) const
92 {
93         return Contains(lineSegment.a, distanceThreshold) && Contains(lineSegment.b, distanceThreshold);
94 }
95
96 bool Ray::Equals(const Ray &rhs, float epsilon) const
97 {
98         return pos.Equals(rhs.pos, epsilon) && dir.Equals(rhs.dir, epsilon);
99 }
100
101 float Ray::Distance(const float3 &point, float *d) const
102 {
103         return ClosestPoint(point, d).Distance(point);
104 }
105
106 float Ray::Distance(const float3 &point) const
107 {
108         return Distance(point, 0);
109 }
110
111 float Ray::Distance(const Ray &other, float *d, float *d2) const
112 {
113         float u2;
114         float3 c = ClosestPoint(other, d, &u2);
115         if (d2) *d2 = u2;
116         return c.Distance(other.GetPoint(u2));
117 }
118
119 float Ray::Distance(const Ray &ray) const
120 {
121         return Distance(ray, 0, 0);
122 }
123
124 float Ray::Distance(const Line &other, float *d, float *d2) const
125 {
126         float u2;
127         float3 c = ClosestPoint(other, d, &u2);
128         if (d2) *d2 = u2;
129         return c.Distance(other.GetPoint(u2));
130 }
131
132 float Ray::Distance(const Line &line) const
133 {
134         return Distance(line, 0, 0);
135 }
136
137 float Ray::Distance(const LineSegment &other, float *d, float *d2) const
138 {
139         float u2;
140         float3 c = ClosestPoint(other, d, &u2);
141         if (d2) *d2 = u2;
142         return c.Distance(other.GetPoint(u2));
143 }
144
145 float Ray::Distance(const LineSegment &lineSegment) const
146 {
147         return Distance(lineSegment, 0, 0);
148 }
149
150 float Ray::Distance(const Sphere &sphere) const
151 {
152         return Max(0.f, Distance(sphere.pos) - sphere.r);
153 }
154
155 float Ray::Distance(const Capsule &capsule) const
156 {
157         return Max(0.f, Distance(capsule.l) - capsule.r);
158 }
159
160 float3 Ray::ClosestPoint(const float3 &targetPoint, float *d) const
161 {
162         float u = Max(0.f, Dot(targetPoint - posdir));
163         if (d)
164                 *d = u;
165         return GetPoint(u);
166 }
167
168 float3 Ray::ClosestPoint(const Ray &other, float *d, float *d2) const
169 {
170         ///\bug Properly cap d2.
171         return Line::ClosestPointLineLine(pospos + dir, other.pos, other.pos + other.dir, d, d2);
172 }
173
174 float3 Ray::ClosestPoint(const Line &other, float *d, float *d2) const
175 {
176         return Line::ClosestPointLineLine(pospos + dir, other.pos, other.pos + other.dir, d, d2);
177 }
178
179 float3 Ray::ClosestPoint(const LineSegment &other, float *d, float *d2) const
180 {
181         ///\bug Properly cap d2.
182         return Line::ClosestPointLineLine(pospos + dir, other.a, other.b, d, d2);
183 }
184
185 bool Ray::Intersects(const Triangle &triangle, float *d, float3 *intersectionPoint) const
186 {
187         return triangle.Intersects(*this, d, intersectionPoint);
188 }
189
190 bool Ray::Intersects(const Triangle &triangle) const
191 {
192         return triangle.Intersects(*this, 0, 0);
193 }
194
195 bool Ray::Intersects(const Plane &plane, float *d) const
196 {
197         return plane.Intersects(*this, d);
198 }
199
200 bool Ray::Intersects(const Plane &plane) const
201 {
202         return plane.Intersects(*this, 0);
203 }
204
205 bool Ray::Intersects(const Sphere &sphere, float3 *intersectionPoint, float3 *intersectionNormal, float *d) const
206 {
207         return sphere.Intersects(*this, intersectionPoint, intersectionNormal, d);
208 }
209
210 bool Ray::Intersects(const Sphere &sphere) const
211 {
212         return sphere.Intersects(*this, 0, 0, 0);
213 }
214
215 bool Ray::Intersects(const AABB &aabb, float *dNear, float *dFar) const
216 {
217         return aabb.Intersects(*this, dNear, dFar);
218 }
219
220 bool Ray::Intersects(const AABB &aabb) const
221 {
222         return aabb.Intersects(*this, 0, 0);
223 }
224
225 bool Ray::Intersects(const OBB &obb, float *dNear, float *dFar) const
226 {
227         return obb.Intersects(*this, dNear, dFar);
228 }
229
230 bool Ray::Intersects(const OBB &obb) const
231 {
232         return obb.Intersects(*this, 0, 0);
233 }
234
235 bool Ray::Intersects(const Capsule &capsule) const
236 {
237         return capsule.Intersects(*this);
238 }
239
240 bool Ray::Intersects(const Polygon &polygon) const
241 {
242         return polygon.Intersects(*this);
243 }
244
245 bool Ray::Intersects(const Frustum &frustum) const
246 {
247         return frustum.Intersects(*this);
248 }
249
250 bool Ray::Intersects(const Polyhedron &polyhedron) const
251 {
252         return polyhedron.Intersects(*this);
253 }
254
255 bool Ray::IntersectsDisc(const Circle &disc) const
256 {
257         return disc.IntersectsDisc(*this);
258 }
259
260 Line Ray::ToLine() const
261 {
262         return Line(posdir);
263 }
264
265 LineSegment Ray::ToLineSegment(float d) const
266 {
267         return LineSegment(posGetPoint(d));
268 }
269
270 #ifdef MATH_ENABLE_STL_SUPPORT
271 std::string Ray::ToString() const
272 {
273         char str[256];
274         sprintf(str, "Ray(Pos:(%.2f, %.2f, %.2f) Dir:(%.2f, %.2f, %.2f))"pos.xpos.ypos.zdir.xdir.ydir.z);
275         return str;
276 }
277 #endif
278
279 Ray operator *(const float3x3 &transform, const Ray &ray)
280 {
281         return Ray(transform * ray.pos, transform * ray.dir);
282 }
283
284 Ray operator *(const float3x4 &transform, const Ray &ray)
285 {
286         return Ray(transform.MulPos(ray.pos), transform.MulDir(ray.dir));
287 }
288
289 Ray operator *(const float4x4 &transform, const Ray &ray)
290 {
291         return Ray(transform.MulPos(ray.pos), transform.MulDir(ray.dir));
292 }
293
294 Ray operator *(const Quat &transform, const Ray &ray)
295 {
296         return Ray(transform * ray.pos, transform * ray.dir);
297 }
298
299 MATH_END_NAMESPACE

Go back to previous page