SPH
Bvh.h
Go to the documentation of this file.
1 #pragma once
2 
4 #include "objects/geometry/Box.h"
7 
9 
10 class Ray {
11  friend bool intersectBox(const Box& box, const Ray& ray, Float& t_min, Float& t_max);
12 
13 private:
14  Vector orig;
15  Vector dir;
16  Vector invDir;
17  Indices signs;
18 
19 public:
20  Ray() = default;
21 
22  Ray(const Vector& origin, const Vector& dir)
23  : orig(origin)
24  , dir(dir) {
25  for (Size i = 0; i < 3; ++i) {
26  invDir[i] = (dir[i] == 0._f) ? INFTY : 1._f / dir[i];
27  signs[i] = int(invDir[i] < 0._f);
28  }
29  }
30 
31  const Vector& origin() const {
32  return orig;
33  }
34 
35  const Vector& direction() const {
36  return dir;
37  }
38 };
39 
44 inline bool intersectBox(const Box& box, const Ray& ray, Float& t_min, Float& t_max);
45 
46 
47 struct BvhPrimitive {
50 };
51 
56 
58  const BvhPrimitive* object = nullptr;
59 
60  INLINE Vector hit(const Ray& ray) const {
61  return ray.origin() + ray.direction() * t;
62  }
63 
65  INLINE bool operator<(const IntersectionInfo& other) const {
66  return t < other.t;
67  }
68 };
69 
71 class BvhTriangle : public BvhPrimitive {
72 private:
73  Vector v0;
74  Vector dir1, dir2;
75 
76 public:
77  BvhTriangle(const Vector& v0, const Vector& v1, const Vector& v2)
78  : v0(v0) {
79  dir1 = v1 - v0;
80  dir2 = v2 - v0;
81  }
82 
83  INLINE bool getIntersection(const Ray& ray, IntersectionInfo& intersection) const {
84  // https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm#C++_Implementation
85 
86  const Float eps = EPS * dot(dir1, dir2);
87  const Vector h = cross(ray.direction(), dir2);
88  const Float a = dot(dir1, h);
89  if (a > -eps && a < eps) {
90  return false;
91  }
92  const Float f = 1._f / a;
93  const Vector s = ray.origin() - v0;
94  const Float u = f * dot(s, h);
95  if (u < 0._f || u > 1._f) {
96  return false;
97  }
98  const Vector q = cross(s, dir1);
99  const Float v = f * dot(ray.direction(), q);
100  if (v < 0._f || u + v > 1._f) {
101  return false;
102  }
103  intersection.object = this;
104  intersection.t = f * dot(dir2, q);
105  return intersection.t > 0.f;
106  }
107 
108  INLINE Box getBBox() const {
109  Box box;
110  box.extend(v0);
111  box.extend(v0 + dir1);
112  box.extend(v0 + dir2);
113  return box;
114  }
115 
117  return v0 + (dir1 + dir2) / 3._f;
118  }
119 };
120 
122 class BvhSphere : public BvhPrimitive {
123 private:
124  Vector center;
125  Float r;
126  Float rSqr;
127 
128 public:
129  BvhSphere() = default;
130 
131  BvhSphere(const Vector& center, const Float radius)
132  : center(center)
133  , r(radius)
134  , rSqr(radius * radius) {
135  SPH_ASSERT(r > 0._f);
136  }
137 
138  INLINE bool getIntersection(const Ray& ray, IntersectionInfo& intersection) const {
139  const Vector delta = center - ray.origin();
140  const Float deltaSqr = getSqrLength(delta);
141  const Float deltaCos = dot(delta, ray.direction());
142  const Float disc = sqr(deltaCos) - deltaSqr + rSqr;
143  if (disc < 0._f) {
144  return false;
145  }
146 
147  intersection.object = this;
148  intersection.t = deltaCos - sqrt(disc);
149  return intersection.t > 0.f;
150  }
151 
152  INLINE Box getBBox() const {
153  return Box(center - Vector(r), center + Vector(r));
154  }
155 
157  return center;
158  }
159 };
160 
162 class BvhBox : public BvhPrimitive {
163 private:
164  Box box;
165 
166 public:
167  explicit BvhBox(const Box& box)
168  : box(box) {}
169 
170  INLINE bool getIntersection(const Ray& ray, IntersectionInfo& intersection) const {
171  Float t_min, t_max;
172  const bool result = intersectBox(box, ray, t_min, t_max);
173  if (result) {
174  intersection.t = t_min;
175  intersection.object = this;
176  return intersection.t > 0.f;
177  } else {
178  return false;
179  }
180  }
181 
182  INLINE Box getBBox() const {
183  return box;
184  }
185 
187  return box.center();
188  }
189 };
190 
197 template <typename TBvhObject>
198 class Bvh : public Noncopyable {
199 private:
200  const Size leafSize;
201  Size nodeCnt = 0;
202  Size leafCnt = 0;
203 
204  Array<TBvhObject> objects;
205 
206  struct BvhNode {
207  Box box;
208  Size start;
209  Size primCnt;
210  Size rightOffset;
211  };
212 
213  Array<BvhNode> nodes;
214 
215 public:
216  explicit Bvh(const Size leafSize = 4)
217  : leafSize(leafSize) {}
218 
222  void build(Array<TBvhObject>&& objects);
223 
227  bool getFirstIntersection(const Ray& ray, IntersectionInfo& intersection) const;
228 
233  template <typename TOutIter>
234  Size getAllIntersections(const Ray& ray, TOutIter iter) const;
235 
237  bool isOccluded(const Ray& ray) const;
238 
240  Box getBoundingBox() const;
241 
242 private:
243  template <typename TAddIntersection>
244  void getIntersections(const Ray& ray, const TAddIntersection& addIntersection) const;
245 };
246 
248 
249 #include "objects/finders/Bvh.inl.h"
Generic dynamically allocated resizable storage.
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
Simplified implementation of std::unique_ptr, using only default deleter.
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
Object representing a three-dimensional axis-aligned box.
bool intersectBox(const Box &box, const Ray &ray, Float &t_min, Float &t_max)
Finds intersections of ray with a box.
Definition: Bvh.inl.h:16
const float radius
Definition: CurveDialog.cpp:18
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
Vectorized computations with integral numbers.
constexpr Float EPS
Definition: MathUtils.h:30
constexpr INLINE T sqr(const T &f) noexcept
Return a squared value.
Definition: MathUtils.h:67
INLINE T sqrt(const T f)
Return a squared root of a value.
Definition: MathUtils.h:78
constexpr Float INFTY
Definition: MathUtils.h:38
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define NAMESPACE_SPH_END
Definition: Object.h:12
INLINE Float getSqrLength(const Vector &v)
Definition: Vector.h:574
INLINE BasicVector< float > cross(const BasicVector< float > &v1, const BasicVector< float > &v2)
Cross product between two vectors.
Definition: Vector.h:559
BasicVector< Float > Vector
Definition: Vector.h:539
INLINE float dot(const BasicVector< float > &v1, const BasicVector< float > &v2)
Make sure the vector is trivially constructible and destructible, needed for fast initialization of a...
Definition: Vector.h:548
Helper object defining three-dimensional interval (box).
Definition: Box.h:17
INLINE void extend(const Vector &v)
Enlarges the box to contain the vector.
Definition: Box.h:49
INLINE Vector center() const
Returns the center of the box.
Definition: Box.h:112
Trait for finding intersections with a axis-aligned box.
Definition: Bvh.h:162
INLINE Box getBBox() const
Definition: Bvh.h:182
BvhBox(const Box &box)
Definition: Bvh.h:167
INLINE bool getIntersection(const Ray &ray, IntersectionInfo &intersection) const
Definition: Bvh.h:170
INLINE Vector getCenter() const
Definition: Bvh.h:186
Trait for finding intersections with a sphere.
Definition: Bvh.h:122
BvhSphere(const Vector &center, const Float radius)
Definition: Bvh.h:131
INLINE Box getBBox() const
Definition: Bvh.h:152
INLINE bool getIntersection(const Ray &ray, IntersectionInfo &intersection) const
Definition: Bvh.h:138
BvhSphere()=default
INLINE Vector getCenter() const
Definition: Bvh.h:156
Trait for finding intersections with a triangle.
Definition: Bvh.h:71
INLINE bool getIntersection(const Ray &ray, IntersectionInfo &intersection) const
Definition: Bvh.h:83
INLINE Vector getCenter() const
Definition: Bvh.h:116
BvhTriangle(const Vector &v0, const Vector &v1, const Vector &v2)
Definition: Bvh.h:77
INLINE Box getBBox() const
Definition: Bvh.h:108
Simple bounding volume hierarchy.
Definition: Bvh.h:198
Bvh(const Size leafSize=4)
Definition: Bvh.h:216
void build(Array< TBvhObject > &&objects)
Contructs the BVH from given set of objects.
Definition: Bvh.inl.h:151
Box getBoundingBox() const
Returns the bounding box of all objects in BVH.
Definition: Bvh.inl.h:235
bool isOccluded(const Ray &ray) const
Returns true if the ray is occluded by some geometry.
Definition: Bvh.inl.h:141
Size getAllIntersections(const Ray &ray, TOutIter iter) const
Returns all intersections of the ray.
Definition: Bvh.inl.h:129
bool getFirstIntersection(const Ray &ray, IntersectionInfo &intersection) const
Finds the closest intersection of the ray.
Definition: Bvh.inl.h:114
Helper object for storing three (possibly four) int or bool values.
Definition: Indices.h:16
Definition: Bvh.h:10
const Vector & direction() const
Definition: Bvh.h:35
friend bool intersectBox(const Box &box, const Ray &ray, Float &t_min, Float &t_max)
Finds intersections of ray with a box.
Definition: Bvh.inl.h:16
Ray()=default
const Vector & origin() const
Definition: Bvh.h:31
Ray(const Vector &origin, const Vector &dir)
Definition: Bvh.h:22
Size userData
Generic user data, can be used to store additional information to the primitives.
Definition: Bvh.h:49
Holds intormation about intersection.
Definition: Bvh.h:53
Float t
Distance of the hit in units of ray.direction().
Definition: Bvh.h:55
INLINE bool operator<(const IntersectionInfo &other) const
Sort by intersection distance.
Definition: Bvh.h:65
const BvhPrimitive * object
Object hit by the ray, or nullptr if nothing has been hit.
Definition: Bvh.h:58
INLINE Vector hit(const Ray &ray) const
Definition: Bvh.h:60
Object with deleted copy constructor and copy operator.
Definition: Object.h:54