Loading...
Searching...
No Matches
CUDAPointHashGridSearcher3-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_SEARCHER3_IMPL_HPP
12#define CUBBYFLOW_CUDA_POINT_HASH_GRID_SEARCHER3_IMPL_HPP
13
14#ifdef CUBBYFLOW_USE_CUDA
15
17
18#include <thrust/for_each.h>
19#include <thrust/iterator/counting_iterator.h>
20
21namespace CubbyFlow
22{
23CUBBYFLOW_CUDA_HOST_DEVICE CUDAPointHashGridSearcher3::HashUtils::HashUtils(
25 : m_gridSpacing{ gridSpacing }, m_resolution{ resolution }
26{
27 // Do nothing
28}
29
30inline CUBBYFLOW_CUDA_HOST_DEVICE void
31CUDAPointHashGridSearcher3::HashUtils::GetNearbyKeys(float4 position,
32 uint32_t* nearbyKeys) const
33{
34 int3 originIndex = GetBucketIndex(position), nearbyBucketIndices[8];
35
36 for (int i = 0; i < 8; i++)
37 {
38 nearbyBucketIndices[i] = originIndex;
39 }
40
41 if ((originIndex.x + 0.5f) * m_gridSpacing <= position.x)
42 {
43 nearbyBucketIndices[1].x += 1;
44 nearbyBucketIndices[3].x += 1;
45 nearbyBucketIndices[5].x += 1;
46 nearbyBucketIndices[7].x += 1;
47 }
48 else
49 {
50 nearbyBucketIndices[1].x -= 1;
51 nearbyBucketIndices[3].x -= 1;
52 nearbyBucketIndices[5].x -= 1;
53 nearbyBucketIndices[7].x -= 1;
54 }
55
56 if ((originIndex.y + 0.5f) * m_gridSpacing <= position.y)
57 {
58 nearbyBucketIndices[2].y += 1;
59 nearbyBucketIndices[3].y += 1;
60 nearbyBucketIndices[6].y += 1;
61 nearbyBucketIndices[7].y += 1;
62 }
63 else
64 {
65 nearbyBucketIndices[2].y -= 1;
66 nearbyBucketIndices[3].y -= 1;
67 nearbyBucketIndices[6].y -= 1;
68 nearbyBucketIndices[7].y -= 1;
69 }
70
71 if ((originIndex.z + 0.5f) * m_gridSpacing <= position.z)
72 {
73 nearbyBucketIndices[4].z += 1;
74 nearbyBucketIndices[5].z += 1;
75 nearbyBucketIndices[6].z += 1;
76 nearbyBucketIndices[7].z += 1;
77 }
78 else
79 {
80 nearbyBucketIndices[4].z -= 1;
81 nearbyBucketIndices[5].z -= 1;
82 nearbyBucketIndices[6].z -= 1;
83 nearbyBucketIndices[7].z -= 1;
84 }
85
86 for (int i = 0; i < 8; i++)
87 {
88 nearbyKeys[i] = GetHashKeyFromBucketIndex(nearbyBucketIndices[i]);
89 }
90}
91
92inline CUBBYFLOW_CUDA_HOST_DEVICE int3
93CUDAPointHashGridSearcher3::HashUtils::GetBucketIndex(float4 position) const
94{
95 int3 bucketIndex;
96
97 bucketIndex.x = static_cast<int>(floorf(position.x / m_gridSpacing));
98 bucketIndex.y = static_cast<int>(floorf(position.y / m_gridSpacing));
99 bucketIndex.z = static_cast<int>(floorf(position.z / m_gridSpacing));
100
101 return bucketIndex;
102}
103
104inline CUBBYFLOW_CUDA_HOST_DEVICE uint32_t
105CUDAPointHashGridSearcher3::HashUtils::GetHashKeyFromBucketIndex(
106 int3 bucketIndex) const
107{
108 // Assumes m_resolution is power of two
109 bucketIndex.x = bucketIndex.x & (m_resolution.x - 1);
110 bucketIndex.y = bucketIndex.y & (m_resolution.y - 1);
111 bucketIndex.z = bucketIndex.z & (m_resolution.z - 1);
112 return bucketIndex.z * m_resolution.y * m_resolution.x +
113 bucketIndex.y * m_resolution.x + bucketIndex.x;
114}
115
116inline CUBBYFLOW_CUDA_HOST_DEVICE uint32_t
117CUDAPointHashGridSearcher3::HashUtils::GetHashKeyFromPosition(
118 float4 position) const
119{
120 int3 bucketIndex = GetBucketIndex(position);
121 return GetHashKeyFromBucketIndex(bucketIndex);
122}
123
124template <typename Callback>
125inline CUBBYFLOW_CUDA_HOST_DEVICE CUDAPointHashGridSearcher3::
126 ForEachNearbyPointFunc<Callback>::ForEachNearbyPointFunc(
127 float r, float gridSpacing, uint3 resolution, const uint32_t* sit,
128 const uint32_t* eit, const uint32_t* si, const float4* p,
129 const float4* o, Callback cb)
130 : m_hashUtils(gridSpacing, resolution),
131 m_radius(r),
132 m_startIndexTable(sit),
133 m_endIndexTable(eit),
134 m_sortedIndices(si),
135 m_points(p),
136 m_origins(o),
137 m_callback(cb)
138{
139 // Do nothing
140}
141
142template <typename Callback>
143template <typename Index>
144inline CUBBYFLOW_CUDA_HOST_DEVICE void
145CUDAPointHashGridSearcher3::ForEachNearbyPointFunc<Callback>::operator()(
146 Index idx)
147{
148 const float4 origin = m_origins[idx];
149
150 uint32_t nearbyKeys[8];
151 m_hashUtils.GetNearbyKeys(origin, nearbyKeys);
152
153 const float queryRadiusSquared = m_radius * m_radius;
154
155 for (int i = 0; i < 8; i++)
156 {
157 uint32_t nearbyKey = nearbyKeys[i];
158 uint32_t start = m_startIndexTable[nearbyKey];
159
160 // Empty bucket -- continue to next bucket
161 if (start == 0xffffffff)
162 {
163 continue;
164 }
165
166 uint32_t end = m_endIndexTable[nearbyKey];
167
168 for (uint32_t jj = start; jj < end; ++jj)
169 {
170 uint32_t j = m_sortedIndices[jj];
171 float4 p = m_points[jj];
172 float4 direction = p - origin;
173
174 float distanceSquared = LengthSquared(direction);
175 if (distanceSquared <= queryRadiusSquared)
176 {
177 if (distanceSquared > 0)
178 {
179 float distance = sqrtf(distanceSquared);
180 direction /= distance;
181 }
182
183 m_callback(idx, origin, j, p);
184 }
185 }
186 }
187}
188
189template <typename Callback>
190void CUDAPointHashGridSearcher3::ForEachNearbyPoint(
191 const ConstCUDAArrayView1<float4>& origins, float radius,
192 Callback callback) const
193{
194 thrust::for_each(
195 thrust::counting_iterator<size_t>(0),
196 thrust::counting_iterator<size_t>(0) + origins.Length(),
197 ForEachNearbyPointFunc<Callback>(
198 radius, m_gridSpacing, m_resolution, m_startIndexTable.data(),
199 m_endIndexTable.data(), m_sortedIndices.data(), m_points.data(),
200 origins.data(), callback));
201}
202} // namespace CubbyFlow
203
204#endif
205
206#endif
Definition pybind11Utils.hpp:21
Matrix< T, Rows, 1 > Vector
Definition Matrix.hpp:738