MUDA
Loading...
Searching...
No Matches
sparse_spatial_hash_impl.h
1#pragma once
2#include <muda/muda_def.h>
3#include <muda/ext/geo/spatial_hash/morton_hash.h>
7#include <muda/ext/geo/spatial_hash/bounding_volume.h>
8#include <muda/ext/geo/spatial_hash/collision_pair.h>
9namespace muda::spatial_hash
10{
16{
17 public:
18 using Vector3u = Eigen::Vector3<uint32_t>;
19 using U32 = uint32_t;
20
21 struct
22 {
23 // most use unsigned int to avoid comparison problem
24 U32 pass : 3;
25 U32 home : 3;
26 U32 overlap : 8;
27 } ctlbit; // controll bit
28
29 U32 cid; // cell id
30 U32 oid;
31 // Vector3u ijk;
32
33 MUDA_GENERIC SpatialPartitionCell()
34 : cid(~0u)
35 , oid(~0u)
36 //, ijk(Vector3u::Zero())
37 {
38 ctlbit.home = 0u;
39 ctlbit.overlap = 0u;
40 ctlbit.pass = 0u;
41 }
42
43 MUDA_GENERIC SpatialPartitionCell(U32 cid, U32 oid)
44 : cid(cid)
45 , oid(oid)
46 //, ijk(Vector3u::Zero())
47 {
48 ctlbit.home = 0u;
49 ctlbit.overlap = 0u;
50 }
51
52 MUDA_GENERIC bool is_phantom() const { return ctlbit.home != ctlbit.pass; }
53
54 MUDA_GENERIC bool is_home() const { return ctlbit.home == ctlbit.pass; }
55
56 MUDA_GENERIC void set_as_phantom(const Vector3u& home_ijk, const Vector3u& cell_ijk)
57 {
58 ctlbit.pass = pass_type(cell_ijk);
59 ctlbit.home = pass_type(home_ijk);
60 }
61
62 MUDA_GENERIC void set_as_home(const Vector3u& ijk)
63 {
64 // bit 2 1 0
65 // home (i % 2) (j % 2) (k % 2)
66 ctlbit.home = pass_type(ijk);
67 ctlbit.pass = ctlbit.home;
68 ctlbit.overlap |= (1 << ctlbit.home);
69 }
70
71 MUDA_GENERIC void set_overlap(const Vector3u& ijk)
72 {
73 ctlbit.overlap |= (1 << pass_type(ijk));
74 }
75
76 MUDA_GENERIC static U32 pass_type(const Vector3u& ijk)
77 {
78 return (((U32)ijk(0) % 2) << 2) | (((U32)ijk(1) % 2) << 1)
79 | (((U32)ijk(2) % 2) << 0);
80 }
81
82 MUDA_GENERIC static bool allow_ignore(const SpatialPartitionCell& l,
83 const SpatialPartitionCell& r)
84 {
85 if(l.is_phantom() && r.is_phantom())
86 {
87 return true;
88 }
89
90 const SpatialPartitionCell* arr[] = {&l, &r};
91
92 U32 pass = l.ctlbit.pass;
93 U32 common_overlap = l.ctlbit.overlap & r.ctlbit.overlap;
94#pragma unroll
95 for(U32 i = 0; i < 2; ++i)
96 {
97 U32 encode_home = (1 << arr[i]->ctlbit.home);
98 if(arr[i]->ctlbit.home < pass && (common_overlap & encode_home))
99 {
100 return true;
101 }
102 }
103 return false;
104 }
105};
106
107template <typename Hash = Morton<uint32_t>>
109{
110 using Float = float;
111 using Vector3 = Eigen::Vector<Float, 3>;
112 using Vector3i = Eigen::Vector<int, 3>;
113 using Vector3u = Eigen::Vector<uint32_t, 3>;
114 using U32 = uint32_t;
115
116 public:
117 Float cell_size = 0.0f;
118 Vector3 coord_min = Vector3::Zero();
119
120 MUDA_GENERIC SpatialHashTableInfo() = default;
121
122 MUDA_GENERIC SpatialHashTableInfo(Float cell_size, const Vector3& coord_min)
123 : cell_size(cell_size)
124 , coord_min(coord_min)
125 {
126 }
127
128 MUDA_GENERIC U32 hash_cell(const Vector3& xyz) const
129 {
130 return hash_cell(cell(xyz));
131 }
132
133 MUDA_GENERIC U32 hash_cell(const Vector3u& ijk) const
134 {
135 return Hash()(ijk) % 0x40000000;
136 }
137
138 MUDA_GENERIC Vector3u cell(const Vector3& xyz) const
139 {
140 Vector3u ret;
141#pragma unroll
142 for(int i = 0; i < 3; ++i)
143 ret(i) = (xyz(i) - coord_min(i)) / cell_size;
144 return ret;
145 }
146 MUDA_GENERIC Vector3 coord(const Vector3u& ijk) const
147 {
148 Vector3 ret;
149#pragma unroll
150 for(int i = 0; i < 3; ++i)
151 ret(i) = ijk(i) * cell_size + coord_min(i);
152 return ret;
153 }
154
155 MUDA_GENERIC Vector3 cell_center_coord(const Vector3u& ijk) const
156 {
157 Vector3 ret;
158#pragma unroll
159 for(int i = 0; i < 3; ++i)
160 ret(i) = (ijk(i) + 0.5f) * cell_size + coord_min(i);
161 return ret;
162 }
163};
164
165namespace details
166{
167 template <typename Hash = Morton<uint32_t>>
169 {
170 public:
172 using U32 = uint32_t;
173 using I32 = int32_t;
174 using Vector3u = Eigen::Vector3<U32>;
175 using Vector3i = Eigen::Vector3<I32>;
176 using Vector3 = Eigen::Vector3f;
177
178 muda::Stream& m_stream;
179
181
182 DeviceVar<int> cellCount;
183 DeviceVar<int> pairCount;
184 DeviceVar<float> maxRadius;
185 DeviceVar<Vector3> minCoord;
186
187 DeviceVar<SpatialHashTableInfo<Hash>> spatialHashConfig;
188 SpatialHashTableInfo<Hash> h_spatialHashConfig;
189
191 DeviceBuffer<SpatialPartitionCell> cellArrayValueSorted;
192 DeviceBuffer<int> cellArrayKey;
193 DeviceBuffer<int> cellArrayKeySorted;
194
195 DeviceBuffer<int> uniqueKey;
196 DeviceVar<int> uniqueKeyCount;
197 int validCellCount;
198 int sum;
199 size_t pairListOffset = 0;
200
201 DeviceBuffer<int> objCountInCell;
202 DeviceBuffer<int> objCountInCellPrefixSum;
203
204 DeviceBuffer<int> collisionPairCount;
205 DeviceBuffer<int> collisionPairPrefixSum;
206
207 int level = 0;
208 bool empty_level = false;
209
210 //using Hash = Hash;
211 SparseSpatialHashImpl(muda::Stream& stream = muda::Stream::Default())
212 : m_stream(stream)
213 {
214 }
215
216 template <typename Pred>
217 void detect(CBufferView<BoundingSphere> boundingSphereList,
218 bool append,
219 DeviceBuffer<CollisionPair>& collisionPairs,
220 Pred&& pred);
221
222 DeviceBuffer<float> allRadius;
223 DeviceBuffer<Vector3> allCoords;
224 DeviceBuffer<int> cellToCollisionPairUpperBound;
225 DeviceBuffer<int> cellToCollisionPairUpperBoundPrefixSum;
226 DeviceBuffer<int> potentialCollisionPairIdToCellIndexBuffer;
227 DeviceBuffer<int> potentialCollisionPairIdToCellIndex;
228 DeviceBuffer<CollisionPair> collisionPairBuffer;
229 DeviceVar<int> validCollisionPairCount;
230
231 void calculate_hash_table_basic_info();
232
233 void setup_hash_table();
234
235 void fill_hash_cells();
236
237 void count_object_per_cell();
238
239 template <typename Pred>
240 void simple_setup_collision_pairs(Pred&& pred, DeviceBuffer<CollisionPair>& collisionPairs);
241
242 template <typename Pred>
243 void simple_count_collision_pairs(Pred&& pred);
244
245 void alloc_collision_pair_list(DeviceBuffer<CollisionPair>& collisionPairs,
246 int totalCollisionPairCount);
247
248 template <typename Pred>
249 void simple_fill_collision_pair_list(DeviceBuffer<CollisionPair>& collisionPairs,
250 Pred&& pred);
251
252 template <typename Pred>
253 void balanced_setup_collision_pairs(bool append,
254 DeviceBuffer<CollisionPair>& collisionPairs,
255 Pred&& pred);
256 };
257} // namespace details
258} // namespace muda::spatial_hash
259
260#include "details/sparse_spatial_hash_impl.inl"
Definition buffer_view.h:24
A std::vector like wrapper of cuda device memory, allows user to:
Definition device_buffer.h:46
Definition device_var.h:11
RAII wrapper for cudaStream.
Definition stream.h:18
Definition sparse_spatial_hash_impl.h:109
To represent a cell-object pair in the spatial hash 3D grid e.g. (cell_id,object_id) = (1024,...
Definition sparse_spatial_hash_impl.h:16
Definition sparse_spatial_hash_impl.h:169
A light-weight wrapper of cuda device memory. Like std::vector, allow user to resize,...
cuda kernel launch in muda style.
A frequently used parallel for loop, DynamicBlockDim and GridStrideLoop strategy are provided,...