OpenVDB  0.104.0
Ray.h
Go to the documentation of this file.
1 
2 //
3 // Copyright (c) 2012 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 //
30 //
33 
34 #ifndef OPENVDB_MATH_RAY_HAS_BEEN_INCLUDED
35 #define OPENVDB_MATH_RAY_HAS_BEEN_INCLUDED
36 
37 #include <set>
38 #include <cassert>
39 #include <cstring>
40 #include <iostream> // for cout
41 #include <fstream> // for ofstream
42 #include <cmath> // for round
43 #include "Math.h" // for isExactlyEqual()
44 #include "Vec3.h"
45 #include <openvdb/math/Transform.h>
46 
47 
48 namespace openvdb {
50 namespace OPENVDB_VERSION_NAME {
51 namespace math {
52 
53 template<typename _Real>
54 class Ray
55 {
56 public:
57  typedef _Real Real;
58  typedef Vec3<Real> Vec3R;
59 
60  //un-initialized, i.e. not valid
61 OPENVDB_DEPRECATED Ray(): mTime(-1),mMinTime(0), mMaxTime(std::numeric_limits<Real>::max())
62  {
63  }
64 
65 OPENVDB_DEPRECATED Ray(const Vec3R &origin, const Vec3R &direction,
66  Real time = std::numeric_limits<Real>::epsilon(),
67  Real start=0, Real end = std::numeric_limits<Real>::max())
68  : mOrigin(origin), mDirection(direction),
69  mInvDirection(1/direction[0],1/direction[1],1/direction[2]),
70  mTime(time), mMinTime(start), mMaxTime(end)
71  {
72  }
73 
74  Vec3R getOrigin() const {return mOrigin;}
75  Real getOrigin(int i) const {return mOrigin[i];}
76 
77  Vec3R getDirection() const {return mDirection;}
78  Real getDirection(int i) const {return mDirection[i];}
79 
80  Vec3R getInvDirection() const {return mInvDirection;}
81  Real getInvDirection(int i) const {return mInvDirection[i];}
82 
83  Real getTime() const {return mTime;}
84  Real getMinTime() const {return mMinTime;}
85  Real getMaxTime() const {return mMaxTime;}
86 
87  void setOrigin(const Vec3R &orig) {mOrigin=orig;}
88  void setOrigin(Real x, Real y, Real z)
89  {
90  mOrigin[0]=x;
91  mOrigin[1]=y;
92  mOrigin[2]=z;
93  }
94 
95  void setDirection(const Vec3R &dir)
96  {
97  mDirection=dir;
98  this->setInvDirection();
99  }
100 
101  void setDirection(Real x, Real y, Real z)
102  {
103  mDirection[0]=x;
104  mDirection[1]=y;
105  mDirection[2]=z;
106  this->setInvDirection();
107  }
108 
109  void setTime(Real time) {mTime=time;}
110 
111  void setMinTime(Real time)
112  {
113  mMinTime=time;
114  }
115 
116  void setMaxTime(Real time)
117  {
118  mMaxTime=time;
119  }
120  void setMinMaxTimes(Real t0, Real t1)
121  {
122  mMinTime=t0;
123  mMaxTime=t1;
124  }
125 
126  // For set and get
127  Real& timer() {return mTime;}
128  Vec3R position(Real time) const { return mOrigin + mDirection * time; }
129  Vec3R start() const { return mOrigin + mDirection * mMinTime; }
130  Vec3R end() const { return mOrigin + mDirection * mMaxTime; }
131  bool isValid() const { return (mTime>mMinTime && mTime<mMaxTime); }
132 
135  void worldToIndex(const Transform::Ptr& xform)
136  {
137 
138  mOrigin = xform->worldToIndex(mOrigin);
139 
140  mDirection = xform->worldToIndex(mDirection);
141  mDirection -= xform->indexToWorld(Vec3R(0,0,0));//ignore translation!
142  this->setInvDirection();
143  }
144 
147  void indexToWorld( const Transform::Ptr& xform )
148  {
149  mOrigin = xform->indexToWorld( mOrigin );
150 
151  mDirection += xform->indexToWorld( Vec3R( 0,0,0 ) );
152  mDirection = xform->indexToWorld( mDirection );
153  this->setInvDirection();
154  }
155 
156 private:
157  void setInvDirection()
158  {
159  mInvDirection[0] = 1/mDirection[0];//1/0=inf, should be safe!
160  mInvDirection[1] = 1/mDirection[1];
161  mInvDirection[2] = 1/mDirection[2];
162  }
163 
164  Vec3R mOrigin;
165  Vec3R mDirection;
166  Vec3R mInvDirection;//for acceleration
167  Real mTime;
168  Real mMinTime, mMaxTime;
169 }; // end of Ray class
170 
171 
172 template<typename Real>
173 inline std::ostream &operator<<(std::ostream &os, const Ray<Real> &r) {
174  os << "org=" << r.getOrigin() << " dir=" << r.getDirection() << " tmin=" <<
175  r.getMinTime() << " tmax=" << r.getMaxTime() << " t=" << r.getTime();
176  return os;
177 }
178 
179 
180 template<typename Real, typename ValueType>
182 {
183 public:
185  class Hit {};
186 
187  enum Tag {EMPTY=0, CONSTANT, VARIABLE};
188 
189  Real t0, t1;
191  ValueType value;//only used with CONSTANT tag!!!
192 
193  // Constructs an EMPTY interval is maximum extent!
195  : t0(std::numeric_limits<Real>::epsilon()),
196  t1(std::numeric_limits<Real>::max()), tag(EMPTY)
197  {
198  }
199  // Constructs an EMPTY interval with t0 and t1
201  : t0(_t0), t1(_t1), tag(EMPTY)
202  {
203  assert(t0<=t1);
204  }
205  // Constructs an VARIABLE interval with t0 and t1
207  : t0(_t0), t1(_t1), tag(VARIABLE)
208  {
209  assert(t0<=t1);
210  }
211  // Constructs a CONSTANT interval with t0 and t1
212 OPENVDB_DEPRECATED RayInterval(Real _t0, Real _t1, const ValueType &_value)
213  : t0(_t0), t1(_t1), tag(CONSTANT), value(_value)
214  {
215  assert(t0<=t1);
216  }
217  bool isEmpty() const {return tag==EMPTY;}
218  bool isConstant() const {return tag==CONSTANT;}
219  bool isVariable() const {return tag==VARIABLE;}
220  // redefines t0 and t1
221  void set(Real _t0, Real _t1)
222  {
223  t0 = _t0;
224  t1 = _t1;
225  assert(t0<=t1);
226  }
227  // Only for EMPTY or VARIABLE intervals!
228  void set(Real _t0, Real _t1, bool empty=false)
229  {
230  t0 = _t0;
231  t1 = _t1;
232  tag = empty ? EMPTY : VARIABLE;
233  assert(t0<=t1);
234  }
235  // Only for CONSTANT intervals
236  void set(Real _t0, Real _t1, const ValueType &_value)
237  {
238  t0 = _t0;
239  t1 = _t1;
240  tag = CONSTANT;
241  value= _value;
242  assert(t0<=t1);
243  }
245  bool operator < (const RayInterval &other) const
246  {
247  return t0<other.t0;
248  }
249  bool operator==(const RayInterval &other) const
250  {
251  if (tag != other.tag || !isExactlyEqual(t0, other.t0)
252  || !isExactlyEqual(t1, other.t1)) return false;
253  if (tag==CONSTANT) return !isExactlyEqual(value, other.value);
254  return true;
255  }
257  bool merge(const RayInterval &other, Real tolerance=1e-4)
258  {
259  if (this->tag != other.tag
260  || (this->tag == CONSTANT && !isExactlyEqual(this->value, other.value)) )
261  {
262  return false;
263  } else if (std::abs(this->t0-other.t1)<tolerance) {//other is before
264  this->t0=other.t0;
265  return true;
266  } else if (std::abs(this->t1-other.t0)<tolerance) {//other is after
267  this->t1=other.t1;
268  return true;
269  }
270  return false;
271  }
272 
273  void print() const
274  {
275  std::cerr << "t0=" << t0 << "\tt1=" << t1 << "\ttag="
276  << (tag==0 ? "EMPTY" : tag==1 ? "CONSTANT" : "VARIABLE");
277  if (tag==1) std::cerr << "\tvalue=" << value;
278  std::cerr << std::endl;
279  }
280 }; // end of RayInterval class
281 
282 
283 template<typename Real, typename ValueType>
284 class RayIntervalSet: public std::set<RayInterval<Real,ValueType> >
285 {
286 public:
288 
290  {
291  }
299  bool merge(const Ray<Real> &R, Real tolerance=1e-4)
300  {
301  if (this->size()==0) return false;//empty - nothing to do!
302  RayIntervalSet merged;
303  typename std::set<IntervalType>::const_iterator iter=this->begin(), iend=this->end();
304  if (R.getMinTime() < iter->t0) // need to patch beginning?
305  merged.insert(IntervalType(R.getMinTime(),iter->t0));//insert EMPTY
306  IntervalType I = *iter;
307  for ( ++iter; iter != iend; ++iter ) {
308  if (I.merge(*iter,tolerance)) continue;
309  merged.insert(I);
310  if (std::abs(I.t1-iter->t0)>tolerance)//is there a gab?
311  merged.insert(IntervalType(I.t1,iter->t0));//insert EMPTY
312  I=*iter;
313  }
314  merged.insert(I);
315  if (R.getMaxTime()>I.t1) //need to patch end?
316  merged.insert(IntervalType(I.t1,R.getMaxTime()));//insert EMPTY
317  *this = merged;
318  return true;
319  }
320  bool isEmpty() const {return this->size()==0;}
321 
322  // Convenient for debugging!
323  void print(const std::string &str=std::string("")) const
324  {
325  if (str!=std::string(""))
326  std::cerr << "RayIntervalSet for \"" << str << "\"" << std::endl;
327  if (this->isEmpty()) {
328  std::cerr << "Empty RayIntervalSet!" << std::endl;
329  return;
330  }
331  typename std::set<IntervalType>::const_iterator iter=this->begin();
332  for (; iter!=this->end(); ++iter) iter->print();
333  }
334 }; // end of RayIntervalSet class
335 
336 } // namespace math
337 } // namespace OPENVDB_VERSION_NAME
338 } // namespace openvdb
339 
340 #endif // OPENVDB_MATH_RAY_HAS_BEEN_INCLUDED
341 
342 // Copyright (c) 2012 DreamWorks Animation LLC
343 // All rights reserved. This software is distributed under the
344 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )