| Line | Branch | Exec | Source | 
|---|---|---|---|
| 1 | // Copyright Contributors to the OpenVDB Project | ||
| 2 | // SPDX-License-Identifier: MPL-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 <algorithm> // for std::swap() | ||
| 17 | #include <iostream> // for std::ostream | ||
| 18 | #include <limits> // for std::numeric_limits<Type>::max() | ||
| 19 | |||
| 20 | namespace openvdb { | ||
| 21 | OPENVDB_USE_VERSION_NAMESPACE | ||
| 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; | ||
| 33 | using Vec3Type = Vec3<RealT>; | ||
| 34 | using Vec3T = Vec3Type; | ||
| 35 | |||
| 36 | struct TimeSpan { | ||
| 37 | RealT t0, t1; | ||
| 38 | /// @brief Default constructor | ||
| 39 | TimeSpan() {} | ||
| 40 | /// @brief Constructor | ||
| 41 | 20/30✗ Branch 1 not taken. ✓ Branch 2 taken 1 times. ✓ Branch 3 taken 1 times. ✗ Branch 4 not taken. ✓ Branch 5 taken 1 times. ✓ Branch 6 taken 1 times. ✗ Branch 7 not taken. ✓ Branch 8 taken 2 times. ✓ Branch 9 taken 1 times. ✓ Branch 10 taken 1 times. ✓ Branch 11 taken 1 times. ✓ Branch 12 taken 1 times. ✗ Branch 13 not taken. ✓ Branch 14 taken 1 times. ✓ Branch 15 taken 1 times. ✗ Branch 16 not taken. ✓ Branch 17 taken 1 times. ✓ Branch 18 taken 1 times. ✗ Branch 19 not taken. ✓ Branch 20 taken 1 times. ✓ Branch 21 taken 1 times. ✗ Branch 22 not taken. ✓ Branch 23 taken 1 times. ✓ Branch 24 taken 1 times. ✗ Branch 25 not taken. ✓ Branch 26 taken 1 times. ✓ Branch 27 taken 1048576 times. ✗ Branch 28 not taken. ✓ Branch 29 taken 1 times. ✗ Branch 30 not taken. | 1048761 | TimeSpan(RealT _t0, RealT _t1) : t0(_t0), t1(_t1) {} | 
| 42 | /// @brief Set both times | ||
| 43 | 1319509 | inline void set(RealT _t0, RealT _t1) { t0=_t0; t1=_t1; } | |
| 44 | /// @brief Get both times | ||
| 45 | 1048625 | inline void get(RealT& _t0, RealT& _t1) const { _t0=t0; _t1=t1; } | |
| 46 | /// @brief Return @c true if t1 is larger than t0 by at least eps. | ||
| 47 | 29/68✗ Branch 0 not taken. ✓ Branch 1 taken 13 times. ✓ Branch 2 taken 2 times. ✗ Branch 3 not taken. ✓ Branch 4 taken 2 times. ✗ Branch 5 not taken. ✗ Branch 6 not taken. ✗ Branch 7 not taken. ✗ Branch 8 not taken. ✗ Branch 9 not taken. ✗ Branch 10 not taken. ✗ Branch 11 not taken. ✗ Branch 12 not taken. ✗ Branch 13 not taken. ✗ Branch 14 not taken. ✗ Branch 15 not taken. ✗ Branch 16 not taken. ✗ Branch 17 not taken. ✓ Branch 18 taken 14 times. ✓ Branch 19 taken 8 times. ✗ Branch 20 not taken. ✓ Branch 21 taken 1 times. ✗ Branch 22 not taken. ✓ Branch 23 taken 1 times. ✗ Branch 24 not taken. ✓ Branch 25 taken 1 times. ✗ Branch 26 not taken. ✓ Branch 27 taken 1 times. ✗ Branch 28 not taken. ✓ Branch 29 taken 1 times. ✗ Branch 30 not taken. ✓ Branch 31 taken 1 times. ✗ Branch 32 not taken. ✓ Branch 33 taken 1 times. ✗ Branch 34 not taken. ✓ Branch 35 taken 1 times. ✗ Branch 36 not taken. ✓ Branch 37 taken 1 times. ✗ Branch 38 not taken. ✓ Branch 39 taken 1 times. ✗ Branch 40 not taken. ✓ Branch 41 taken 1 times. ✗ Branch 42 not taken. ✓ Branch 43 taken 1 times. ✗ Branch 44 not taken. ✓ Branch 45 taken 1 times. ✗ Branch 46 not taken. ✓ Branch 47 taken 1 times. ✗ Branch 48 not taken. ✓ Branch 49 taken 1 times. ✗ Branch 50 not taken. ✓ Branch 51 taken 1 times. ✗ Branch 52 not taken. ✓ Branch 53 taken 1 times. ✗ Branch 54 not taken. ✓ Branch 55 taken 1 times. ✗ Branch 56 not taken. ✓ Branch 57 taken 1 times. ✗ Branch 58 not taken. ✓ Branch 59 taken 1 times. ✗ Branch 60 not taken. ✓ Branch 61 taken 1 times. ✗ Branch 62 not taken. ✓ Branch 63 taken 1 times. ✗ Branch 64 not taken. ✓ Branch 65 taken 1 times. ✗ Branch 66 not taken. ✓ Branch 67 taken 1 times. | 63 | inline bool valid(RealT eps=math::Delta<RealT>::value()) const { return (t1-t0)>eps; } | 
| 48 | /// @brief Return the midpoint of the ray. | ||
| 49 | 2 | inline RealT mid() const { return 0.5*(t0 + t1); } | |
| 50 | /// @brief Multiplies both times | ||
| 51 | inline void scale(RealT s) {assert(s>0); t0*=s; t1*=s; } | ||
| 52 | /// @brief Return @c true if time is inclusive | ||
| 53 | 1/2✗ Branch 0 not taken. ✓ Branch 1 taken 4 times. | 4 | inline bool test(RealT t) const { return (t>=t0 && t<=t1); } | 
| 54 | }; | ||
| 55 | |||
| 56 | 131 | Ray(const Vec3Type& eye = Vec3Type(0,0,0), | |
| 57 | const Vec3Type& direction = Vec3Type(1,0,0), | ||
| 58 | RealT t0 = math::Delta<RealT>::value(), | ||
| 59 | RealT t1 = std::numeric_limits<RealT>::max()) | ||
| 60 | 19/27✓ Branch 2 taken 1 times. ✓ Branch 3 taken 1 times. ✗ Branch 4 not taken. ✓ Branch 5 taken 1 times. ✓ Branch 6 taken 1 times. ✗ Branch 7 not taken. ✓ Branch 8 taken 2 times. ✓ Branch 9 taken 1 times. ✓ Branch 10 taken 1 times. ✓ Branch 11 taken 1 times. ✓ Branch 12 taken 1 times. ✗ Branch 13 not taken. ✓ Branch 14 taken 1 times. ✓ Branch 15 taken 1 times. ✗ Branch 16 not taken. ✓ Branch 17 taken 1 times. ✓ Branch 18 taken 1 times. ✗ Branch 19 not taken. ✓ Branch 20 taken 1 times. ✓ Branch 21 taken 1 times. ✗ Branch 22 not taken. ✓ Branch 23 taken 1 times. ✓ Branch 24 taken 1 times. ✗ Branch 25 not taken. ✓ Branch 26 taken 1 times. ✓ Branch 27 taken 1048576 times. ✗ Branch 28 not taken. | 1048760 | : mEye(eye), mDir(direction), mInvDir(1/mDir), mTimeSpan(t0, t1) | 
| 61 | { | ||
| 62 | } | ||
| 63 | |||
| 64 | 5/28✗ Branch 0 not taken. ✓ Branch 1 taken 3 times. ✗ Branch 2 not taken. ✓ Branch 3 taken 1 times. ✗ Branch 4 not taken. ✗ Branch 5 not taken. ✗ Branch 6 not taken. ✓ Branch 7 taken 6 times. ✗ Branch 8 not taken. ✗ Branch 9 not taken. ✗ Branch 10 not taken. ✗ Branch 11 not taken. ✗ Branch 12 not taken. ✗ Branch 13 not taken. ✗ Branch 14 not taken. ✗ Branch 15 not taken. ✗ Branch 16 not taken. ✓ Branch 17 taken 3 times. ✗ Branch 18 not taken. ✗ Branch 19 not taken. ✗ Branch 20 not taken. ✗ Branch 21 not taken. ✗ Branch 22 not taken. ✗ Branch 23 not taken. ✗ Branch 24 not taken. ✗ Branch 25 not taken. ✗ Branch 26 not taken. ✓ Branch 27 taken 1082366 times. | 1082381 | inline void setEye(const Vec3Type& eye) { mEye = eye; } | 
| 65 | |||
| 66 | inline void setDir(const Vec3Type& dir) | ||
| 67 | { | ||
| 68 | 5/28✗ Branch 0 not taken. ✓ Branch 1 taken 3 times. ✗ Branch 2 not taken. ✓ Branch 3 taken 1 times. ✗ Branch 4 not taken. ✗ Branch 5 not taken. ✗ Branch 6 not taken. ✓ Branch 7 taken 6 times. ✗ Branch 8 not taken. ✗ Branch 9 not taken. ✗ Branch 10 not taken. ✗ Branch 11 not taken. ✗ Branch 12 not taken. ✗ Branch 13 not taken. ✗ Branch 14 not taken. ✗ Branch 15 not taken. ✗ Branch 16 not taken. ✓ Branch 17 taken 3 times. ✗ Branch 18 not taken. ✗ Branch 19 not taken. ✗ Branch 20 not taken. ✗ Branch 21 not taken. ✗ Branch 22 not taken. ✗ Branch 23 not taken. ✗ Branch 24 not taken. ✗ Branch 25 not taken. ✗ Branch 26 not taken. ✓ Branch 27 taken 1082366 times. | 1082381 | mDir = dir; | 
| 69 | 5/28✗ Branch 0 not taken. ✓ Branch 1 taken 3 times. ✗ Branch 2 not taken. ✓ Branch 3 taken 1 times. ✗ Branch 4 not taken. ✗ Branch 5 not taken. ✗ Branch 6 not taken. ✓ Branch 7 taken 6 times. ✗ Branch 8 not taken. ✗ Branch 9 not taken. ✗ Branch 10 not taken. ✗ Branch 11 not taken. ✗ Branch 12 not taken. ✗ Branch 13 not taken. ✗ Branch 14 not taken. ✗ Branch 15 not taken. ✗ Branch 16 not taken. ✓ Branch 17 taken 3 times. ✗ Branch 18 not taken. ✗ Branch 19 not taken. ✗ Branch 20 not taken. ✗ Branch 21 not taken. ✗ Branch 22 not taken. ✗ Branch 23 not taken. ✗ Branch 24 not taken. ✗ Branch 25 not taken. ✗ Branch 26 not taken. ✓ Branch 27 taken 1082366 times. | 1082381 | mInvDir = 1/mDir; | 
| 70 | } | ||
| 71 | |||
| 72 | 5/28✗ Branch 0 not taken. ✓ Branch 1 taken 3 times. ✗ Branch 2 not taken. ✓ Branch 3 taken 1 times. ✗ Branch 4 not taken. ✗ Branch 5 not taken. ✗ Branch 6 not taken. ✓ Branch 7 taken 6 times. ✗ Branch 8 not taken. ✗ Branch 9 not taken. ✗ Branch 10 not taken. ✗ Branch 11 not taken. ✗ Branch 12 not taken. ✗ Branch 13 not taken. ✗ Branch 14 not taken. ✗ Branch 15 not taken. ✗ Branch 16 not taken. ✓ Branch 17 taken 3 times. ✗ Branch 18 not taken. ✗ Branch 19 not taken. ✗ Branch 20 not taken. ✗ Branch 21 not taken. ✗ Branch 22 not taken. ✗ Branch 23 not taken. ✗ Branch 24 not taken. ✗ Branch 25 not taken. ✗ Branch 26 not taken. ✓ Branch 27 taken 1082366 times. | 1082379 | inline void setMinTime(RealT t0) { assert(t0>0); mTimeSpan.t0 = t0; } | 
| 73 | |||
| 74 | 5/28✗ Branch 0 not taken. ✓ Branch 1 taken 3 times. ✗ Branch 4 not taken. ✓ Branch 5 taken 1 times. ✗ Branch 8 not taken. ✗ Branch 9 not taken. ✗ Branch 12 not taken. ✓ Branch 13 taken 6 times. ✗ Branch 16 not taken. ✗ Branch 17 not taken. ✗ Branch 20 not taken. ✗ Branch 21 not taken. ✗ Branch 24 not taken. ✗ Branch 25 not taken. ✗ Branch 28 not taken. ✗ Branch 29 not taken. ✗ Branch 32 not taken. ✓ Branch 33 taken 3 times. ✗ Branch 36 not taken. ✗ Branch 37 not taken. ✗ Branch 40 not taken. ✗ Branch 41 not taken. ✗ Branch 44 not taken. ✗ Branch 45 not taken. ✗ Branch 48 not taken. ✗ Branch 49 not taken. ✗ Branch 52 not taken. ✓ Branch 53 taken 1082366 times. | 1082379 | inline void setMaxTime(RealT t1) { assert(t1>0); mTimeSpan.t1 = t1; } | 
| 75 | |||
| 76 | inline void setTimes( | ||
| 77 | RealT t0 = math::Delta<RealT>::value(), | ||
| 78 | RealT t1 = std::numeric_limits<RealT>::max()) | ||
| 79 | { | ||
| 80 | 14/32✓ Branch 0 taken 537345 times. ✗ Branch 1 not taken. ✗ Branch 2 not taken. ✓ Branch 3 taken 537345 times. ✓ Branch 5 taken 6 times. ✗ Branch 6 not taken. ✗ Branch 7 not taken. ✓ Branch 8 taken 6 times. ✓ Branch 10 taken 515868 times. ✗ Branch 11 not taken. ✗ Branch 12 not taken. ✓ Branch 13 taken 515868 times. ✓ Branch 15 taken 21 times. ✗ Branch 16 not taken. ✗ Branch 17 not taken. ✓ Branch 18 taken 21 times. ✓ Branch 20 taken 266257 times. ✗ Branch 21 not taken. ✗ Branch 22 not taken. ✓ Branch 23 taken 266257 times. ✓ Branch 25 taken 6 times. ✗ Branch 26 not taken. ✗ Branch 27 not taken. ✓ Branch 28 taken 6 times. ✓ Branch 30 taken 13 times. ✗ Branch 31 not taken. ✗ Branch 32 not taken. ✓ Branch 33 taken 13 times. ✗ Branch 35 not taken. ✗ Branch 36 not taken. ✗ Branch 37 not taken. ✗ Branch 38 not taken. | 1319516 | assert(t0>0 && t1>0); | 
| 81 | mTimeSpan.set(t0, t1); | ||
| 82 | 13 | } | |
| 83 | |||
| 84 | inline void scaleTimes(RealT scale) { mTimeSpan.scale(scale); } | ||
| 85 | |||
| 86 | 1/2✓ Branch 0 taken 2 times. ✗ Branch 1 not taken. | 2 | inline void reset( | 
| 87 | const Vec3Type& eye, | ||
| 88 | const Vec3Type& direction, | ||
| 89 | RealT t0 = math::Delta<RealT>::value(), | ||
| 90 | RealT t1 = std::numeric_limits<RealT>::max()) | ||
| 91 | { | ||
| 92 | this->setEye(eye); | ||
| 93 | this->setDir(direction); | ||
| 94 | this->setTimes(t0, t1); | ||
| 95 | 2 | } | |
| 96 | |||
| 97 | inline const Vec3T& eye() const {return mEye;} | ||
| 98 | |||
| 99 | 2/4✓ Branch 1 taken 205861 times. ✗ Branch 2 not taken. ✓ Branch 4 taken 8 times. ✗ Branch 5 not taken. | 205869 | inline const Vec3T& dir() const {return mDir;} | 
| 100 | |||
| 101 | inline const Vec3T& invDir() const {return mInvDir;} | ||
| 102 | |||
| 103 | 2/4✓ Branch 1 taken 1 times. ✗ Branch 2 not taken. ✓ Branch 4 taken 1 times. ✗ Branch 5 not taken. | 2668165 | inline RealT t0() const {return mTimeSpan.t0;} | 
| 104 | |||
| 105 | 2/4✓ Branch 1 taken 1 times. ✗ Branch 2 not taken. ✓ Branch 4 taken 1 times. ✗ Branch 5 not taken. | 2668178 | inline RealT t1() const {return mTimeSpan.t1;} | 
| 106 | |||
| 107 | /// @brief Return the position along the ray at the specified time. | ||
| 108 | 5014770 | inline Vec3R operator()(RealT time) const { return mEye + mDir * time; } | |
| 109 | |||
| 110 | /// @brief Return the starting point of the ray. | ||
| 111 | 3 | inline Vec3R start() const { return (*this)(mTimeSpan.t0); } | |
| 112 | |||
| 113 | /// @brief Return the endpoint of the ray. | ||
| 114 | 3 | inline Vec3R end() const { return (*this)(mTimeSpan.t1); } | |
| 115 | |||
| 116 | /// @brief Return the midpoint of the ray. | ||
| 117 | 3 | inline Vec3R mid() const { return (*this)(mTimeSpan.mid()); } | |
| 118 | |||
| 119 | /// @brief Return @c true if t1 is larger than t0 by at least eps. | ||
| 120 | inline bool valid(RealT eps=math::Delta<float>::value()) const { return mTimeSpan.valid(eps); } | ||
| 121 | |||
| 122 | /// @brief Return @c true if @a time is within t0 and t1, both inclusive. | ||
| 123 | inline bool test(RealT time) const { return mTimeSpan.test(time); } | ||
| 124 | |||
| 125 | /// @brief Return a new Ray that is transformed with the specified map. | ||
| 126 | /// @param map the map from which to construct the new Ray. | ||
| 127 | /// @warning Assumes a linear map and a normalized direction. | ||
| 128 | /// @details The requirement that the direction is normalized | ||
| 129 | /// follows from the transformation of t0 and t1 - and that fact that | ||
| 130 | /// we want applyMap and applyInverseMap to be inverse operations. | ||
| 131 | template<typename MapType> | ||
| 132 | 2 | inline Ray applyMap(const MapType& map) const | |
| 133 | { | ||
| 134 | 1/2✗ Branch 1 not taken. ✓ Branch 2 taken 2 times. | 2 | assert(map.isLinear()); | 
| 135 | ✗ | assert(math::isRelOrApproxEqual(mDir.length(), RealT(1), | |
| 136 | Tolerance<RealT>::value(), Delta<RealT>::value())); | ||
| 137 | 2 | const Vec3T eye = map.applyMap(mEye); | |
| 138 | 2 | const Vec3T dir = map.applyJacobian(mDir); | |
| 139 | const RealT length = dir.length(); | ||
| 140 | 2 | return Ray(eye, dir/length, length*mTimeSpan.t0, length*mTimeSpan.t1); | |
| 141 | } | ||
| 142 | |||
| 143 | /// @brief Return a new Ray that is transformed with the inverse of the specified map. | ||
| 144 | /// @param map the map from which to construct the new Ray by inverse mapping. | ||
| 145 | /// @warning Assumes a linear map and a normalized direction. | ||
| 146 | /// @details The requirement that the direction is normalized | ||
| 147 | /// follows from the transformation of t0 and t1 - and that fact that | ||
| 148 | /// we want applyMap and applyInverseMap to be inverse operations. | ||
| 149 | template<typename MapType> | ||
| 150 | 1048586 | inline Ray applyInverseMap(const MapType& map) const | |
| 151 | { | ||
| 152 | 1/2✗ Branch 1 not taken. ✓ Branch 2 taken 1048586 times. | 1048586 | assert(map.isLinear()); | 
| 153 | ✗ | assert(math::isRelOrApproxEqual(mDir.length(), RealT(1), Tolerance<RealT>::value(), Delta<RealT>::value())); | |
| 154 | 1048586 | const Vec3T eye = map.applyInverseMap(mEye); | |
| 155 | 1048586 | const Vec3T dir = map.applyInverseJacobian(mDir); | |
| 156 | const RealT length = dir.length(); | ||
| 157 | 1048586 | return Ray(eye, dir/length, length*mTimeSpan.t0, length*mTimeSpan.t1); | |
| 158 | } | ||
| 159 | |||
| 160 | /// @brief Return a new ray in world space, assuming the existing | ||
| 161 | /// ray is represented in the index space of the specified grid. | ||
| 162 | template<typename GridType> | ||
| 163 | inline Ray indexToWorld(const GridType& grid) const | ||
| 164 | { | ||
| 165 | return this->applyMap(*(grid.transform().baseMap())); | ||
| 166 | } | ||
| 167 | |||
| 168 | /// @brief Return a new ray in the index space of the specified | ||
| 169 | /// grid, assuming the existing ray is represented in world space. | ||
| 170 | template<typename GridType> | ||
| 171 | 1048584 | inline Ray worldToIndex(const GridType& grid) const | |
| 172 | { | ||
| 173 | 1/2✓ Branch 1 taken 1048584 times. ✗ Branch 2 not taken. | 2097168 | return this->applyInverseMap(*(grid.transform().baseMap())); | 
| 174 | } | ||
| 175 | |||
| 176 | /// @brief Return true if this ray intersects the specified sphere. | ||
| 177 | /// @param center The center of the sphere in the same space as this ray. | ||
| 178 | /// @param radius The radius of the sphere in the same units as this ray. | ||
| 179 | /// @param t0 The first intersection point if an intersection exists. | ||
| 180 | /// @param t1 The second intersection point if an intersection exists. | ||
| 181 | /// @note If the return value is true, i.e. a hit, and t0 = | ||
| 182 | /// this->t0() or t1 == this->t1() only one true intersection exist. | ||
| 183 | 2/2✓ Branch 0 taken 205870 times. ✓ Branch 1 taken 1 times. | 205871 | 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 | 205871 | const RealT B = 2 * mDir.dot(origin); | |
| 188 | 205871 | const RealT C = origin.lengthSqr() - radius * radius; | |
| 189 | 205871 | const RealT D = B * B - 4 * A * C; | |
| 190 | |||
| 191 | 2/2✓ Branch 0 taken 205870 times. ✓ Branch 1 taken 1 times. | 205871 | if (D < 0) return false; | 
| 192 | |||
| 193 | 1/2✓ Branch 0 taken 205870 times. ✗ Branch 1 not taken. | 205870 | const RealT Q = RealT(-0.5)*(B<0 ? (B + Sqrt(D)) : (B - Sqrt(D))); | 
| 194 | |||
| 195 | 205870 | t0 = Q / A; | |
| 196 | 205870 | t1 = C / Q; | |
| 197 | |||
| 198 | 1/2✗ Branch 0 not taken. ✓ Branch 1 taken 205870 times. | 205870 | if (t0 > t1) std::swap(t0, t1); | 
| 199 | 2/2✓ Branch 0 taken 1 times. ✓ Branch 1 taken 205869 times. | 205870 | if (t0 < mTimeSpan.t0) t0 = mTimeSpan.t0; | 
| 200 | 1/2✗ Branch 0 not taken. ✓ Branch 1 taken 205870 times. | 205870 | if (t1 > mTimeSpan.t1) t1 = mTimeSpan.t1; | 
| 201 | 205870 | return t0 <= t1; | |
| 202 | } | ||
| 203 | |||
| 204 | /// @brief Return true if this ray intersects the specified sphere. | ||
| 205 | /// @param center The center of the sphere in the same space as this ray. | ||
| 206 | /// @param radius The radius of the sphere in the same units as this ray. | ||
| 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 | |||
| 213 | /// @brief Return true if this ray intersects the specified sphere. | ||
| 214 | /// @note For intersection this ray is clipped to the two intersection points. | ||
| 215 | /// @param center The center of the sphere in the same space as this ray. | ||
| 216 | /// @param radius The radius of the sphere in the same units as this ray. | ||
| 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 | |||
| 225 | /// @brief Return true if the Ray intersects the specified | ||
| 226 | /// axisaligned bounding box. | ||
| 227 | /// @param bbox Axis-aligned bounding box in the same space as the Ray. | ||
| 228 | /// @param t0 If an intersection is detected this is assigned | ||
| 229 | /// the time for the first intersection point. | ||
| 230 | /// @param t1 If an intersection is detected this is assigned | ||
| 231 | /// the time for the second intersection point. | ||
| 232 | template<typename BBoxT> | ||
| 233 | 1048605 | inline bool intersects(const BBoxT& bbox, RealT& t0, RealT& t1) const | |
| 234 | { | ||
| 235 | mTimeSpan.get(t0, t1); | ||
| 236 | 2/2✓ Branch 0 taken 2430033 times. ✓ Branch 1 taken 266281 times. | 2696322 | for (int i = 0; i < 3; ++i) { | 
| 237 | 4/6✗ Branch 0 not taken. ✓ Branch 1 taken 2430027 times. ✗ Branch 2 not taken. ✓ Branch 3 taken 2430027 times. ✓ Branch 4 taken 16 times. ✓ Branch 5 taken 2430011 times. | 2430039 | RealT a = (bbox.min()[i] - mEye[i]) * mInvDir[i]; | 
| 238 | 2430039 | RealT b = (bbox.max()[i] - mEye[i]) * mInvDir[i]; | |
| 239 | 2/2✓ Branch 0 taken 18 times. ✓ Branch 1 taken 2430015 times. | 2430039 | if (a > b) std::swap(a, b); | 
| 240 | 2/2✓ Branch 0 taken 657438 times. ✓ Branch 1 taken 1772595 times. | 2430039 | if (a > t0) t0 = a; | 
| 241 | 2/2✓ Branch 0 taken 1048605 times. ✓ Branch 1 taken 1381428 times. | 2430039 | if (b < t1) t1 = b; | 
| 242 | 2/2✓ Branch 0 taken 1647711 times. ✓ Branch 1 taken 782322 times. | 2430039 | if (t0 > t1) return false; | 
| 243 | } | ||
| 244 | return true; | ||
| 245 | } | ||
| 246 | |||
| 247 | /// @brief Return true if this ray intersects the specified bounding box. | ||
| 248 | /// @param bbox Axis-aligned bounding box in the same space as this ray. | ||
| 249 | template<typename BBoxT> | ||
| 250 | inline bool intersects(const BBoxT& bbox) const | ||
| 251 | { | ||
| 252 | RealT t0, t1; | ||
| 253 | 1 | return this->intersects(bbox, t0, t1); | |
| 254 | } | ||
| 255 | |||
| 256 | /// @brief Return true if this ray intersects the specified bounding box. | ||
| 257 | /// @note For intersection this ray is clipped to the two intersection points. | ||
| 258 | /// @param bbox Axis-aligned bounding box in the same space as this ray. | ||
| 259 | template<typename BBoxT> | ||
| 260 | ✗ | inline bool clip(const BBoxT& bbox) | |
| 261 | { | ||
| 262 | RealT t0, t1; | ||
| 263 | 1048600 | const bool hit = this->intersects(bbox, t0, t1); | |
| 264 | 4/8✓ Branch 0 taken 266270 times. ✓ Branch 1 taken 782320 times. ✓ Branch 2 taken 9 times. ✗ Branch 3 not taken. ✗ Branch 4 not taken. ✓ Branch 5 taken 1 times. ✗ Branch 6 not taken. ✗ Branch 7 not taken. | 1048600 | if (hit) mTimeSpan.set(t0, t1); | 
| 265 | ✗ | return hit; | |
| 266 | } | ||
| 267 | |||
| 268 | /// @brief Return true if the Ray intersects the plane specified | ||
| 269 | /// by a normal and distance from the origin. | ||
| 270 | /// @param normal Normal of the plane. | ||
| 271 | /// @param distance Distance of the plane to the origin. | ||
| 272 | /// @param t Time of intersection, if one exists. | ||
| 273 | 2/2✓ Branch 0 taken 6 times. ✓ Branch 1 taken 4 times. | 10 | 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 | 2/2✓ Branch 0 taken 4 times. ✓ Branch 1 taken 5 times. | 9 | t = (distance - mEye.dot(normal))/cosAngle; | 
| 278 | return this->test(t); | ||
| 279 | } | ||
| 280 | |||
| 281 | /// @brief Return true if the Ray intersects the plane specified | ||
| 282 | /// by a normal and point. | ||
| 283 | /// @param normal Normal of the plane. | ||
| 284 | /// @param point Point in the plane. | ||
| 285 | /// @param t Time of intersection, if one exists. | ||
| 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 | |||
| 297 | /// @brief Output streaming of the Ray class. | ||
| 298 | /// @note Primarily intended for debugging. | ||
| 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 | ||
| 312 |