项目作者: ToruNiina

项目描述 :
an implementation of parallel linear BVH (LBVH) on GPU
高级语言: Cuda
项目地址: git://github.com/ToruNiina/lbvh.git
创建时间: 2019-07-29T07:40:27Z
项目社区:https://github.com/ToruNiina/lbvh

开源协议:MIT License

下载


LBVH

An implementation of the following paper

  • Tero Karras, “Maximizing Parallelism in the Construction of BVHs, Octrees, and k-d Trees”, High Performance Graphics (2012)

and the following blog posts

depending on thrust.

It can contain any object and also handles morton code overlap.

If the morton codes of objects are the same, it appends object index to the
morton code and use the “extended” indices as described in the paper.

Also, nearest neighbor query based on the following paper is supported.

  • Nick Roussopoulos, Stephen Kelley, Frederic Vincent, “Nearest Neighbor Queries”, ACM-SIGMOD (1995)

example code

  1. struct object
  2. {
  3. // any object you want.
  4. // For example, sphere.
  5. float4 xyzr;
  6. };
  7. struct aabb_getter
  8. {
  9. // return aabb<float> if your object uses float.
  10. // if you chose double, return aabb<double>.
  11. __device__
  12. lbvh::aabb<float> operator()(const object& f) const noexcept
  13. {
  14. // calculate aabb of object ...
  15. const float r = f.xyzr.r;
  16. lbvh::aabb<float> box;
  17. box.upper = make_float4(f.xyzr.x + r, f.xyzr.y + r, f.xyzr.z + r, 0.0f);
  18. box.lower = make_float4(f.xyzr.x - r, f.xyzr.y - r, f.xyzr.z - r, 0.0f);
  19. return box;
  20. }
  21. };
  22. // this struct will be used in nearest neighbor query (If you don't need nearest
  23. // neighbor query, you don't need to implement this).
  24. struct distance_sq_calculator
  25. {
  26. __device__
  27. float operator()(const float4 pos, const object& f) const noexcept
  28. {
  29. // calculate square distance...
  30. const float dx = pos.x - f.xyzr.x;
  31. const float dy = pos.y - f.xyzr.y;
  32. const float dz = pos.z - f.xyzr.z;
  33. return dx * dx + dy * dy + dz * dz;
  34. }
  35. };
  36. int main()
  37. {
  38. std::vector<objects> objs;
  39. // initialize objs ...
  40. // construct a bvh
  41. lbvh::bvh<float, object, aabb_getter> bvh(objs.begin(), objs.end());
  42. // get a set of device (raw) pointers to use it in device functions.
  43. // Do not use this on host!
  44. const auto bvh_dev = bvh.get_device_repr();
  45. thrust::for_each(thrust::device,
  46. thrust::make_counting_iterator<unsigned int>(0),
  47. thrust::make_counting_iterator<unsigned int>(N),
  48. [bvh_dev] __device__ (const unsigned int idx)
  49. {
  50. unsigned int buffer[10];
  51. point_getter get_point;
  52. const auto self = get_point(bvh_dev.objects[idx]);
  53. // make a query box.
  54. const lbvh::aabb<float> box(
  55. make_float4(self.x-0.1, self.y-0.1, self.z-0.1, 0),
  56. make_float4(self.x+0.1, self.y+0.1, self.z+0.1, 0)
  57. );
  58. // send a query!
  59. const auto num_found = query_device(bvh_dev, overlaps(box), 10, buffer);
  60. for(unsigned int j=0; j<num_found; ++j)
  61. {
  62. const unsigned int other_idx = buffer[j];
  63. const object& other = bvh_dev.objects[other_idx];
  64. // do some stuff ...
  65. }
  66. const float3 pos = make_float3(0.0, 1.0, 2.0);
  67. const auto nearest = query_device(bvh_dev, nearest(pos), distance_sq_calculator());
  68. return ;
  69. });
  70. return 0;
  71. }

Synopsis

AABB

  1. template<typename T>
  2. struct aabb
  3. {
  4. /* T4 (float4 if T == float, double4 if T == double) */ upper;
  5. /* T4 (float4 if T == float, double4 if T == double) */ lower;
  6. };
  7. template<typename T>
  8. __device__ __host__
  9. inline bool intersects(const aabb<T>& lhs, const aabb<T>& rhs) noexcept;
  10. template<typename T>
  11. __device__ __host__
  12. inline aabb<T> merge(const aabb<T>& lhs, const aabb<T>& rhs) noexcept

BVH

  1. template<typename Real, typename Object, typename AABBGetter,
  2. typename MortonCodeCalculator = default_morton_code_calculator<Real, Object, AABBGetter>>
  3. class bvh
  4. {
  5. public:
  6. using real_type = Real;
  7. using index_type = std::uint32_t;
  8. using object_type = Object;
  9. using aabb_type = aabb<real_type>;
  10. using node_type = detail::node;
  11. using point_getter_type = PointGetter;
  12. using aabb_getter_type = AABBGetter;
  13. template<typename InputIterator>
  14. bvh(InputIterator first, InputIterator last)
  15. : objects_h_(first, last), objects_d_(objects_h_)
  16. {
  17. this->construct();
  18. }
  19. template<typename InputIterator>
  20. void assign(InputIterator first, InputIterator last);
  21. void clear();
  22. bvh_device<real_type, object_type> get_device_repr() noexcept;
  23. cbvh_device<real_type, object_type> get_device_repr() const noexcept;
  24. };
  25. namespace detail {
  26. template<typename Real, typename Object, bool IsConst>
  27. struct basic_device_bvh
  28. {
  29. using real_type = Real;
  30. using aabb_type = aabb<real_type>;
  31. using node_type = detail::node;
  32. using index_type = std::uint32_t;
  33. using object_type = Object;
  34. unsigned int num_nodes; // (# of internal node) + (# of leaves), 2N+1
  35. unsigned int num_leaves; // (# of leaves), N
  36. unsigned int num_objects; // (# of objects) ; can be larger than N
  37. /* const if IsConst is true */ node_type * nodes;
  38. /* const if IsConst is true */ aabb_type * aabbs;
  39. /* const if IsConst is true */ index_type * ranges;
  40. /* const if IsConst is true */ index_type * indices;
  41. /* const if IsConst is true */ object_type* objects;
  42. };
  43. }
  44. template<typename Real, typename Object>
  45. using bvh_device = detail::basic_device_bvh<Real, Object, false>;
  46. template<typename Real, typename Object>
  47. using cbvh_device = detail::basic_device_bvh<Real, Object, true>;

queries

  1. template<typename Real>
  2. __device__ __host__
  3. query_overlap<Real> overlaps(const aabb<Real>& region) noexcept;
  4. template<typename Real>
  5. __device__ __host__
  6. inline query_nearest<Real> nearest(const /*Real4 or Real3*/& point) noexcept
  7. {
  8. return query_nearest<Real>(point);
  9. }
  10. template<typename Real, typename Objects, bool IsConst, typename OutputIterator>
  11. __device__
  12. unsigned int query_device(
  13. const detail::basic_device_bvh<Real, Objects, IsConst>& bvh,
  14. const query_overlap<Real>& q, unsigned int max_buffer_size,
  15. OutputIterator outiter) noexcept;
  16. template<typename Real, typename Objects, bool IsConst, typename DistanceCalculator>
  17. __device__
  18. thrust::pair<unsigned int, Real> query_device(
  19. const detail::basic_device_bvh<Real, Objects, IsConst>& bvh,
  20. const query_nearest<Real>& q, DistanceCalculator calc_dist) noexcept