1 /* Copyright 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.h
16         @author Jukka Jyl�nki
17         @brief The Ray geometry object. */
18 #pragma once
19
20 #include "../MathGeoLibFwd.h"
21 #include "../Math/float3.h"
22
23 #ifdef MATH_OGRE_INTEROP
24 #include <OgreRay.h>
25 #endif
26 #ifdef MATH_URHO3D_INTEROP
27 #include <Urho3D/Math/Ray.h>
28 #endif
29
30 MATH_BEGIN_NAMESPACE
31
32 /// A ray in 3D space is a line that starts from an origin point and extends to infinity in one direction.
33 class Ray
34 {
35 public:
36         /// Specifies the origin of this ray.
37         vec pos;
38
39         /// The normalized direction vector of this ray. [similarOverload: pos]
40         /** @note For proper functionality, this direction vector needs to always be normalized. If you set to this
41                 member manually, remember to make sure you only assign normalized direction vectors. */
42         vec dir;
43
44         /// The default constructor does not initialize any members of this class.
45         /** This means that the values of the members pos and dir are undefined after creating a new Ray using this
46                 default constructor. Remember to assign to them before use.
47                 @see pos, dir. */
48         Ray() {}
49
50         /// Constructs a new ray by explicitly specifying the member variables.
51         /** @param pos The origin position of the ray.
52                 @param dir The direction of the ray. This vector must be normalized, this function will not normalize
53                         the vector for you (for performance reasons).
54                 @see pos, dir. */
55         Ray(const vec &posconst vec &dir);
56
57         /// Converts a Line to a Ray.
58         /** This conversion simply copies the members pos and dir over from the given Line to this Ray.
59                 This means that the new Ray starts at the same position, but only extends to one direction in space,
60                 instead of two.
61                 @see class Line, ToLine(). */
62         explicit Ray(const Line &line);
63
64         /// Converts a LineSegment to a Ray.
65         /** This constructor sets pos = lineSegment.a, and dir = (lineSegment.b - lineSegment.a).Normalized().
66                 @see class LineSegment, ToLineSegment(). */
67         explicit Ray(const LineSegment &lineSegment);
68
69         bool IsFinite() const;
70
71         /// Gets a point along the ray at the given distance.
72         /** Use this function to convert a 1D parametric point along the Ray to a 3D point in the linear space.
73                 @param distance The point to compute. GetPoint(0) will return pos. GetPoint(t) will return a point
74                         at distance |t| from pos. Passing in negative values is allowed, but in that case, the
75                         returned point does not actually lie on this Ray.
76                 @return pos + distance * dir.
77                 @see pos, dir. */
78         vec GetPoint(float distance) const;
79
80         /// Translates this Ray in world space.
81         /** @param offset The amount of displacement to apply to this Ray, in world space coordinates.
82                 @see Transform(). */
83         void Translate(const vec &offset);
84
85         /// Applies a transformation to this Ray, in-place.
86         /** See Translate(), classes float3x3, float3x4, float4x4, Quat. */
87         void Transform(const float3x3 &transform);
88         void Transform(const float3x4 &transform);
89         void Transform(const float4x4 &transform);
90         void Transform(const Quat &transform);
91
92         /// Tests if the given object is fully contained on this ray.
93         /** @param distanceThreshold The magnitude of the epsilon test threshold to use. Since a Ray
94                 is a 1D object in a 3D space, an epsilon threshold is used to allow errors caused by floating-point
95                 inaccuracies.
96                 @return True if this ray contains the given object, up to the given distance threshold.
97                 @see class LineSegment, Distance(), ClosestPoint(), Intersects(). */
98         bool Contains(const vec &point, float distanceThreshold = 1e-3f) const;
99         bool Contains(const LineSegment &lineSegment, float distanceThreshold = 1e-3f) const;
100
101         /// Tests if two rays are equal.
102         /** @return True if this and the given Ray represent the same set of points, up to the given epsilon. */
103         bool Equals(const Ray &otherRay, float epsilon = 1e-3f) const;
104
105         /// Compares whether this Ray and the given Ray are identical bit-by-bit in the underlying representation.
106         /** @note Prefer using this over e.g. memcmp, since there can be SSE-related padding in the structures. */
107         bool BitEquals(const Ray &other) const return pos.BitEquals(other.pos) && dir.BitEquals(other.dir); }
108
109         /// Computes the distance between this ray and the given object.
110         /** This function finds the nearest pair of points on this and the given object, and computes their distance.
111                 If the two objects intersect, or one object is contained inside the other, the returned distance is zero.
112                 @param d [out] If specified, receives the parametric distance along this ray that
113                         specifies the closest point on this ray to the given object. The value returned here can be negative.
114                 @see Contains(), Intersects(), ClosestPoint(), GetPoint(). */
115         float Distance(const vec &point) const float dreturn Distance(point, d); }
116         float Distance(const vec &point, float &dconst;
117
118         /** @param d2 [out] If specified, receives the parametric distance along the other line that specifies the
119                 closest point on that line to this ray. The value returned here can be negative. */
120         float Distance(const Ray &other) const float d, d2; return Distance(other, d, d2); }
121         float Distance(const Ray &other, float &d) const float d2; return Distance(other, d, d2); }
122         float Distance(const Ray &other, float &dfloat &d2) const;
123         float Distance(const Line &other) const float d, d2; return Distance(other, d, d2); }
124         float Distance(const Line &other, float &d) const float d2; return Distance(other, d, d2); }
125         float Distance(const Line &other, float &dfloat &d2) const;
126         float Distance(const LineSegment &other) const float d, d2; return Distance(other, d, d2); }
127         float Distance(const LineSegment &other, float &d) const float d2; return Distance(other, d, d2); }
128         float Distance(const LineSegment &other, float &dfloat &d2) const;
129         float Distance(const Sphere &sphere) const;
130         float Distance(const Capsule &capsule) const;
131
132         /// Computes the closest point on this ray to the given object.
133         /** If the other object intersects this ray, this function will return an arbitrary point inside
134                 the region of intersection.
135                 @param d [out] If specified, receives the parametric distance along this ray that
136                         specifies the closest point on this ray to the given object. The value returned here can be negative.
137                 @see Contains(), Distance(), Intersects(), GetPoint(). */
138         vec ClosestPoint(const vec &targetPoint) const float dreturn ClosestPoint(targetPoint, d); }
139         vec ClosestPoint(const vec &targetPoint, float &dconst;
140         /** @param d2 [out] If specified, receives the parametric distance along the other line that specifies the
141                 closest point on that line to this ray. The value returned here can be negative. */
142         vec ClosestPoint(const Ray &other) const float d, d2; return ClosestPoint(other, d, d2); }
143         vec ClosestPoint(const Ray &other, float &d) const float d2; return ClosestPoint(other, d, d2); }
144         vec ClosestPoint(const Ray &other, float &dfloat &d2) const;
145         vec ClosestPoint(const Line &other) const float d, d2; return ClosestPoint(other, d, d2); }
146         vec ClosestPoint(const Line &other, float &d) const float d2; return ClosestPoint(other, d, d2); }
147         vec ClosestPoint(const Line &other, float &dfloat &d2) const;
148         vec ClosestPoint(const LineSegment &other) const float d, d2; return ClosestPoint(other, d, d2); }
149         vec ClosestPoint(const LineSegment &other, float &d) const float d2; return ClosestPoint(other, d, d2); }
150         vec ClosestPoint(const LineSegment &other, float &dfloat &d2) const;
151
152         /// Tests whether this ray and the given object intersect.      
153         /** Both objects are treated as "solid", meaning that if one of the objects is fully contained inside
154                 another, this function still returns true.
155                 @param d [out] If specified, this parameter will receive the parametric distance of
156                         the intersection point along this object. Use the GetPoint(d) function
157                         to get the actual point of intersection. This pointer may be null.
158                 @param intersectionPoint [out] If specified, receives the actual point of intersection. This pointer
159                         may be null.
160                 @return True if an intersection occurs or one of the objects is contained inside the other, false otherwise.
161                 @see Contains(), Distance(), ClosestPoint(), GetPoint(). */
162         bool Intersects(const Triangle &triangle, float *d, vec *intersectionPoint) const;
163         bool Intersects(const Triangle &triangle) const;
164         bool Intersects(const Plane &plane, float *dconst;
165         bool Intersects(const Plane &plane) const;
166         /** @param intersectionNormal [out] If specified, receives the surface normal of the other object at
167                 the point of intersection. This pointer may be null. */
168         bool Intersects(const Sphere &s, vec *intersectionPoint, vec *intersectionNormal, float *dconst;
169         bool Intersects(const Sphere &s) const;
170         /** @param dNear [out] If specified, receives the distance along this ray to where the ray enters
171                 the bounding box.
172                 @param dFar [out] If specified, receives the distance along this ray to where the ray exits
173                 the bounding box. */
174         bool Intersects(const AABB &aabb, float &dNear, float &dFar) const;
175         bool Intersects(const AABB &aabb) const;
176         bool Intersects(const OBB &obb, float &dNear, float &dFar) const;
177         bool Intersects(const OBB &obb) const;
178         bool Intersects(const Capsule &capsule) const;
179         bool Intersects(const Polygon &polygon) const;
180         bool Intersects(const Frustum &frustum) const;
181         bool Intersects(const Polyhedron &polyhedron) const;
182         /// Tests if this ray intersects the given disc.
183         /// @todo This signature will be moved to bool Intersects(const Disc &disc) const;
184         bool IntersectsDisc(const Circle &disc) const;
185
186         /// Converts this Ray to a Line.
187         /** The pos and dir members of the returned Line will be equal to this Ray. The only difference is
188                 that a Line extends to infinity in two directions, whereas the Ray spans only in the positive
189                 direction.
190                 @see dir, Ray::Ray, class Line, ToLineSegment(). */
191         Line ToLine() const;
192         /// Converts this Ray to a LineSegment.
193         /** @param d Specifies the position of the other endpoint along this Ray. This parameter may be negative,
194                 in which case the returned LineSegment does not lie inside this Ray.
195                 @return A LineSegment with point a at pos, and point b at pos + d * dir.
196                 @see pos, dir, Ray::Ray, class LineSegment, ToLine(). */
197         LineSegment ToLineSegment(float dconst;
198
199         /// Projects this Ray onto the given 1D axis direction vector.
200         /** This function collapses this Ray onto an 1D axis for the purposes of e.g. separate axis test computations.
201                 The function returns a 1D range [outMin, outMax] denoting the interval of the projection.
202                 @param direction The 1D axis to project to. This vector may be unnormalized, in which case the output
203                         of this function gets scaled by the length of this vector.
204                 @param outMin [out] Returns the minimum extent of this object along the projection axis.
205                 @param outMax [out] Returns the maximum extent of this object along the projection axis. */
206         void ProjectToAxis(const vec &direction, float &outMin, float &outMax) const;
207
208         /// Converts this Ray to a LineSegment.
209         /** @param dStart Specifies the position of the first endpoint along this Ray. This parameter may be negative,
210                 in which case the starting point lies outside this Ray to the opposite direction of the Ray.
211                 @param dEnd Specifies the position of the second endpoint along this Ray. This parameter may also be negative.
212                 @return A LineSegment with point a at pos + dStart * dir, and point b at pos + dEnd * dir.
213                 @see pos, dir, Ray::Ray, class LineSegment, ToLine(). */
214         LineSegment ToLineSegment(float dStart, float dEnd) const;
215
216 #ifdef MATH_ENABLE_STL_SUPPORT
217         /// Returns a human-readable representation of this Ray.
218         /** The returned string specifies the position and direction of this Ray. */
219         std::string ToString() const;
220         std::string SerializeToString() const;
221
222         /// Returns a string of C++ code that can be used to construct this object. Useful for generating test cases from badly behaving objects.
223         std::string SerializeToCodeString() const;
224 #endif
225
226         static Ray FromString(const char *str, const char **outEndStr = 0);
227 #ifdef MATH_ENABLE_STL_SUPPORT
228         static Ray FromString(const std::string &str) { return FromString(str.c_str()); }
229 #endif
230
231 #ifdef MATH_QT_INTEROP
232         operator QString() const return toString(); }
233         QString toString() const return QString::fromStdString(ToString()); }
234 #endif
235 #ifdef MATH_OGRE_INTEROP
236         Ray(const Ogre::Ray &other):pos(other.getOrigin()), dir(other.getDirection()) {}
237         operator Ogre::Ray() const return Ogre::Ray(posdir); }
238 #endif
239 #ifdef MATH_URHO3D_INTEROP
240         Ray(const Urho3D::Ray &other) : pos(other.origin_), dir(other.direction_) {}
241         operator Urho3D::Ray() const return Urho3D::Ray(posdir); }
242 #endif
243 };
244
245 /// @note Assumes that transform may contain scaling, and re-normalizes the ray direction
246 ///             after the transform.
247 Ray operator *(const float3x3 &transform, const Ray &ray);
248 /// @note Assumes that transform may contain scaling, and re-normalizes the ray direction
249 ///             after the transform.
250 Ray operator *(const float3x4 &transform, const Ray &ray);
251 /// @note Assumes that transform may contain scaling, and re-normalizes the ray direction
252 ///             after the transform.
253 Ray operator *(const float4x4 &transform, const Ray &ray);
254 Ray operator *(const Quat &transform, const Ray &ray);
255
256 #ifdef MATH_QT_INTEROP
257 Q_DECLARE_METATYPE(Ray)
258 Q_DECLARE_METATYPE(Ray*)
259 #endif
260
261 #ifdef MATH_ENABLE_STL_SUPPORT
262 std::ostream &operator <<(std::ostream &o, const Ray &ray);
263 #endif
264
265 MATH_END_NAMESPACE

Go back to previous page