17#ifndef AGX_CREATETIER_H
18#define AGX_CREATETIER_H
25 template <
typename Gr
idCellTableT>
36 template <
typename Gr
idCellTableT>
46 Real halfSize = tierSize *
Real(0.5);
47 return std::sqrt(halfSize * halfSize *
Real(3)) + halfSize;
53 Real halfSize = tierSize *
Real(0.5);
54 return std::sqrt(halfSize * halfSize *
Real(2)) + halfSize;
57 template <
typename Gr
idTierDataT,
typename Gr
idCellTableT>
63 GridTierDataT& gridTier
66 gridTier.getStorage()->createInstance();
67 gridTier.size[ tier ] = tierSize;
68 gridTier.invSize[ tier ] =
Real(1.0) / tierSize;
69 gridTier.boundingRadius[ tier ] = (
Real32)calculateBoundingRadius<GridCellTableT>(tierSize);
70 gridTier.cellTable[ tier ] =
new GridCellTableT(cellIdBuffer);
78 if (value > alignment)
81 Real alignedSize = alignment * (
Real)multiplier;
82 if (alignedSize < value)
89 return align(value, alignment/2);
93 template <
typename Gr
idTierDataT,
typename CellDataT,
typename CellT,
typename CellIdT,
typename CellPosT,
typename Gr
idCellTableT,
size_t NumNeighbors>
99 GridTierDataT& gridTier,
102 const CellIdT *NeighborTable,
105 const agx::UInt& contactZoneAccumulationLevel
110 size_t numTiers = gridTier.numElements();
114 if (cell.sizeAlignment > 0)
116 Real alignedSize =
align(minCellSize, cell.sizeAlignment);
117 UInt multiplier = (
UInt)round(alignedSize > cell.sizeAlignment ? alignedSize/cell.sizeAlignment : cell.sizeAlignment/alignedSize);
120 minCellSize = alignedSize;
125 createTier<GridTierDataT, GridCellTableT>(tier, minCellSize, cell.id.buffer(), gridTier);
127 else if (
Real(2.0)*minCellSize <= gridTier.size[ numTiers-1 ] )
132 Real currentTierSize = gridTier.size[ tier ];
135 while(
Real(2.0)*minCellSize <= currentTierSize )
138 currentTierSize =
Real(0.5)*gridTier.size[ tier - 1 ];
139 createTier<GridTierDataT, GridCellTableT>(tier, currentTierSize, cell.id.buffer(), gridTier);
142 numTiers = gridTier.numElements();
144 else if ( minCellSize > gridTier.size[0] )
147 Real currentTierSize = gridTier.size[ 0 ];
151 while ( minCellSize > currentTierSize )
153 currentTierSize *=
Real(2.0);
158 GridCellTableT& rootTierTable = *gridTier.cellTable[0];
161 size_t numNewTiers = newTiers.
size();
162 agxVerify1( numNewTiers > 0,
"Expected at least one tier to be created. Why wasn't it?" );
163 gridTier.getStorage()->createInstances( numNewTiers );
164 size_t tierOffset = gridTier.numElements();
170 for (
Int n = (
Int)numTiers-1 ; n >= 0 ; --n )
172 size_t newTierIndex = n + numNewTiers;
173 gridTier.size[ newTierIndex ] = gridTier.size[ n ];
174 gridTier.invSize[ newTierIndex ] = gridTier.invSize[ n ];
175 gridTier.boundingRadius[ newTierIndex ] = gridTier.boundingRadius[ n ];
176 gridTier.cellTable[ newTierIndex ] = gridTier.cellTable[ n ];
177 gridTier.zoneTable[ newTierIndex ] = gridTier.zoneTable[ n ];
178 gridTier.instance[ newTierIndex ].swapId(gridTier.instance[ n ]);
184 for (
size_t newTierIndex = 0; newTierIndex < newTiers.
size(); ++newTierIndex )
186 size_t destIndex = numNewTiers - newTierIndex - 1;
187 gridTier.size[ destIndex ] = newTiers[ newTierIndex ].cellSize;
188 gridTier.invSize[ destIndex ] =
Real(1.0) / newTiers[ newTierIndex ].cellSize;
189 gridTier.boundingRadius[ destIndex ] = (
Real32)calculateBoundingRadius<GridCellTableT>(gridTier.size[ destIndex ]);
190 gridTier.cellTable[ destIndex ] =
new GridCellTableT(cell.id.buffer());
199 for (
size_t n = 0 ; n < cell.numElements() ; ++n )
203 cell.tier[ n ] =
agx::UInt8(cell.tier[n] + numNewTiers);
212 auto& internalZone = cell.internalZone[n];
215 UInt zoneTierOffset = internalZone.tier().calculateIndex() - cell.tier[n];
217 if (zoneTierOffset != contactZoneAccumulationLevel) {
219 invalidatedZones.
push_back(internalZone);
220 internalZone.invalidate();
225 if (!invalidatedZones.
empty()) {
229 for(
auto&& zone : emptyZones) {
230 uniqueEmptyZones.
insert(zone);
233 auto oldSize = emptyZones.buffer()->size();
234 size_t numNewEmpty = 0;
235 emptyZones.buffer()->resize(oldSize + invalidatedZones.
size());
238 for(
auto&& zone : invalidatedZones) {
239 if (!uniqueEmptyZones.
contains(zone)) {
240 emptyZones[oldSize + numNewEmpty] = zone;
246 emptyZones.buffer()->resize(oldSize + numNewEmpty);
251 for (
typename GridCellTableT::iterator it = rootTierTable.begin(); it != rootTierTable.end(); ++it)
255 connectToParentCell<GridTierDataT, CellDataT, CellT, CellIdT, CellPosT, GridCellTableT, NumNeighbors>
260 cell.tier[ oldRootCell ],
261 cell.id[ oldRootCell ],
267 contactZoneAccumulationLevel
272 tier = gridTier.numElements() - tierOffset;
276 agxAbort1(
"The appropriate tier for a particle doesn't exist, but the current tier range is neither too large nor too small. Precision problems perhaps?");
Type-specific Array used for fast access into the data held by a Buffer.
Abstract representation of a data buffer.
bool contains(const KeyT &key) const
Boolean query to test existence of an element.
insert_iterator insert(const KeyT &key)
Insert an element, overwriting if key already exists.
Inheritance with partial specialization due to bug with ref_ptr containers.
void push_back(const T2 &value)
#define agxVerify1(expr, msg)
The agx namespace contains the dynamics/math part of the AGX Dynamics API.
bool isPowerOfTwo(T value)
agx::HashTable< Vec3i, agx::Physics::HierarchicalGrid::ContactZonePtr > ContactZoneTable
static Real align(Real value, Real alignment)
Real calculateBoundingRadius< agx::GridCell2DTable >(Real tierSize)
Real calculateBoundingRadius(Real)
UInt32 alignPowerOfTwo(UInt32 value)
Real calculateBoundingRadius< agx::GridCellTable >(Real tierSize)
AGXCORE_EXPORT const InvalidIndexStruct InvalidIndex
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)
void createTier(size_t tier, Real tierSize, agxData::Buffer *cellIdBuffer, GridTierDataT &gridTier)
GridCellTableT * cellTable
GridTier(Real cellSize, GridCellTableT *cellTable)