HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Ray.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2012-2018 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
29 ///////////////////////////////////////////////////////////////////////////
30 //
31 /// @file Ray.h
32 ///
33 /// @author Ken Museth
34 ///
35 /// @brief A Ray class.
36 
37 #ifndef OPENVDB_MATH_RAY_HAS_BEEN_INCLUDED
38 #define OPENVDB_MATH_RAY_HAS_BEEN_INCLUDED
39 
40 #include "Math.h"
41 #include "Vec3.h"
42 #include "Transform.h"
43 #include <algorithm> // for std::swap()
44 #include <iostream> // for std::ostream
45 #include <limits> // for std::numeric_limits<Type>::max()
46 
47 namespace openvdb {
49 namespace OPENVDB_VERSION_NAME {
50 namespace math {
51 
52 template<typename RealT = double>
53 class Ray
54 {
55 public:
57  "math::Ray requires a floating-point value type");
58 
59  using RealType = RealT;
61  using Vec3T = Vec3Type;
62 
63  struct TimeSpan {
64  RealT t0, t1;
65  /// @brief Default constructor
66  TimeSpan() {}
67  /// @brief Constructor
68  TimeSpan(RealT _t0, RealT _t1) : t0(_t0), t1(_t1) {}
69  /// @brief Set both times
70  inline void set(RealT _t0, RealT _t1) { t0=_t0; t1=_t1; }
71  /// @brief Get both times
72  inline void get(RealT& _t0, RealT& _t1) const { _t0=t0; _t1=t1; }
73  /// @brief Return @c true if t1 is larger than t0 by at least eps.
74  inline bool valid(RealT eps=math::Delta<RealT>::value()) const { return (t1-t0)>eps; }
75  /// @brief Return the midpoint of the ray.
76  inline RealT mid() const { return 0.5*(t0 + t1); }
77  /// @brief Multiplies both times
78  inline void scale(RealT s) {assert(s>0); t0*=s; t1*=s; }
79  /// @brief Return @c true if time is inclusive
80  inline bool test(RealT t) const { return (t>=t0 && t<=t1); }
81  };
82 
83  Ray(const Vec3Type& eye = Vec3Type(0,0,0),
84  const Vec3Type& direction = Vec3Type(1,0,0),
85  RealT t0 = math::Delta<RealT>::value(),
87  : mEye(eye), mDir(direction), mInvDir(1/mDir), mTimeSpan(t0, t1)
88  {
89  }
90 
91  inline void setEye(const Vec3Type& eye) { mEye = eye; }
92 
93  inline void setDir(const Vec3Type& dir)
94  {
95  mDir = dir;
96  mInvDir = 1/mDir;
97  }
98 
99  inline void setMinTime(RealT t0) { assert(t0>0); mTimeSpan.t0 = t0; }
100 
101  inline void setMaxTime(RealT t1) { assert(t1>0); mTimeSpan.t1 = t1; }
102 
103  inline void setTimes(
104  RealT t0 = math::Delta<RealT>::value(),
106  {
107  assert(t0>0 && t1>0);
108  mTimeSpan.set(t0, t1);
109  }
110 
111  inline void scaleTimes(RealT scale) { mTimeSpan.scale(scale); }
112 
113  inline void reset(
114  const Vec3Type& eye,
115  const Vec3Type& direction,
116  RealT t0 = math::Delta<RealT>::value(),
118  {
119  this->setEye(eye);
120  this->setDir(direction);
121  this->setTimes(t0, t1);
122  }
123 
124  inline const Vec3T& eye() const {return mEye;}
125 
126  inline const Vec3T& dir() const {return mDir;}
127 
128  inline const Vec3T& invDir() const {return mInvDir;}
129 
130  inline RealT t0() const {return mTimeSpan.t0;}
131 
132  inline RealT t1() const {return mTimeSpan.t1;}
133 
134  /// @brief Return the position along the ray at the specified time.
135  inline Vec3R operator()(RealT time) const { return mEye + mDir * time; }
136 
137  /// @brief Return the starting point of the ray.
138  inline Vec3R start() const { return (*this)(mTimeSpan.t0); }
139 
140  /// @brief Return the endpoint of the ray.
141  inline Vec3R end() const { return (*this)(mTimeSpan.t1); }
142 
143  /// @brief Return the midpoint of the ray.
144  inline Vec3R mid() const { return (*this)(mTimeSpan.mid()); }
145 
146  /// @brief Return @c true if t1 is larger than t0 by at least eps.
147  inline bool valid(RealT eps=math::Delta<float>::value()) const { return mTimeSpan.valid(eps); }
148 
149  /// @brief Return @c true if @a time is within t0 and t1, both inclusive.
150  inline bool test(RealT time) const { return mTimeSpan.test(time); }
151 
152  /// @brief Return a new Ray that is transformed with the specified map.
153  /// @param map the map from which to construct the new Ray.
154  /// @warning Assumes a linear map and a normalized direction.
155  /// @details The requirement that the direction is normalized
156  /// follows from the transformation of t0 and t1 - and that fact that
157  /// we want applyMap and applyInverseMap to be inverse operations.
158  template<typename MapType>
159  inline Ray applyMap(const MapType& map) const
160  {
161  assert(map.isLinear());
162  assert(math::isRelOrApproxEqual(mDir.length(), RealT(1),
164  const Vec3T eye = map.applyMap(mEye);
165  const Vec3T dir = map.applyJacobian(mDir);
166  const RealT length = dir.length();
167  return Ray(eye, dir/length, length*mTimeSpan.t0, length*mTimeSpan.t1);
168  }
169 
170  /// @brief Return a new Ray that is transformed with the inverse of the specified map.
171  /// @param map the map from which to construct the new Ray by inverse mapping.
172  /// @warning Assumes a linear map and a normalized direction.
173  /// @details The requirement that the direction is normalized
174  /// follows from the transformation of t0 and t1 - and that fact that
175  /// we want applyMap and applyInverseMap to be inverse operations.
176  template<typename MapType>
177  inline Ray applyInverseMap(const MapType& map) const
178  {
179  assert(map.isLinear());
181  const Vec3T eye = map.applyInverseMap(mEye);
182  const Vec3T dir = map.applyInverseJacobian(mDir);
183  const RealT length = dir.length();
184  return Ray(eye, dir/length, length*mTimeSpan.t0, length*mTimeSpan.t1);
185  }
186 
187  /// @brief Return a new ray in world space, assuming the existing
188  /// ray is represented in the index space of the specified grid.
189  template<typename GridType>
190  inline Ray indexToWorld(const GridType& grid) const
191  {
192  return this->applyMap(*(grid.transform().baseMap()));
193  }
194 
195  /// @brief Return a new ray in the index space of the specified
196  /// grid, assuming the existing ray is represented in world space.
197  template<typename GridType>
198  inline Ray worldToIndex(const GridType& grid) const
199  {
200  return this->applyInverseMap(*(grid.transform().baseMap()));
201  }
202 
203  /// @brief Return true if this ray intersects the specified sphere.
204  /// @param center The center of the sphere in the same space as this ray.
205  /// @param radius The radius of the sphere in the same units as this ray.
206  /// @param t0 The first intersection point if an intersection exists.
207  /// @param t1 The second intersection point if an intersection exists.
208  /// @note If the return value is true, i.e. a hit, and t0 =
209  /// this->t0() or t1 == this->t1() only one true intersection exist.
210  inline bool intersects(const Vec3T& center, RealT radius, RealT& t0, RealT& t1) const
211  {
212  const Vec3T origin = mEye - center;
213  const RealT A = mDir.lengthSqr();
214  const RealT B = 2 * mDir.dot(origin);
215  const RealT C = origin.lengthSqr() - radius * radius;
216  const RealT D = B * B - 4 * A * C;
217 
218  if (D < 0) return false;
219 
220  const RealT Q = RealT(-0.5)*(B<0 ? (B + Sqrt(D)) : (B - Sqrt(D)));
221 
222  t0 = Q / A;
223  t1 = C / Q;
224 
225  if (t0 > t1) std::swap(t0, t1);
226  if (t0 < mTimeSpan.t0) t0 = mTimeSpan.t0;
227  if (t1 > mTimeSpan.t1) t1 = mTimeSpan.t1;
228  return t0 <= t1;
229  }
230 
231  /// @brief Return true if this ray intersects the specified sphere.
232  /// @param center The center of the sphere in the same space as this ray.
233  /// @param radius The radius of the sphere in the same units as this ray.
234  inline bool intersects(const Vec3T& center, RealT radius) const
235  {
236  RealT t0, t1;
237  return this->intersects(center, radius, t0, t1)>0;
238  }
239 
240  /// @brief Return true if this ray intersects the specified sphere.
241  /// @note For intersection this ray is clipped to the two intersection points.
242  /// @param center The center of the sphere in the same space as this ray.
243  /// @param radius The radius of the sphere in the same units as this ray.
244  inline bool clip(const Vec3T& center, RealT radius)
245  {
246  RealT t0, t1;
247  const bool hit = this->intersects(center, radius, t0, t1);
248  if (hit) mTimeSpan.set(t0, t1);
249  return hit;
250  }
251 
252  /// @brief Return true if the Ray intersects the specified
253  /// axisaligned bounding box.
254  /// @param bbox Axis-aligned bounding box in the same space as the Ray.
255  /// @param t0 If an intersection is detected this is assigned
256  /// the time for the first intersection point.
257  /// @param t1 If an intersection is detected this is assigned
258  /// the time for the second intersection point.
259  template<typename BBoxT>
260  inline bool intersects(const BBoxT& bbox, RealT& t0, RealT& t1) const
261  {
262  mTimeSpan.get(t0, t1);
263  for (int i = 0; i < 3; ++i) {
264  RealT a = (bbox.min()[i] - mEye[i]) * mInvDir[i];
265  RealT b = (bbox.max()[i] - mEye[i]) * mInvDir[i];
266  if (a > b) std::swap(a, b);
267  if (a > t0) t0 = a;
268  if (b < t1) t1 = b;
269  if (t0 > t1) return false;
270  }
271  return true;
272  }
273 
274  /// @brief Return true if this ray intersects the specified bounding box.
275  /// @param bbox Axis-aligned bounding box in the same space as this ray.
276  template<typename BBoxT>
277  inline bool intersects(const BBoxT& bbox) const
278  {
279  RealT t0, t1;
280  return this->intersects(bbox, t0, t1);
281  }
282 
283  /// @brief Return true if this ray intersects the specified bounding box.
284  /// @note For intersection this ray is clipped to the two intersection points.
285  /// @param bbox Axis-aligned bounding box in the same space as this ray.
286  template<typename BBoxT>
287  inline bool clip(const BBoxT& bbox)
288  {
289  RealT t0, t1;
290  const bool hit = this->intersects(bbox, t0, t1);
291  if (hit) mTimeSpan.set(t0, t1);
292  return hit;
293  }
294 
295  /// @brief Return true if the Ray intersects the plane specified
296  /// by a normal and distance from the origin.
297  /// @param normal Normal of the plane.
298  /// @param distance Distance of the plane to the origin.
299  /// @param t Time of intersection, if one exists.
300  inline bool intersects(const Vec3T& normal, RealT distance, RealT& t) const
301  {
302  const RealT cosAngle = mDir.dot(normal);
303  if (math::isApproxZero(cosAngle)) return false;//parallel
304  t = (distance - mEye.dot(normal))/cosAngle;
305  return this->test(t);
306  }
307 
308  /// @brief Return true if the Ray intersects the plane specified
309  /// by a normal and point.
310  /// @param normal Normal of the plane.
311  /// @param point Point in the plane.
312  /// @param t Time of intersection, if one exists.
313  inline bool intersects(const Vec3T& normal, const Vec3T& point, RealT& t) const
314  {
315  return this->intersects(normal, point.dot(normal), t);
316  }
317 
318 private:
319  Vec3T mEye, mDir, mInvDir;
320  TimeSpan mTimeSpan;
321 }; // end of Ray class
322 
323 
324 /// @brief Output streaming of the Ray class.
325 /// @note Primarily intended for debugging.
326 template<typename RealT>
327 inline std::ostream& operator<<(std::ostream& os, const Ray<RealT>& r)
328 {
329  os << "eye=" << r.eye() << " dir=" << r.dir() << " 1/dir="<<r.invDir()
330  << " t0=" << r.t0() << " t1=" << r.t1();
331  return os;
332 }
333 
334 } // namespace math
335 } // namespace OPENVDB_VERSION_NAME
336 } // namespace openvdb
337 
338 #endif // OPENVDB_MATH_RAY_HAS_BEEN_INCLUDED
339 
340 // Copyright (c) 2012-2018 DreamWorks Animation LLC
341 // All rights reserved. This software is distributed under the
342 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
RealT mid() const
Return the midpoint of the ray.
Definition: Ray.h:76
void setTimes(RealT t0=math::Delta< RealT >::value(), RealT t1=std::numeric_limits< RealT >::max())
Definition: Ray.h:103
bool clip(const Vec3T &center, RealT radius)
Return true if this ray intersects the specified sphere.
Definition: Ray.h:244
void swap(UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &a, UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &b)
Definition: UT_ArraySet.h:1519
GT_API const UT_StringHolder time
void setEye(const Vec3Type &eye)
Definition: Ray.h:91
Vec3R end() const
Return the endpoint of the ray.
Definition: Ray.h:141
IMF_EXPORT IMATH_NAMESPACE::V3f direction(const IMATH_NAMESPACE::Box2i &dataWindow, const IMATH_NAMESPACE::V2f &pixelPosition)
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:198
const Vec3T & eye() const
Definition: Ray.h:124
bool intersects(const Vec3T &center, RealT radius) const
Return true if this ray intersects the specified sphere.
Definition: Ray.h:234
void setDir(const Vec3Type &dir)
Definition: Ray.h:93
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:189
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:216
png_uint_32 i
Definition: png.h:2877
bool test(RealT time) const
Return true if time is within t0 and t1, both inclusive.
Definition: Ray.h:150
void set(RealT _t0, RealT _t1)
Set both times.
Definition: Ray.h:70
void get(RealT &_t0, RealT &_t1) const
Get both times.
Definition: Ray.h:72
Ray applyMap(const MapType &map) const
Return a new Ray that is transformed with the specified map.
Definition: Ray.h:159
const Vec3T & invDir() const
Definition: Ray.h:128
Vec3R operator()(RealT time) const
Return the position along the ray at the specified time.
Definition: Ray.h:135
Ray applyInverseMap(const MapType &map) const
Return a new Ray that is transformed with the inverse of the specified map.
Definition: Ray.h:177
T distance(const UT_Vector4T< T > &v1, const UT_Vector4T< T > &v2)
Definition: UT_Vector4.h:698
Vec3R start() const
Return the starting point of the ray.
Definition: Ray.h:138
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:133
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Delta for small floating-point offsets.
Definition: Math.h:124
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:715
bool intersects(const BBoxT &bbox, RealT &t0, RealT &t1) const
Return true if the Ray intersects the specified axisaligned bounding box.
Definition: Ray.h:260
bool isRelOrApproxEqual(const Type &a, const Type &b, const Type &absTol, const Type &relTol)
Definition: Math.h:405
void scale(RealT s)
Multiplies both times.
Definition: Ray.h:78
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
Definition: Math.h:320
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
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:83
bool clip(const BBoxT &bbox)
Return true if this ray intersects the specified bounding box.
Definition: Ray.h:287
bool valid(RealT eps=math::Delta< float >::value()) const
Return true if t1 is larger than t0 by at least eps.
Definition: Ray.h:147
GLsizei const GLfloat * value
Definition: glcorearb.h:823
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:647
bool intersects(const Vec3T &center, RealT radius, RealT &t0, RealT &t1) const
Return true if this ray intersects the specified sphere.
Definition: Ray.h:210
const Vec3T & dir() const
Definition: Ray.h:126
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:313
Vec3R mid() const
Return the midpoint of the ray.
Definition: Ray.h:144
TimeSpan(RealT _t0, RealT _t1)
Constructor.
Definition: Ray.h:68
bool valid(RealT eps=math::Delta< RealT >::value()) const
Return true if t1 is larger than t0 by at least eps.
Definition: Ray.h:74
GLboolean r
Definition: glcorearb.h:1221
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:190
void reset(const Vec3Type &eye, const Vec3Type &direction, RealT t0=math::Delta< RealT >::value(), RealT t1=std::numeric_limits< RealT >::max())
Definition: Ray.h:113
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:135
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:300
bool test(RealT t) const
Return true if time is inclusive.
Definition: Ray.h:80
bool intersects(const BBoxT &bbox) const
Return true if this ray intersects the specified bounding box.
Definition: Ray.h:277
T length() const
Length of the vector.
Definition: Vec3.h:225
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:794