OpenVDB: openvdb/math/Ray.h Source File

OpenVDB 13.0.0

Loading...
Searching...
No Matches
Ray.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3//
4/// @file Ray.h
5///
6/// @author Ken Museth
7///
8/// @brief A Ray class.
9
10#ifndef OPENVDB_MATH_RAY_HAS_BEEN_INCLUDED
11#define OPENVDB_MATH_RAY_HAS_BEEN_INCLUDED
12
13#include "Math.h"
14#include "Vec3.h"
15#include "Transform.h"
16#include <openvdb/util/Assert.h>
17#include <algorithm> // for std::swap()
18#include <iostream> // for std::ostream
19#include <limits> // for std::numeric_limits<Type>::max()
20
21namespace openvdb {
22 OPENVDB_USE_VERSION_NAMESPACE
23namespace OPENVDB_VERSION_NAME {
24namespace math {
25
26template<typename RealT = double>
27 class Ray
28{
29public:
30 static_assert(std::is_floating_point<RealT>::value,
31 "math::Ray requires a floating-point value type");
32
33 using RealType = RealT;
34 using Vec3Type = Vec3<RealT>;
35 using Vec3T = Vec3Type;
36
37 struct TimeSpan {
38 RealT t0, t1;
39 /// @brief Default constructor
40 TimeSpan() {}
41 /// @brief Constructor
42 TimeSpan(RealT _t0, RealT _t1) : t0(_t0), t1(_t1) {}
43 /// @brief Set both times
44 inline void set(RealT _t0, RealT _t1) { t0=_t0; t1=_t1; }
45 /// @brief Get both times
46 inline void get(RealT& _t0, RealT& _t1) const { _t0=t0; _t1=t1; }
47 /// @brief Return @c true if t1 is larger than t0 by at least eps.
48 inline bool valid(RealT eps=math::Delta<RealT>::value()) const { return (t1-t0)>eps; }
49 /// @brief Return the midpoint of the ray.
50 inline RealT mid() const { return 0.5*(t0 + t1); }
51 /// @brief Multiplies both times
52 inline void scale(RealT s) {OPENVDB_ASSERT(s>0); t0*=s; t1*=s; }
53 /// @brief Return @c true if time is inclusive
54 inline bool test(RealT t) const { return (t>=t0 && t<=t1); }
55 };
56
57 Ray(const Vec3Type& eye = Vec3Type(0,0,0),
58 const Vec3Type& direction = Vec3Type(1,0,0),
59 RealT t0 = math::Delta<RealT>::value(),
60 RealT t1 = std::numeric_limits<RealT>::max())
61 : mEye(eye), mDir(direction), mInvDir(1/mDir), mTimeSpan(t0, t1)
62 {
63 }
64
65 inline void setEye(const Vec3Type& eye) { mEye = eye; }
66
67 inline void setDir(const Vec3Type& dir)
68 {
69 mDir = dir;
70 mInvDir = 1/mDir;
71 }
72
73 inline void setMinTime(RealT t0) { OPENVDB_ASSERT(t0>0); mTimeSpan.t0 = t0; }
74
75 inline void setMaxTime(RealT t1) { OPENVDB_ASSERT(t1>0); mTimeSpan.t1 = t1; }
76
77 inline void setTimes(
78 RealT t0 = math::Delta<RealT>::value(),
79 RealT t1 = std::numeric_limits<RealT>::max())
80 {
81 OPENVDB_ASSERT(t0>0 && t1>0);
82 mTimeSpan.set(t0, t1);
83 }
84
85 inline void scaleTimes(RealT scale) { mTimeSpan.scale(scale); }
86
87 inline void reset(
88 const Vec3Type& eye,
89 const Vec3Type& direction,
90 RealT t0 = math::Delta<RealT>::value(),
91 RealT t1 = std::numeric_limits<RealT>::max())
92 {
93 this->setEye(eye);
94 this->setDir(direction);
95 this->setTimes(t0, t1);
96 }
97
98 inline const Vec3T& eye() const {return mEye;}
99
100 inline const Vec3T& dir() const {return mDir;}
101
102 inline const Vec3T& invDir() const {return mInvDir;}
103
104 inline RealT t0() const {return mTimeSpan.t0;}
105
106 inline RealT t1() const {return mTimeSpan.t1;}
107
108 /// @brief Return the position along the ray at the specified time.
109 inline Vec3R operator()(RealT time) const { return mEye + mDir * time; }
110
111 /// @brief Return the starting point of the ray.
112 inline Vec3R start() const { return (*this)(mTimeSpan.t0); }
113
114 /// @brief Return the endpoint of the ray.
115 inline Vec3R end() const { return (*this)(mTimeSpan.t1); }
116
117 /// @brief Return the midpoint of the ray.
118 inline Vec3R mid() const { return (*this)(mTimeSpan.mid()); }
119
120 /// @brief Return @c true if t1 is larger than t0 by at least eps.
121 inline bool valid(RealT eps=math::Delta<float>::value()) const { return mTimeSpan.valid(eps); }
122
123 /// @brief Return @c true if @a time is within t0 and t1, both inclusive.
124 inline bool test(RealT time) const { return mTimeSpan.test(time); }
125
126 /// @brief Return a new Ray that is transformed with the specified map.
127 /// @param map the map from which to construct the new Ray.
128 /// @warning Assumes a linear map and a normalized direction.
129 /// @details The requirement that the direction is normalized
130 /// follows from the transformation of t0 and t1 - and that fact that
131 /// we want applyMap and applyInverseMap to be inverse operations.
132 template<typename MapType>
133 inline Ray applyMap(const MapType& map) const
134 {
135 OPENVDB_ASSERT(map.isLinear());
136 OPENVDB_ASSERT(math::isRelOrApproxEqual(mDir.length(), RealT(1),
137 Tolerance<RealT>::value(), Delta<RealT>::value()));
138 const Vec3T eye = map.applyMap(mEye);
139 const Vec3T dir = map.applyJacobian(mDir);
140 const RealT length = dir.length();
141 return Ray(eye, dir/length, length*mTimeSpan.t0, length*mTimeSpan.t1);
142 }
143
144 /// @brief Return a new Ray that is transformed with the inverse of the specified map.
145 /// @param map the map from which to construct the new Ray by inverse mapping.
146 /// @warning Assumes a linear map and a normalized direction.
147 /// @details The requirement that the direction is normalized
148 /// follows from the transformation of t0 and t1 - and that fact that
149 /// we want applyMap and applyInverseMap to be inverse operations.
150 template<typename MapType>
151 inline Ray applyInverseMap(const MapType& map) const
152 {
153 OPENVDB_ASSERT(map.isLinear());
154 OPENVDB_ASSERT(math::isRelOrApproxEqual(mDir.length(), RealT(1), Tolerance<RealT>::value(), Delta<RealT>::value()));
155 const Vec3T eye = map.applyInverseMap(mEye);
156 const Vec3T dir = map.applyInverseJacobian(mDir);
157 const RealT length = dir.length();
158 return Ray(eye, dir/length, length*mTimeSpan.t0, length*mTimeSpan.t1);
159 }
160
161 /// @brief Return a new ray in world space, assuming the existing
162 /// ray is represented in the index space of the specified grid.
163 template<typename GridType>
164 inline Ray indexToWorld(const GridType& grid) const
165 {
166 return this->applyMap(*(grid.transform().baseMap()));
167 }
168
169 /// @brief Return a new ray in the index space of the specified
170 /// grid, assuming the existing ray is represented in world space.
171 template<typename GridType>
172 inline Ray worldToIndex(const GridType& grid) const
173 {
174 return this->applyInverseMap(*(grid.transform().baseMap()));
175 }
176
177 /// @brief Return true if this ray intersects the specified sphere.
178 /// @param center The center of the sphere in the same space as this ray.
179 /// @param radius The radius of the sphere in the same units as this ray.
180 /// @param t0 The first intersection point if an intersection exists.
181 /// @param t1 The second intersection point if an intersection exists.
182 /// @note If the return value is true, i.e. a hit, and t0 =
183 /// this->t0() or t1 == this->t1() only one true intersection exist.
184 inline bool intersects(const Vec3T& center, RealT radius, RealT& t0, RealT& t1) const
185 {
186 const Vec3T origin = mEye - center;
187 const RealT A = mDir.lengthSqr();
188 const RealT B = 2 * mDir.dot(origin);
189 const RealT C = origin.lengthSqr() - radius * radius;
190 const RealT D = B * B - 4 * A * C;
191
192 if (D < 0) return false;
193
194 const RealT Q = RealT(-0.5)*(B<0 ? (B + Sqrt(D)) : (B - Sqrt(D)));
195
196 t0 = Q / A;
197 t1 = C / Q;
198
199 if (t0 > t1) std::swap(t0, t1);
200 if (t0 < mTimeSpan.t0) t0 = mTimeSpan.t0;
201 if (t1 > mTimeSpan.t1) t1 = mTimeSpan.t1;
202 return t0 <= t1;
203 }
204
205 /// @brief Return true if this ray intersects the specified sphere.
206 /// @param center The center of the sphere in the same space as this ray.
207 /// @param radius The radius of the sphere in the same units as this ray.
208 inline bool intersects(const Vec3T& center, RealT radius) const
209 {
210 RealT t0, t1;
211 return this->intersects(center, radius, t0, t1)>0;
212 }
213
214 /// @brief Return true if this ray intersects the specified sphere.
215 /// @note For intersection this ray is clipped to the two intersection points.
216 /// @param center The center of the sphere in the same space as this ray.
217 /// @param radius The radius of the sphere in the same units as this ray.
218 inline bool clip(const Vec3T& center, RealT radius)
219 {
220 RealT t0, t1;
221 const bool hit = this->intersects(center, radius, t0, t1);
222 if (hit) mTimeSpan.set(t0, t1);
223 return hit;
224 }
225
226 /// @brief Return true if the Ray intersects the specified
227 /// axisaligned bounding box.
228 /// @param bbox Axis-aligned bounding box in the same space as the Ray.
229 /// @param t0 If an intersection is detected this is assigned
230 /// the time for the first intersection point.
231 /// @param t1 If an intersection is detected this is assigned
232 /// the time for the second intersection point.
233 template<typename BBoxT>
234 inline bool intersects(const BBoxT& bbox, RealT& t0, RealT& t1) const
235 {
236 mTimeSpan.get(t0, t1);
237 for (int i = 0; i < 3; ++i) {
238 RealT a = (bbox.min()[i] - mEye[i]) * mInvDir[i];
239 RealT b = (bbox.max()[i] - mEye[i]) * mInvDir[i];
240 if (a > b) std::swap(a, b);
241 if (a > t0) t0 = a;
242 if (b < t1) t1 = b;
243 if (t0 > t1) return false;
244 }
245 return true;
246 }
247
248 /// @brief Return true if this ray intersects the specified bounding box.
249 /// @param bbox Axis-aligned bounding box in the same space as this ray.
250 template<typename BBoxT>
251 inline bool intersects(const BBoxT& bbox) const
252 {
253 RealT t0, t1;
254 return this->intersects(bbox, t0, t1);
255 }
256
257 /// @brief Return true if this ray intersects the specified bounding box.
258 /// @note For intersection this ray is clipped to the two intersection points.
259 /// @param bbox Axis-aligned bounding box in the same space as this ray.
260 template<typename BBoxT>
261 inline bool clip(const BBoxT& bbox)
262 {
263 RealT t0, t1;
264 const bool hit = this->intersects(bbox, t0, t1);
265 if (hit) mTimeSpan.set(t0, t1);
266 return hit;
267 }
268
269 /// @brief Return true if the Ray intersects the plane specified
270 /// by a normal and distance from the origin.
271 /// @param normal Normal of the plane.
272 /// @param distance Distance of the plane to the origin.
273 /// @param t Time of intersection, if one exists.
274 inline bool intersects(const Vec3T& normal, RealT distance, RealT& t) const
275 {
276 const RealT cosAngle = mDir.dot(normal);
277 if (math::isApproxZero(cosAngle)) return false;//parallel
278 t = (distance - mEye.dot(normal))/cosAngle;
279 return this->test(t);
280 }
281
282 /// @brief Return true if the Ray intersects the plane specified
283 /// by a normal and point.
284 /// @param normal Normal of the plane.
285 /// @param point Point in the plane.
286 /// @param t Time of intersection, if one exists.
287 inline bool intersects(const Vec3T& normal, const Vec3T& point, RealT& t) const
288 {
289 return this->intersects(normal, point.dot(normal), t);
290 }
291
292private:
293 Vec3T mEye, mDir, mInvDir;
294 TimeSpan mTimeSpan;
295}; // end of Ray class
296
297
298/// @brief Output streaming of the Ray class.
299/// @note Primarily intended for debugging.
300template<typename RealT>
301 inline std::ostream& operator<<(std::ostream& os, const Ray<RealT>& r)
302{
303 os << "eye=" << r.eye() << " dir=" << r.dir() << " 1/dir="<<r.invDir()
304 << " t0=" << r.t0() << " t1=" << r.t1();
305 return os;
306}
307
308} // namespace math
309} // namespace OPENVDB_VERSION_NAME
310} // namespace openvdb
311
312#endif // OPENVDB_MATH_RAY_HAS_BEEN_INCLUDED
Assert.h
OPENVDB_ASSERT
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Transform.h
Vec3.h
openvdb::v13_0::math::Ray
Definition Ray.h:28
openvdb::v13_0::math::Ray::test
bool test(RealT time) const
Return true if time is within t0 and t1, both inclusive.
Definition Ray.h:124
openvdb::v13_0::math::Ray::Ray
Ray(const Vec3Type &eye=Vec3Type(0, 0, 0), const Vec3Type &direction=Vec3Type(1, 0, 0), RealT t0=math::Delta< RealT >::value(), RealT t1=std::numeric_limits< RealT >::max())
Definition Ray.h:57
openvdb::v13_0::math::Ray::intersects
bool intersects(const Vec3T &normal, RealT distance, RealT &t) const
Return true if the Ray intersects the plane specified by a normal and distance from the origin.
Definition Ray.h:274
openvdb::v13_0::math::Ray::applyInverseMap
Ray applyInverseMap(const MapType &map) const
Return a new Ray that is transformed with the inverse of the specified map.
Definition Ray.h:151
openvdb::v13_0::math::Ray< RealT >::dir
const Vec3T & dir() const
Definition Ray.h:100
openvdb::v13_0::math::Ray::clip
bool clip(const BBoxT &bbox)
Return true if this ray intersects the specified bounding box.
Definition Ray.h:261
openvdb::v13_0::math::Ray::Vec3Type
Vec3< RealT > Vec3Type
Definition Ray.h:34
openvdb::v13_0::math::Ray::setEye
void setEye(const Vec3Type &eye)
Definition Ray.h:65
openvdb::v13_0::math::Ray< RealT >::eye
const Vec3T & eye() const
Definition Ray.h:98
openvdb::v13_0::math::Ray::intersects
bool intersects(const BBoxT &bbox) const
Return true if this ray intersects the specified bounding box.
Definition Ray.h:251
openvdb::v13_0::math::Ray::applyMap
Ray applyMap(const MapType &map) const
Return a new Ray that is transformed with the specified map.
Definition Ray.h:133
openvdb::v13_0::math::Ray::RealType
RealT RealType
Definition Ray.h:33
openvdb::v13_0::math::Ray::operator()
Vec3R operator()(RealT time) const
Return the position along the ray at the specified time.
Definition Ray.h:109
openvdb::v13_0::math::Ray::setDir
void setDir(const Vec3Type &dir)
Definition Ray.h:67
openvdb::v13_0::math::Ray::intersects
bool intersects(const Vec3T &center, RealT radius) const
Return true if this ray intersects the specified sphere.
Definition Ray.h:208
openvdb::v13_0::math::Ray::valid
bool valid(RealT eps=math::Delta< float >::value()) const
Return true if t1 is larger than t0 by at least eps.
Definition Ray.h:121
openvdb::v13_0::math::Ray::scaleTimes
void scaleTimes(RealT scale)
Definition Ray.h:85
openvdb::v13_0::math::Ray::worldToIndex
Ray worldToIndex(const GridType &grid) const
Return a new ray in the index space of the specified grid, assuming the existing ray is represented i...
Definition Ray.h:172
openvdb::v13_0::math::Ray::setTimes
void setTimes(RealT t0=math::Delta< RealT >::value(), RealT t1=std::numeric_limits< RealT >::max())
Definition Ray.h:77
openvdb::v13_0::math::Ray::start
Vec3R start() const
Return the starting point of the ray.
Definition Ray.h:112
openvdb::v13_0::math::Ray::invDir
const Vec3T & invDir() const
Definition Ray.h:102
openvdb::v13_0::math::Ray::setMaxTime
void setMaxTime(RealT t1)
Definition Ray.h:75
openvdb::v13_0::math::Ray::Vec3T
Vec3Type Vec3T
Definition Ray.h:35
openvdb::v13_0::math::Ray::clip
bool clip(const Vec3T &center, RealT radius)
Return true if this ray intersects the specified sphere.
Definition Ray.h:218
openvdb::v13_0::math::Ray::intersects
bool intersects(const BBoxT &bbox, RealT &t0, RealT &t1) const
Return true if the Ray intersects the specified axisaligned bounding box.
Definition Ray.h:234
openvdb::v13_0::math::Ray::intersects
bool intersects(const Vec3T &normal, const Vec3T &point, RealT &t) const
Return true if the Ray intersects the plane specified by a normal and point.
Definition Ray.h:287
openvdb::v13_0::math::Ray< RealT >::t0
RealT t0() const
Definition Ray.h:104
openvdb::v13_0::math::Ray::reset
void reset(const Vec3Type &eye, const Vec3Type &direction, RealT t0=math::Delta< RealT >::value(), RealT t1=std::numeric_limits< RealT >::max())
Definition Ray.h:87
openvdb::v13_0::math::Ray::indexToWorld
Ray indexToWorld(const GridType &grid) const
Return a new ray in world space, assuming the existing ray is represented in the index space of the s...
Definition Ray.h:164
openvdb::v13_0::math::Ray< RealT >::t1
RealT t1() const
Definition Ray.h:106
openvdb::v13_0::math::Ray::end
Vec3R end() const
Return the endpoint of the ray.
Definition Ray.h:115
openvdb::v13_0::math::Ray::intersects
bool intersects(const Vec3T &center, RealT radius, RealT &t0, RealT &t1) const
Return true if this ray intersects the specified sphere.
Definition Ray.h:184
openvdb::v13_0::math::Ray::mid
Vec3R mid() const
Return the midpoint of the ray.
Definition Ray.h:118
openvdb::v13_0::math::Ray::setMinTime
void setMinTime(RealT t0)
Definition Ray.h:73
openvdb::v13_0::math::Vec3
Definition Vec3.h:25
openvdb::v13_0::math::Vec3::length
T length() const
Length of the vector.
Definition Vec3.h:201
openvdb::v13_0::math::Vec3::dot
T dot(const Vec3< T > &v) const
Dot product.
Definition Vec3.h:192
openvdb::v13_0::math::Vec3::lengthSqr
T lengthSqr() const
Definition Vec3.h:212
openvdb::v13_0::math::isApproxZero
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance.
Definition Math.h:362
openvdb::v13_0::math::operator<<
std::ostream & operator<<(std::ostream &os, const BBox< Vec3T > &b)
Definition BBox.h:413
openvdb::v13_0::math::Sqrt
float Sqrt(float x)
Return the square root of a floating-point value.
Definition Math.h:832
openvdb::v13_0::math::isRelOrApproxEqual
bool isRelOrApproxEqual(const Type &a, const Type &b, const Type &absTol, const Type &relTol)
Definition Math.h:478
openvdb::v13_0::math::scale
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition Mat.h:615
openvdb::v13_0::Vec3R
math::Vec3< Real > Vec3R
Definition Types.h:53
openvdb
Definition Exceptions.h:13
openvdb::v13_0::math::Delta::value
static T value()
Definition Math.h:167
openvdb::v13_0::math::Ray::TimeSpan::TimeSpan
TimeSpan(RealT _t0, RealT _t1)
Constructor.
Definition Ray.h:42
openvdb::v13_0::math::Ray::TimeSpan::mid
RealT mid() const
Return the midpoint of the ray.
Definition Ray.h:50
openvdb::v13_0::math::Ray::TimeSpan::TimeSpan
TimeSpan()
Default constructor.
Definition Ray.h:40
openvdb::v13_0::math::Ray::TimeSpan::test
bool test(RealT t) const
Return true if time is inclusive.
Definition Ray.h:54
openvdb::v13_0::math::Ray::TimeSpan::scale
void scale(RealT s)
Multiplies both times.
Definition Ray.h:52
openvdb::v13_0::math::Ray::TimeSpan::t1
RealT t1
Definition Ray.h:38
openvdb::v13_0::math::Ray::TimeSpan::valid
bool valid(RealT eps=math::Delta< RealT >::value()) const
Return true if t1 is larger than t0 by at least eps.
Definition Ray.h:48
openvdb::v13_0::math::Ray::TimeSpan::t0
RealT t0
Definition Ray.h:38
openvdb::v13_0::math::Ray::TimeSpan::set
void set(RealT _t0, RealT _t1)
Set both times.
Definition Ray.h:44
openvdb::v13_0::math::Ray::TimeSpan::get
void get(RealT &_t0, RealT &_t1) const
Get both times.
Definition Ray.h:46
openvdb::v13_0::math::Tolerance::value
static T value()
Definition Math.h:159
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218