OpenVDB  1.2.0
Hermite.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2013 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 
31 #ifndef OPENVDB_MATH_HERMITE_HAS_BEEN_INCLUDED
32 #define OPENVDB_MATH_HERMITE_HAS_BEEN_INCLUDED
33 
34 #include <openvdb/Platform.h>
35 #include <openvdb/version.h>
36 #include "QuantizedUnitVec.h"
37 #include "Math.h"
38 
39 namespace openvdb {
41 namespace OPENVDB_VERSION_NAME {
42 namespace math {
43 
44 
45 // Forward declaration
46 class Hermite;
47 
48 
50 
51 // Utility methods
52 
53 
55 OPENVDB_API Hermite min(const Hermite&, const Hermite&);
57 OPENVDB_API Hermite max(const Hermite&, const Hermite&);
59 
60 
62 
63 
67 {
68 public:
69 
70  Hermite();
71  Hermite(const Hermite&);
72  const Hermite& operator=(const Hermite&);
73 
75  void clear();
76 
78  operator bool() const;
79 
81  inline bool operator==(const Hermite&) const;
83  bool operator!=(const Hermite& rhs) const { return !(*this == rhs); }
84 
86  Hermite operator-() const;
87 
89  template <typename T>
92  void setX(T offset, const Vec3<T>&);
93 
94  template <typename T>
95  void setY(T offset, const Vec3<T>&);
96 
97  template <typename T>
98  void setZ(T offset, const Vec3<T>&);
100 
102  // as being inside a contour.
103  bool isInside() const { return MASK_SIGN & mData; }
106  void setIsInside(bool);
107 
109  bool hasOffsetX() const { return mXNormal; };
112  bool hasOffsetY() const { return mYNormal; }
113  bool hasOffsetZ() const { return MASK_ZFLAG & mData; }
115 
117  bool isGreaterX(const Hermite& other) const;
120  bool isGreaterY(const Hermite& other) const;
121  bool isGreaterZ(const Hermite& other) const;
123 
125  bool isLessX(const Hermite& other) const;
128  bool isLessY(const Hermite& other) const;
129  bool isLessZ(const Hermite& other) const;
131 
133  float getOffsetX() const;
135  float getOffsetY() const;
136  float getOffsetZ() const;
138 
140  Vec3s getNormalX() const { return QuantizedUnitVec::unpack(mXNormal); }
142  Vec3s getNormalY() const { return QuantizedUnitVec::unpack(mYNormal); }
143  Vec3s getNormalZ() const { return QuantizedUnitVec::unpack(mZNormal); }
145 
147  void setX(const Hermite&);
150  void setY(const Hermite&);
151  void setZ(const Hermite&);
153 
155  std::string str() const;
156 
158  void read(std::istream&);
160  void write(std::ostream&) const;
161 
163  bool operator< (const Hermite&) const { return false; };
166  bool operator> (const Hermite&) const { return false; };
167  template<class T> Hermite operator+(const T&) const { return *this; };
168  template<class T> Hermite operator-(const T&) const { return *this; };
170 
171 private:
173  template <typename T>
174  static uint32_t quantizeOffset(T offset);
175 
178  static void getSignedOffsets(const Hermite& lhs, const Hermite& rhs,
179  const uint32_t bitmask, int& lhsV, int& rhsV);
180 
181 
182  // Bits masks
183  // 10000000000000000000000000000000
184  static const uint32_t MASK_SIGN = 0x80000000;
185  // 01000000000000000000000000000000
186  static const uint32_t MASK_ZFLAG = 0x40000000;
187  // 00111111111100000000000000000000
188  static const uint32_t MASK_XSLOT = 0x3FF00000;
189  // 00000000000011111111110000000000
190  static const uint32_t MASK_YSLOT = 0x000FFC00;
191  // 00000000000000000000001111111111
192  static const uint32_t MASK_ZSLOT = 0x000003FF;
193  // 00111111111111111111111111111111
194  static const uint32_t MASK_SLOTS = 0x3FFFFFFF;
195 
196 
197  uint16_t mXNormal, mYNormal, mZNormal;
198  uint32_t mData;
199 
200 }; // class Hermite
201 
202 
204 
205 // output-stream insertion operator
206 
207 inline std::ostream&
208 operator<<(std::ostream& ostr, const Hermite& rhs)
209 {
210  ostr << rhs.str();
211  return ostr;
212 }
213 
214 
216 
217 // construction and assignment
218 
219 inline const Hermite&
221 {
222  mData = rhs.mData;
223  mXNormal = rhs.mXNormal;
224  mYNormal = rhs.mYNormal;
225  mZNormal = rhs.mZNormal;
226  return *this;
227 }
228 
229 
230 inline void
232 {
233  mXNormal = 0;
234  mYNormal = 0;
235  mZNormal = 0;
236  mData = 0;
237 }
238 
239 
241 
242 // bool operator and equality
243 
244 inline
245 Hermite::operator bool() const
246 {
247  if (0 != (mXNormal | mYNormal)) return true;
248  return hasOffsetZ();
249 }
250 
251 
252 inline bool
253 Hermite::operator==(const Hermite& rhs) const
254 {
255  if(mXNormal != rhs.mXNormal) return false;
256  if(mYNormal != rhs.mYNormal) return false;
257  if(mZNormal != rhs.mZNormal) return false;
258  return mData == rhs.mData;
259 }
260 
261 
263 
264 // unary negation operator
265 
266 inline Hermite
268 {
269  Hermite ret(*this);
270  QuantizedUnitVec::flipSignBits(ret.mXNormal);
271  QuantizedUnitVec::flipSignBits(ret.mYNormal);
272  QuantizedUnitVec::flipSignBits(ret.mZNormal);
273  ret.mData = (~MASK_SIGN & ret.mData) | (MASK_SIGN & ~ret.mData);
274  return ret;
275 }
276 
277 
279 
280 // Helper funcions
281 
282 template <typename T>
283 inline uint32_t
284 Hermite::quantizeOffset(T offset)
285 {
286  // the offset is expected to be normalized [0 to 1)
287  assert(offset < 1.0);
288  assert(offset > -1.0e-8);
289 
290  // quantize the offset using 10-bits. (higher bits are masked out)
291  return uint32_t(1023 * offset) & MASK_ZSLOT;
292 }
293 
294 inline void
295 Hermite::getSignedOffsets(const Hermite& lhs, const Hermite& rhs,
296  const uint32_t bitmask, int& lhsV, int& rhsV)
297 {
298  lhsV = bitmask & lhs.mData;
299  rhsV = bitmask & rhs.mData;
300 
301  if(lhs.isInside()) lhsV = -lhsV;
302  if(rhs.isInside()) rhsV = -rhsV;
303 }
304 
305 
307 
308 // compress and set edge data
309 
310 template <typename T>
311 inline void
312 Hermite::setX(T offset, const Vec3<T>& n)
313 {
314  mData &= ~MASK_XSLOT; // clear xslot
315  mData |= quantizeOffset(offset) << 20;
316  mXNormal = QuantizedUnitVec::pack(n);
317 }
318 
319 template <typename T>
320 inline void
321 Hermite::setY(T offset, const Vec3<T>& n)
322 {
323  mData &= ~MASK_YSLOT; // clear yslot
324  mData |= quantizeOffset(offset) << 10;
325  mYNormal = QuantizedUnitVec::pack(n);
326 }
327 
328 template <typename T>
329 inline void
330 Hermite::setZ(T offset, const Vec3<T>& n)
331 {
332  mData &= ~MASK_ZSLOT; // clear zslot
333  mData |= MASK_ZFLAG | quantizeOffset(offset);
334  mZNormal = QuantizedUnitVec::pack(n);
335 }
336 
337 
339 
340 // change inside/outside state
341 
342 inline void
343 Hermite::setIsInside(bool isInside)
344 {
345  mData &= ~MASK_SIGN; // clear sign-bit
346  mData |= uint32_t(isInside) * MASK_SIGN;
347 }
348 
349 
351 
352 // Uncompress and return the edge intersection-offsets
353 // 0.000977517 = 1.0 / 1023
354 
355 inline float
357 {
358  return float((mData >> 20) & MASK_ZSLOT) * 0.000977517;
359 }
360 
361 inline float
363 {
364  return float((mData >> 10) & MASK_ZSLOT) * 0.000977517;
365 }
366 
367 inline float
369 {
370  return float(mData & MASK_ZSLOT) * 0.000977517;
371 }
372 
373 
375 
376 // copy compressed edge data from other object
377 
378 inline void
380 {
381  mData &= ~MASK_XSLOT; // clear xslot
382  mData |= MASK_XSLOT & rhs.mData; // copy xbits from rhs
383  mXNormal = rhs.mXNormal; // copy compressed normal
384 
385  // Flip the copied normal if the rhs object has
386  // a different inside/outside state.
387  if(hasOffsetX() && isInside() != rhs.isInside())
388  QuantizedUnitVec::flipSignBits(mXNormal);
389 }
390 
391 inline void
393 {
394  mData &= ~MASK_YSLOT;
395  mData |= MASK_YSLOT & rhs.mData;
396  mYNormal = rhs.mYNormal;
397 
398  if(hasOffsetY() && isInside() != rhs.isInside())
399  QuantizedUnitVec::flipSignBits(mYNormal);
400 }
401 
402 inline void
404 {
405  mData &= ~MASK_ZSLOT;
406  mData |= (MASK_ZFLAG | MASK_ZSLOT) & rhs.mData;
407  mZNormal = rhs.mZNormal;
408  if(hasOffsetZ() && isInside() != rhs.isInside())
409  QuantizedUnitVec::flipSignBits(mZNormal);
410 }
411 
412 
414 
415 // edge comparison operators
416 
417 inline bool
418 Hermite::isGreaterX(const Hermite& rhs) const
419 {
420  int lhsV, rhsV;
421  getSignedOffsets(*this, rhs, MASK_XSLOT, lhsV, rhsV);
422  return lhsV > rhsV;
423 }
424 
425 inline bool
426 Hermite::isGreaterY(const Hermite& rhs) const
427 {
428  int lhsV, rhsV;
429  getSignedOffsets(*this, rhs, MASK_YSLOT, lhsV, rhsV);
430  return lhsV > rhsV;
431 }
432 
433 inline bool
434 Hermite::isGreaterZ(const Hermite& rhs) const
435 {
436  int lhsV, rhsV;
437  getSignedOffsets(*this, rhs, MASK_ZSLOT, lhsV, rhsV);
438  return lhsV > rhsV;
439 }
440 
441 inline bool
442 Hermite::isLessX(const Hermite& rhs) const
443 {
444  int lhsV, rhsV;
445  getSignedOffsets(*this, rhs, MASK_XSLOT, lhsV, rhsV);
446  return lhsV < rhsV;
447 }
448 
449 inline bool
450 Hermite::isLessY(const Hermite& rhs) const
451 {
452  int lhsV, rhsV;
453  getSignedOffsets(*this, rhs, MASK_YSLOT, lhsV, rhsV);
454  return lhsV < rhsV;
455 }
456 
457 inline bool
458 Hermite::isLessZ(const Hermite& rhs) const
459 {
460  int lhsV, rhsV;
461  getSignedOffsets(*this, rhs, MASK_ZSLOT, lhsV, rhsV);
462  return lhsV < rhsV;
463 }
464 
465 
467 
468 
469 inline bool
470 isApproxEqual(const Hermite& lhs, const Hermite& rhs) { return lhs == rhs; }
471 
472 inline bool
473 isApproxEqual(const Hermite& lhs, const Hermite& rhs, const Hermite& /*tolerance*/)
474  { return isApproxEqual(lhs, rhs); }
475 
476 
477 } // namespace math
478 
479 
481 
482 
483 template<> inline math::Hermite zeroVal<math::Hermite>() { return math::Hermite(); }
484 
485 
486 } // namespace OPENVDB_VERSION_NAME
487 } // namespace openvdb
488 
489 #endif // OPENVDB_MATH_HERMITE_HAS_BEEN_INCLUDED
490 
491 // Copyright (c) 2012-2013 DreamWorks Animation LLC
492 // All rights reserved. This software is distributed under the
493 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )