AGX Dynamics 2.42.3.0
Loading...
Searching...
No Matches
CreateCell.h
Go to the documentation of this file.
1/*
2Copyright 2007-2025. Algoryx Simulation AB.
3
4All AGX source code, intellectual property, documentation, sample code,
5tutorials, scene files and technical white papers, are copyrighted, proprietary
6and confidential material of Algoryx Simulation AB. You may not download, read,
7store, distribute, publish, copy or otherwise disseminate, use or expose this
8material unless having a written signed agreement with Algoryx Simulation AB, or having been
9advised so by Algoryx Simulation AB for a time limited evaluation, or having purchased a
10valid commercial license from Algoryx Simulation AB.
11
12Algoryx Simulation AB disclaims all responsibilities for loss or damage caused
13from using this software, unless otherwise stated in written agreements with
14Algoryx Simulation AB.
15*/
16
17
18#ifndef AGX_CREATE_CELL_H
19#define AGX_CREATE_CELL_H
20
21#include <agx/Morton.h>
22#include <agx/Prefetch.h>
23
24#include "Common.h"
25#include "Util.h"
26#include "SolveBodyManager.h"
27
28
29namespace agx
30{
31
32 //-----------------------------------------------------------------------------------------------------
33
34 // Forward declarations
35 template <typename GridTierDataT, typename CellDataT, typename CellT, typename CellIdT, typename CellPosT, typename GridCellTableT, size_t NumNeighbors>
37 (
40 Index cellIndex,
41 UInt8 tier,
42 const CellIdT cellId, // NOTE: Must be copy, not reference, can get invalid buffer read otherwise, see #2182
43 GridTierDataT& gridTier,
44 CellDataT& cell,
45 agxData::Array< CellT >& rootCells,
46 const CellIdT *NeighborTable,
47 agx::Bool& hasNewTiers,
48 Physics::HierarchicalGrid::SolveBodyManager* solveBodyManager,
49 const agx::UInt& contactZoneAccumulationLevel
50
51 );
52
53 template <typename CellDataT, typename CellIdT>
55 (
56 Index cellIndex,
57 const CellIdT cellId, // NOTE: Must be copy, not reference, can get invalid buffer read otherwise, see #2182
58 Index parentCellIndex,
59 CellDataT& cell,
60 Physics::HierarchicalGrid::SolveBodyManager* solveBodyManager,
61 const agx::UInt& contactZoneAccumulationLevel
62 );
63
64
65
66 template <typename GridTierDataT, typename CellDataT, typename CellT, typename CellIdT, typename CellPosT, typename GridCellTableT, size_t NumNeighbors>
68 (
69 Real minCellSize,
72 GridTierDataT& gridTier,
73 CellDataT& cell,
74 agxData::Array< CellT >& rootCells,
75 const CellIdT *NeighborTable,
76 agx::Bool& hasNewTiers,
77 Physics::HierarchicalGrid::SolveBodyManager* solveBodyManager,
78 const agx::UInt& contactZoneAccumulationLevel
79 );
80
81
82 //-----------------------------------------------------------------------------------------------------
83
87 template <typename GridTierDataT, typename CellDataT, typename CellT, typename CellIdT, typename CellPosT, typename GridCellTableT, size_t NumNeighbors>
89 (
92 UInt8 tier,
93 const CellIdT cellId,
94 GridTierDataT& gridTier,
95 CellDataT& cell,
96 agxData::Array< CellT >& rootCells,
97 const CellIdT *NeighborTable,
98 agx::Bool& hasNewTiers,
100 const agx::UInt& contactZoneAccumulationLevel
101 )
102 {
103 UInt32 parentCellIndex = InvalidIndex;
104
105 if (tier > 0)
106 {
107 // Make sure parent cell is available, we want big tier cells first in list of new cells for better performance in InitializedNewCells kernel
108 UInt8 parentTier = (UInt8)(tier - 1);
109 CellIdT parentId = calculateParentCellId(cellId);
110
111 GridCellTableT& parentTierTable = *gridTier.cellTable[ parentTier ];
112 parentCellIndex = parentTierTable.find( parentId );
113
114 // Create parent cell if needed (recursive)
115 if ( parentCellIndex == InvalidIndex )
116 {
117 size_t oldNumTiers = gridTier.cellTable.size();
118
119 parentCellIndex = createCell
120 <
121 GridTierDataT, CellDataT, CellT, CellIdT, CellPosT, GridCellTableT, NumNeighbors
122 >
123 (
124 deadCells, emptyZones, parentTier, parentId, gridTier, cell,
125 rootCells, NeighborTable, hasNewTiers, solveBodyManager,
126 contactZoneAccumulationLevel
127 );
128
129 // Important: update current tier
130 tier = agx::UInt8(tier + (gridTier.numElements() - oldNumTiers));
131 }
132 }
133
134 UInt32 cellIndex = InvalidIndex;
135
136
137 // Check if we have a dead cell to use
138 if (!deadCells.empty())
139 {
140 cellIndex = deadCells.back();
141 deadCells.range().end()--;
142 // std::cout << "Reusing dead cell " << cellIndex << " at index " << deadCells.size() << std::endl;
143
144 // Must explicitly initialize parameters when reusing an old cell
145 cell.parent[cellIndex] = InvalidIndex;
146 cell.numChildren[cellIndex] = 0;
147 cell.invDepth[cellIndex] = 0;
148 }
149 else
150 {
151 cellIndex = cell.createInstance();
152 }
153
154
155
156 cell.tier[ cellIndex ] = tier;
157 cell.id[ cellIndex ] = cellId;
158 cell.state[ cellIndex ] = CELL_UNINITIALIZED;
159
160 GridCellTableT& cellTable = *gridTier.cellTable[ tier ];
161 agxAssert( cellTable.find( cellId ) == InvalidIndex );
162 cellTable.insert(cellId, cellIndex);
163
164 // std::cout << cellIndex << ": Creating cell " << cellId << " in tier " << (UInt)tier << " with parent " << parentCellIndex << std::endl;
165
166 if ( tier > 0 )
167 {
168 connectToParentCell<CellDataT, CellIdT>(cellIndex, cellId, parentCellIndex, cell, solveBodyManager, contactZoneAccumulationLevel);
169 }
170 else // Special handling of root cell
171 {
178 UInt rootIndex = calculateRootCellIndex(cellId);
179 // std::cout << "Creating root " << cellId << ", cellIndex: " << cellIndex << ", cell size: " << gridTier.size[tier] << std::endl;
180 solveBodyManager->registerCell(cell.instance[cellIndex]);
181
182 if (!rootCells[rootIndex])
183 {
185 rootCells[rootIndex] = root;
186
187 // Set up neighbor connections to other root cells, including self
188 UInt32 *neighborList = &cell.neighbors[CellDataT::neighborsArraySize * cellIndex];
189
190 for (size_t i = 0; i < NumNeighbors; ++i)
191 neighborList[i] = InvalidIndex;
192
193 for (size_t i = 0; i < rootCells.size(); ++i)
194 {
195 if (!rootCells[i])
196 continue;
197
198 UInt32 otherIndex = rootCells[i].calculateIndex();
199
200 CellIdT offset = cell.id[otherIndex] - cellId;
202 {
204 neighborList[localNeighborIndex] = otherIndex;
205
206 UInt32 *reverseList = &cell.neighbors[CellDataT::neighborsArraySize * otherIndex];
207 reverseList[ NumNeighbors-1-localNeighborIndex ] = cellIndex;
208 }
209 }
210 }
211 else
212 {
213 // Remove current root cells
214 for (size_t i = 0; i < rootCells.size(); ++i)
215 rootCells[i] = agxData::EntityPtr();
216
217 // Create new top tier
219 <
220 GridTierDataT, CellDataT, CellT, CellIdT, CellPosT, GridCellTableT, NumNeighbors
221 >
222 (
223 gridTier.size[0] * Real(2),
224 deadCells,
225 emptyZones,
226 gridTier,
227 cell,
228 rootCells,
229 NeighborTable,
230 hasNewTiers,
231 solveBodyManager,
232 contactZoneAccumulationLevel
233 );
234 }
235
236 }
237
238 return cellIndex;
239 }
240
241
242 template <typename CellDataT, typename CellIdT>
244 (
245 Index cellIndex,
246 const CellIdT cellId,
247 Index parentCellIndex,
248 CellDataT& cell,
250 const agx::UInt& contactZoneAccumulationLevel
251 )
252 {
253 // Connect both ways
254 // std::cout << "Connecting " << cellIndex << " with parent " << parentCellIndex << std::endl;
255 agxAssert(parentCellIndex != InvalidIndex);
256 cell.parent[ cellIndex ] = (UInt32)parentCellIndex;
257 UInt32 *childList = &cell.children[CellDataT::childrenArraySize * parentCellIndex];
258 UInt childIndex = calculateCellChildIndex(cellId);
259
260 const UInt numChildren = cell.numChildren[ parentCellIndex ];
261 UInt compactedIndex = 0;
262 for (; compactedIndex < numChildren; ++compactedIndex)
263 {
264 if (childIndex < childList[ compactedIndex ])
265 break;
266 }
267
268 for (UInt n = numChildren; n > compactedIndex; --n)
269 childList[n] = childList[n-1];
270
271 childList[compactedIndex] = (UInt32)cellIndex;
272
273 cell.numChildren[ parentCellIndex ]++;
274 agxAssert(cell.numChildren[parentCellIndex] <= CellDataT::childrenArraySize);
275
276 // Update inv depth of parents if parent was a leaf node
277 if (numChildren == 0)
278 {
279 UInt8 invDepth = cell.invDepth[cellIndex];
280
281 while (parentCellIndex != InvalidIndex && cell.invDepth[parentCellIndex] <= invDepth)
282 {
283 // std::cout << "cell " << cell.indexToId(parentCellIndex) << ", id: " << cell.id[parentCellIndex] << ", tier: " << (UInt)cell.tier[parentCellIndex] << " now has inv depth " << (UInt)(invDepth + 1) << std::endl;
284 cell.invDepth[parentCellIndex] = ++invDepth;
285
286 if ( (invDepth >= contactZoneAccumulationLevel || cell.tier[parentCellIndex] <= contactZoneAccumulationLevel) && !cell.solveBodyOffsets[parentCellIndex])
287 solveBodyManager->registerCell(cell.instance[parentCellIndex]);
288
289 parentCellIndex = cell.parent[parentCellIndex];
290 }
291 }
292 }
293
294
295 template <typename GridTierDataT, typename CellDataT, typename CellT, typename CellIdT, typename CellPosT, typename GridCellTableT, size_t NumNeighbors>
297 (
300 Index cellIndex,
301 UInt8 tier,
302 const CellIdT cellId,
303 GridTierDataT& gridTier,
304 CellDataT& cell,
305 agxData::Array< CellT >& rootCells,
306 const CellIdT *NeighborTable,
307 agx::Bool& hasNewTiers,
309 const agx::UInt& contactZoneAccumulationLevel
310 )
311 {
312 UInt8 parentTier = UInt8(tier - 1);
313 CellIdT parentId = calculateParentCellId(cellId);
314
315 GridCellTableT& parentTierTable = *gridTier.cellTable[ parentTier ];
316 UInt32 parentCellIndex = parentTierTable.find( parentId );
317
318 // Create parent cell if needed (recursive)
319 if ( parentCellIndex == InvalidIndex )
320 {
321 parentCellIndex = createCell
322 <
323 GridTierDataT, CellDataT, CellT, CellIdT, CellPosT, GridCellTableT, NumNeighbors
324 >
325 (
326 deadCells, emptyZones, parentTier, parentId, gridTier, cell,
327 rootCells, NeighborTable, hasNewTiers, solveBodyManager,
328 contactZoneAccumulationLevel
329 );
330
331 }
332
333 connectToParentCell<CellDataT, CellIdT>(cellIndex, cellId, parentCellIndex, cell, solveBodyManager, contactZoneAccumulationLevel);
334
335 return parentCellIndex;
336 }
337
338}
339
340#endif
agx::IndexRange32 & range()
Definition: Buffer.h:721
size_t size() const
Definition: Buffer.h:708
bool empty() const
Definition: Buffer.h:713
Type-specific Array used for fast access into the data held by a Buffer.
Definition: Array.h:107
T & back()
Definition: Buffer.h:820
Accessor to a entity instance stored in a EntityStorage, to allow SOA (structure of arrays) data to b...
Definition: EntityPtr.h:52
static EntityPtr createWithIndex(EntityStorage *storage, agx::Index index)
Pointer to a entity instance of type Physics.HierarchicalGrid.Cell.
Definition: CellEntity.h:250
#define agxAssert(expr)
Definition: debug.h:143
#define AGX_FORCE_INLINE
Definition: macros.h:58
AGXPHYSICS_EXPORT bool isNeighborOffset(const Vec3i &offset)
AGXPHYSICS_EXPORT Index calculateNeighborIndex(const Vec3i &offset)
The agx namespace contains the dynamics/math part of the AGX Dynamics API.
UInt32 createCell(agxData::Array< agx::UInt32 > &deadCells, agxData::Array< Physics::HierarchicalGrid::ContactZonePtr > &emptyZones, UInt8 tier, const CellIdT cellId, GridTierDataT &gridTier, CellDataT &cell, agxData::Array< CellT > &rootCells, const CellIdT *NeighborTable, agx::Bool &hasNewTiers, Physics::HierarchicalGrid::SolveBodyManager *solveBodyManager, const agx::UInt &contactZoneAccumulationLevel)
Create and connect a cell.
Definition: CreateCell.h:89
UInt32 connectToParentCell(agxData::Array< agx::UInt32 > &deadCells, agxData::Array< Physics::HierarchicalGrid::ContactZonePtr > &emptyZones, Index cellIndex, UInt8 tier, const CellIdT cellId, GridTierDataT &gridTier, CellDataT &cell, agxData::Array< CellT > &rootCells, const CellIdT *NeighborTable, agx::Bool &hasNewTiers, Physics::HierarchicalGrid::SolveBodyManager *solveBodyManager, const agx::UInt &contactZoneAccumulationLevel)
Definition: CreateCell.h:297
uint32_t UInt32
Definition: Integer.h:32
bool Bool
Definition: Integer.h:40
uint64_t UInt
Definition: Integer.h:27
double Real
Definition: Real.h:41
UInt calculateRootCellIndex(const Vec3i &cellId)
uint8_t UInt8
Definition: Integer.h:30
AGXCORE_EXPORT const InvalidIndexStruct InvalidIndex
UInt calculateCellChildIndex(const Vec3i &cellId)
size_t createMissingTiers(Real minCellSize, agxData::Array< agx::UInt32 > &deadCells, agxData::Array< Physics::HierarchicalGrid::ContactZonePtr > &emptyZones, GridTierDataT &gridTier, CellDataT &cell, agxData::Array< CellT > &rootCells, const CellIdT *NeighborTable, agx::Bool &hasNewTiers, Physics::HierarchicalGrid::SolveBodyManager *solveBodyManager, const agx::UInt &contactZoneAccumulationLevel)
Definition: CreateTier.h:95
AGXCORE_EXPORT Component * root()
Vec3i calculateParentCellId(const Vec3i &cellId)
UInt32 Index
Definition: Integer.h:44