CUDAPointHashGridSearcher2-Impl.hpp
Go to the documentation of this file.
1 // This code is based on Jet framework.
2 // Copyright (c) 2018 Doyub Kim
3 // CubbyFlow is voxel-based fluid simulation engine for computer games.
4 // Copyright (c) 2020 CubbyFlow Team
5 // Core Part: Chris Ohk, Junwoo Hwang, Jihong Sin, Seungwoo Yoo
6 // AI Part: Dongheon Cho, Minseo Kim
7 // We are making my contributions/submissions to this project solely in our
8 // personal capacity and are not conveying any rights to any intellectual
9 // property of any third parties.
10 
11 #ifndef CUBBYFLOW_CUDA_POINT_HASH_GRID_SEARCHER2_IMPL_HPP
12 #define CUBBYFLOW_CUDA_POINT_HASH_GRID_SEARCHER2_IMPL_HPP
13 
14 #ifdef CUBBYFLOW_USE_CUDA
15 
16 #include <Core/CUDA/CUDAUtils.hpp>
17 
18 #include <thrust/for_each.h>
19 #include <thrust/iterator/counting_iterator.h>
20 
21 namespace CubbyFlow
22 {
23 CUBBYFLOW_CUDA_HOST_DEVICE CUDAPointHashGridSearcher2::HashUtils::HashUtils(
24  float gridSpacing, uint2 resolution)
25  : m_gridSpacing{ gridSpacing }, m_resolution{ resolution }
26 {
27  (void)m_dummy;
28 }
29 
30 inline CUBBYFLOW_CUDA_HOST_DEVICE void
31 CUDAPointHashGridSearcher2::HashUtils::GetNearbyKeys(float2 position,
32  uint32_t* nearbyKeys) const
33 {
34  int2 originIndex = GetBucketIndex(position), nearbyBucketIndices[8];
35 
36  for (int i = 0; i < 4; i++)
37  {
38  nearbyBucketIndices[i] = originIndex;
39  }
40 
41  if ((originIndex.x + 0.5f) * m_gridSpacing <= position.x)
42  {
43  nearbyBucketIndices[2].x += 1;
44  nearbyBucketIndices[3].x += 1;
45  }
46  else
47  {
48  nearbyBucketIndices[2].x -= 1;
49  nearbyBucketIndices[3].x -= 1;
50  }
51 
52  if ((originIndex.y + 0.5f) * m_gridSpacing <= position.y)
53  {
54  nearbyBucketIndices[1].y += 1;
55  nearbyBucketIndices[3].y += 1;
56  }
57  else
58  {
59  nearbyBucketIndices[1].y -= 1;
60  nearbyBucketIndices[3].y -= 1;
61  }
62 
63  for (int i = 0; i < 4; i++)
64  {
65  nearbyKeys[i] = GetHashKeyFromBucketIndex(nearbyBucketIndices[i]);
66  }
67 }
68 
69 inline CUBBYFLOW_CUDA_HOST_DEVICE int2
70 CUDAPointHashGridSearcher2::HashUtils::GetBucketIndex(float2 position) const
71 {
72  int2 bucketIndex;
73 
74  bucketIndex.x = static_cast<int>(floorf(position.x / m_gridSpacing));
75  bucketIndex.y = static_cast<int>(floorf(position.y / m_gridSpacing));
76 
77  return bucketIndex;
78 }
79 
80 inline CUBBYFLOW_CUDA_HOST_DEVICE uint32_t
81 CUDAPointHashGridSearcher2::HashUtils::GetHashKeyFromBucketIndex(
82  int2 bucketIndex) const
83 {
84  // Assumes m_resolution is power of two
85  bucketIndex.x = bucketIndex.x & (m_resolution.x - 1);
86  bucketIndex.y = bucketIndex.y & (m_resolution.y - 1);
87  return bucketIndex.y * m_resolution.x + bucketIndex.x;
88 }
89 
90 inline CUBBYFLOW_CUDA_HOST_DEVICE uint32_t
91 CUDAPointHashGridSearcher2::HashUtils::GetHashKeyFromPosition(
92  float2 position) const
93 {
94  int2 bucketIndex = GetBucketIndex(position);
95  return GetHashKeyFromBucketIndex(bucketIndex);
96 }
97 
98 template <typename Callback>
99 inline CUBBYFLOW_CUDA_HOST_DEVICE CUDAPointHashGridSearcher2::
100  ForEachNearbyPointFunc<Callback>::ForEachNearbyPointFunc(
101  float r, float gridSpacing, uint2 resolution, const uint32_t* sit,
102  const uint32_t* eit, const uint32_t* si, const float2* p,
103  const float2* o, Callback cb)
104  : m_hashUtils(gridSpacing, resolution),
105  m_radius(r),
106  m_startIndexTable(sit),
107  m_endIndexTable(eit),
108  m_sortedIndices(si),
109  m_points(p),
110  m_origins(o),
111  m_callback(cb)
112 {
113  // Do nothing
114 }
115 
116 template <typename Callback>
117 template <typename Index>
118 inline CUBBYFLOW_CUDA_HOST_DEVICE void
119 CUDAPointHashGridSearcher2::ForEachNearbyPointFunc<Callback>::operator()(
120  Index idx)
121 {
122  const float2 origin = m_origins[idx];
123 
124  uint32_t nearbyKeys[4];
125  m_hashUtils.GetNearbyKeys(origin, nearbyKeys);
126 
127  const float queryRadiusSquared = m_radius * m_radius;
128 
129  for (int i = 0; i < 4; i++)
130  {
131  uint32_t nearbyKey = nearbyKeys[i];
132  uint32_t start = m_startIndexTable[nearbyKey];
133 
134  // Empty bucket -- continue to next bucket
135  if (start == 0xffffffff)
136  {
137  continue;
138  }
139 
140  uint32_t end = m_endIndexTable[nearbyKey];
141 
142  for (uint32_t jj = start; jj < end; ++jj)
143  {
144  uint32_t j = m_sortedIndices[jj];
145  float2 p = m_points[jj];
146  float2 direction = p - origin;
147 
148  float distanceSquared = LengthSquared(direction);
149  if (distanceSquared <= queryRadiusSquared)
150  {
151  if (distanceSquared > 0)
152  {
153  float distance = sqrtf(distanceSquared);
154  direction /= distance;
155  }
156 
157  m_callback(idx, origin, j, p);
158  }
159  }
160  }
161 }
162 
163 template <typename Callback>
164 void CUDAPointHashGridSearcher2::ForEachNearbyPoint(
165  const ConstCUDAArrayView1<float2>& origins, float radius,
166  Callback callback) const
167 {
168  thrust::for_each(
169  thrust::counting_iterator<size_t>(0),
170  thrust::counting_iterator<size_t>(0) + origins.Length(),
171  ForEachNearbyPointFunc<Callback>(
172  radius, m_gridSpacing, m_resolution, m_startIndexTable.data(),
173  m_endIndexTable.data(), m_sortedIndices.data(), m_points.data(),
174  origins.data(), callback));
175 }
176 } // namespace CubbyFlow
177 
178 #endif
179 
180 #endif
Iterator end()
Definition: ArrayBase-Impl.hpp:102
Definition: pybind11Utils.hpp:20
size_t Index(size_t i) const
Definition: ArrayBase-Impl.hpp:17