OpenVDB  7.0.0
Ray.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 //
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 <algorithm> // for std::swap()
17 #include <iostream> // for std::ostream
18 #include <limits> // for std::numeric_limits<Type>::max()
19 
20 namespace openvdb {
22 namespace OPENVDB_VERSION_NAME {
23 namespace math {
24 
25 template<typename RealT = double>
26 class Ray
27 {
28 public:
29  static_assert(std::is_floating_point<RealT>::value,
30  "math::Ray requires a floating-point value type");
31 
32  using RealType = RealT;
34  using Vec3T = Vec3Type;
35 
36  struct TimeSpan {
37  RealT t0, t1;
39  TimeSpan() {}
41  TimeSpan(RealT _t0, RealT _t1) : t0(_t0), t1(_t1) {}
43  inline void set(RealT _t0, RealT _t1) { t0=_t0; t1=_t1; }
45  inline void get(RealT& _t0, RealT& _t1) const { _t0=t0; _t1=t1; }
47  inline bool valid(RealT eps=math::Delta<RealT>::value()) const { return (t1-t0)>eps; }
49  inline RealT mid() const { return 0.5*(t0 + t1); }
51  inline void scale(RealT s) {assert(s>0); t0*=s; t1*=s; }
53  inline bool test(RealT t) const { return (t>=t0 && t<=t1); }
54  };
55 
56  Ray(const Vec3Type& eye = Vec3Type(0,0,0),
57  const Vec3Type& direction = Vec3Type(1,0,0),
58  RealT t0 = math::Delta<RealT>::value(),
60  : mEye(eye), mDir(direction), mInvDir(1/mDir), mTimeSpan(t0, t1)
61  {
62  }
63 
64  inline void setEye(const Vec3Type& eye) { mEye = eye; }
65 
66  inline void setDir(const Vec3Type& dir)
67  {
68  mDir = dir;
69  mInvDir = 1/mDir;
70  }
71 
72  inline void setMinTime(RealT t0) { assert(t0>0); mTimeSpan.t0 = t0; }
73 
74  inline void setMaxTime(RealT t1) { assert(t1>0); mTimeSpan.t1 = t1; }
75 
76  inline void setTimes(
77  RealT t0 = math::Delta<RealT>::value(),
79  {
80  assert(t0>0 && t1>0);
81  mTimeSpan.set(t0, t1);
82  }
83 
84  inline void scaleTimes(RealT scale) { mTimeSpan.scale(scale); }
85 
86  inline void reset(
87  const Vec3Type& eye,
88  const Vec3Type& direction,
89  RealT t0 = math::Delta<RealT>::value(),
91  {
92  this->setEye(eye);
93  this->setDir(direction);
94  this->setTimes(t0, t1);
95  }
96 
97  inline const Vec3T& eye() const {return mEye;}
98 
99  inline const Vec3T& dir() const {return mDir;}
100 
101  inline const Vec3T& invDir() const {return mInvDir;}
102 
103  inline RealT t0() const {return mTimeSpan.t0;}
104 
105  inline RealT t1() const {return mTimeSpan.t1;}
106 
108  inline Vec3R operator()(RealT time) const { return mEye + mDir * time; }
109 
111  inline Vec3R start() const { return (*this)(mTimeSpan.t0); }
112 
114  inline Vec3R end() const { return (*this)(mTimeSpan.t1); }
115 
117  inline Vec3R mid() const { return (*this)(mTimeSpan.mid()); }
118 
120  inline bool valid(RealT eps=math::Delta<float>::value()) const { return mTimeSpan.valid(eps); }
121 
123  inline bool test(RealT time) const { return mTimeSpan.test(time); }
124 
131  template<typename MapType>
132  inline Ray applyMap(const MapType& map) const
133  {
134  assert(map.isLinear());
135  assert(math::isRelOrApproxEqual(mDir.length(), RealT(1),
137  const Vec3T eye = map.applyMap(mEye);
138  const Vec3T dir = map.applyJacobian(mDir);
139  const RealT length = dir.length();
140  return Ray(eye, dir/length, length*mTimeSpan.t0, length*mTimeSpan.t1);
141  }
142 
149  template<typename MapType>
150  inline Ray applyInverseMap(const MapType& map) const
151  {
152  assert(map.isLinear());
153  assert(math::isRelOrApproxEqual(mDir.length(), RealT(1), Tolerance<RealT>::value(), Delta<RealT>::value()));
154  const Vec3T eye = map.applyInverseMap(mEye);
155  const Vec3T dir = map.applyInverseJacobian(mDir);
156  const RealT length = dir.length();
157  return Ray(eye, dir/length, length*mTimeSpan.t0, length*mTimeSpan.t1);
158  }
159 
162  template<typename GridType>
163  inline Ray indexToWorld(const GridType& grid) const
164  {
165  return this->applyMap(*(grid.transform().baseMap()));
166  }
167 
170  template<typename GridType>
171  inline Ray worldToIndex(const GridType& grid) const
172  {
173  return this->applyInverseMap(*(grid.transform().baseMap()));
174  }
175 
183  inline bool intersects(const Vec3T& center, RealT radius, RealT& t0, RealT& t1) const
184  {
185  const Vec3T origin = mEye - center;
186  const RealT A = mDir.lengthSqr();
187  const RealT B = 2 * mDir.dot(origin);
188  const RealT C = origin.lengthSqr() - radius * radius;
189  const RealT D = B * B - 4 * A * C;
190 
191  if (D < 0) return false;
192 
193  const RealT Q = RealT(-0.5)*(B<0 ? (B + Sqrt(D)) : (B - Sqrt(D)));
194 
195  t0 = Q / A;
196  t1 = C / Q;
197 
198  if (t0 > t1) std::swap(t0, t1);
199  if (t0 < mTimeSpan.t0) t0 = mTimeSpan.t0;
200  if (t1 > mTimeSpan.t1) t1 = mTimeSpan.t1;
201  return t0 <= t1;
202  }
203 
207  inline bool intersects(const Vec3T& center, RealT radius) const
208  {
209  RealT t0, t1;
210  return this->intersects(center, radius, t0, t1)>0;
211  }
212 
217  inline bool clip(const Vec3T& center, RealT radius)
218  {
219  RealT t0, t1;
220  const bool hit = this->intersects(center, radius, t0, t1);
221  if (hit) mTimeSpan.set(t0, t1);
222  return hit;
223  }
224 
232  template<typename BBoxT>
233  inline bool intersects(const BBoxT& bbox, RealT& t0, RealT& t1) const
234  {
235  mTimeSpan.get(t0, t1);
236  for (int i = 0; i < 3; ++i) {
237  RealT a = (bbox.min()[i] - mEye[i]) * mInvDir[i];
238  RealT b = (bbox.max()[i] - mEye[i]) * mInvDir[i];
239  if (a > b) std::swap(a, b);
240  if (a > t0) t0 = a;
241  if (b < t1) t1 = b;
242  if (t0 > t1) return false;
243  }
244  return true;
245  }
246 
249  template<typename BBoxT>
250  inline bool intersects(const BBoxT& bbox) const
251  {
252  RealT t0, t1;
253  return this->intersects(bbox, t0, t1);
254  }
255 
259  template<typename BBoxT>
260  inline bool clip(const BBoxT& bbox)
261  {
262  RealT t0, t1;
263  const bool hit = this->intersects(bbox, t0, t1);
264  if (hit) mTimeSpan.set(t0, t1);
265  return hit;
266  }
267 
273  inline bool intersects(const Vec3T& normal, RealT distance, RealT& t) const
274  {
275  const RealT cosAngle = mDir.dot(normal);
276  if (math::isApproxZero(cosAngle)) return false;//parallel
277  t = (distance - mEye.dot(normal))/cosAngle;
278  return this->test(t);
279  }
280 
286  inline bool intersects(const Vec3T& normal, const Vec3T& point, RealT& t) const
287  {
288  return this->intersects(normal, point.dot(normal), t);
289  }
290 
291 private:
292  Vec3T mEye, mDir, mInvDir;
293  TimeSpan mTimeSpan;
294 }; // end of Ray class
295 
296 
299 template<typename RealT>
300 inline std::ostream& operator<<(std::ostream& os, const Ray<RealT>& r)
301 {
302  os << "eye=" << r.eye() << " dir=" << r.dir() << " 1/dir="<<r.invDir()
303  << " t0=" << r.t0() << " t1=" << r.t1();
304  return os;
305 }
306 
307 } // namespace math
308 } // namespace OPENVDB_VERSION_NAME
309 } // namespace openvdb
310 
311 #endif // OPENVDB_MATH_RAY_HAS_BEEN_INCLUDED
void scaleTimes(RealT scale)
Definition: Ray.h:84
double RealType
Definition: Ray.h:32
Delta for small floating-point offsets.
Definition: Math.h:97
bool intersects(const BBoxT &bbox) const
Return true if this ray intersects the specified bounding box.
Definition: Ray.h:250
void reset(const Vec3Type &eye, const Vec3Type &direction, RealT t0=math::Delta< RealT >::value(), RealT t1=std::numeric_limits< RealT >::max())
Definition: Ray.h:86
bool intersects(const BBoxT &bbox, RealT &t0, RealT &t1) const
Return true if the Ray intersects the specified axisaligned bounding box.
Definition: Ray.h:233
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
void setMaxTime(RealT t1)
Definition: Ray.h:74
TimeSpan()
Default constructor.
Definition: Ray.h:39
bool test(RealT t) const
Return true if time is inclusive.
Definition: Ray.h:53
Vec3R mid() const
Return the midpoint of the ray.
Definition: Ray.h:117
void setMinTime(RealT t0)
Definition: Ray.h:72
RealT t1
Definition: Ray.h:37
Vec3R operator()(RealT time) const
Return the position along the ray at the specified time.
Definition: Ray.h:108
T length() const
Length of the vector.
Definition: Vec3.h:198
Vec3R start() const
Return the starting point of the ray.
Definition: Ray.h:111
void setEye(const Vec3Type &eye)
Definition: Ray.h:64
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:171
TimeSpan(RealT _t0, RealT _t1)
Constructor.
Definition: Ray.h:41
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:189
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:102
Definition: Ray.h:26
bool isRelOrApproxEqual(const Type &a, const Type &b, const Type &absTol, const Type &relTol)
Definition: Math.h:398
Definition: Exceptions.h:13
const Vec3T & eye() const
Definition: Ray.h:97
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:286
bool test(RealT time) const
Return true if time is within t0 and t1, both inclusive.
Definition: Ray.h:123
bool clip(const Vec3T &center, RealT radius)
Return true if this ray intersects the specified sphere.
Definition: Ray.h:217
void scale(RealT s)
Multiplies both times.
Definition: Ray.h:51
void setTimes(RealT t0=math::Delta< RealT >::value(), RealT t1=std::numeric_limits< RealT >::max())
Definition: Ray.h:76
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:708
Ray applyInverseMap(const MapType &map) const
Return a new Ray that is transformed with the inverse of the specified map.
Definition: Ray.h:150
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:273
Tolerance for floating-point comparison.
Definition: Math.h:90
RealT mid() const
Return the midpoint of the ray.
Definition: Ray.h:49
bool valid(RealT eps=math::Delta< RealT >::value()) const
Return true if t1 is larger than t0 by at least eps.
Definition: Ray.h:47
Ray applyMap(const MapType &map) const
Return a new Ray that is transformed with the specified map.
Definition: Ray.h:132
Vec3R end() const
Return the endpoint of the ray.
Definition: Ray.h:114
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:56
RealT t0() const
Definition: Ray.h:103
const Vec3T & invDir() const
Definition: Ray.h:101
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
Definition: Math.h:293
bool intersects(const Vec3T &center, RealT radius, RealT &t0, RealT &t1) const
Return true if this ray intersects the specified sphere.
Definition: Ray.h:183
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:154
T lengthSqr() const
Definition: Vec3.h:209
RealT t1() const
Definition: Ray.h:105
bool valid(RealT eps=math::Delta< float >::value()) const
Return true if t1 is larger than t0 by at least eps.
Definition: Ray.h:120
bool clip(const BBoxT &bbox)
Return true if this ray intersects the specified bounding box.
Definition: Ray.h:260
bool intersects(const Vec3T &center, RealT radius) const
Return true if this ray intersects the specified sphere.
Definition: Ray.h:207
void setDir(const Vec3Type &dir)
Definition: Ray.h:66
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:163
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:620
const Vec3T & dir() const
Definition: Ray.h:99
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:106