AGX Dynamics 2.42.3.0
Loading...
Searching...
No Matches
Components/agx/Physics/HierarchicalGrid/Util.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#ifndef AGX_PHYSISCS_HIERARCHICAL_GRID_UTIL_H
18#define AGX_PHYSISCS_HIERARCHICAL_GRID_UTIL_H
19
20// #include <agx/Physics/HierarchicalGrid/ContactZoneEntity.h>
21
22#include <agx/Vec3.h>
23#include <agx/Vec2.h>
24#include <agx/Math.h>
25#include <agx/debug.h>
26#include <agxData/LocalVector.h>
28
29
30#define NUM_ITERATION_ZONE_JOBS 2
31
32namespace agx { namespace Physics { namespace HierarchicalGrid {
33
90
95
96
100
106
110 AGXPHYSICS_EXPORT bool isNeighborOffset(const Vec3i& offset);
111 AGXPHYSICS_EXPORT bool isNeighborOffset(const Vec2i& offset);
112
116 AGXPHYSICS_EXPORT Index getParentCell(CellData& cell, Index cellIndex, UInt level);
117
121 AGXPHYSICS_EXPORT Index alignCellTiers(CellData& cell, Index tier1, Index tier2, Index& cellIndex1, Index& cellIndex2);
122
126 AGXPHYSICS_EXPORT UInt8 calculateZoneType(Vec3i id, UInt tierAccumulation);
127
136 {
141 };
142
147
152
153
158
159
163 AGXPHYSICS_EXPORT Vec3i calculateBoundaryZoneId(CellData& cell, Index cellIndex1, Index cellIndex2, UInt tierAccumulation);
164
165
167 {
170 };
171
172
174 AGXPHYSICS_EXPORT const UInt8 *getNeighborPathOrderTable(size_t childIndex);
175
176
177 template <typename ZoneDataT>
178 UInt countNumContacts(ZoneDataT& contactZone, Index zoneIndex)
179 {
180 return contactZone.particleParticleContacts[zoneIndex].size() +
181 contactZone.particleGeometryContacts[zoneIndex].size() +
182 contactZone.geometryGeometryContacts[zoneIndex].size();
183 }
184
185 template <typename ZonePtrT>
186 UInt countNumContacts(ZonePtrT zone)
187 {
188 agxData::EntityStorage *storage = zone.getStorage();
189 return countNumContacts(*storage->getData<typename ZonePtrT::DataType>(), zone.calculateIndex());
190 }
191
192
193
194
195
196 /* Implementation */
198 extern const Vec3i __private_neighborTable[];
199 extern const Vec2i __private_neighborTable_2D[];
200
203
205 {
206 agxAssert(index < 27);
207 return __private_neighborTable[index];
208 }
209
211 {
212 agxAssert(index < 9);
213 return __private_neighborTable_2D[index];
214 }
215
217
219 {
221 Vec3i shiftedOffset = offset + 1;
222 Index neighborIndex = (Index)((shiftedOffset[0] * 9) + (shiftedOffset[1] * 3) + shiftedOffset[2]);
223 agxAssert(getNeighborOffset(neighborIndex) == offset);
224 return neighborIndex;
225 }
226
228 {
230 Vec2i shiftedOffset = offset + 1;
231 Index neighborIndex = (Index)((shiftedOffset[0] * 2) + shiftedOffset[1]);
232 agxAssert(getNeighborOffset2d(neighborIndex) == offset);
233 return neighborIndex;
234 }
235
237
239 {
240 return (UInt)(offset[0]+1) <= 2 && (UInt)(offset[1]+1) <= 2 && (UInt)(offset[2]+1) <= 2;
241 }
242
244 {
245 return (UInt)(offset[0]+1) <= 2 && (UInt)(offset[1]+1) <= 2;
246 }
247
249
250 AGX_FORCE_INLINE Index getParentCell(CellData& cell, Index cellIndex, UInt level)
251 {
252 for (UInt i = 0; i < level; ++i)
253 {
254 if (cell.parent[cellIndex] == InvalidIndex)
255 break;
256
257 cellIndex = cell.parent[cellIndex];
258 }
259
260 return cellIndex;
261 }
262
263 /*
264 If the particles belong to different tiers, use the lower tier
265 */
266 AGX_FORCE_INLINE Index alignCellTiers(CellData& cell, Index tier1, Index tier2, Index& cellIndex1, Index& cellIndex2)
267 {
268 Index minCellIndex = InvalidIndex;
269
270 if (tier1 > tier2)
271 {
272 minCellIndex = cellIndex1;
273 cellIndex1 = getParentCell(cell, cellIndex1, tier1 - tier2);
274 }
275 else
276 {
277 minCellIndex = cellIndex2;
278 cellIndex2 = getParentCell(cell, cellIndex2, tier2 - tier1);
279 }
280
281 return minCellIndex;
282 }
283
284
285 // Generate a bitmask with numBits LSB bits set
287 {
288 return (UInt(1) << numBits) - UInt(1);
289 }
290
291
292
294 {
295 agxAssert(zoneType < 27);
296 return __private_categoryTable[zoneType];
297 }
298
300 {
301 Vec3i offset = Vec3i(zoneId[0] & 0x1, zoneId[1] & 0x1, zoneId[2] & 0x1);
303 }
304
305
306 AGX_FORCE_INLINE Vec3i calculateBoundaryZoneId(CellData& cell, Index cellIndex1, Index cellIndex2, UInt tierAccumulation)
307 {
308 ZoneCategory zoneType1 = getZoneCategory(cell.zoneType[cellIndex1]);
309 ZoneCategory zoneType2 = getZoneCategory(cell.zoneType[cellIndex2]);
310
311 // Extended zones, using the dominant zone type
312 Index dominantCellIndex = zoneType1 > zoneType2 ? cellIndex1 : cellIndex2;
313
314 Vec3i zoneId1 = cell.id[dominantCellIndex];
315 Vec3i zoneId2 = cell.id[dominantCellIndex] + getNeighborOffset(cell.zoneType[dominantCellIndex]);
316
317 zoneId1[0] >>= tierAccumulation;
318 zoneId1[1] >>= tierAccumulation;
319 zoneId1[2] >>= tierAccumulation;
320
321 zoneId2[0] >>= tierAccumulation;
322 zoneId2[1] >>= tierAccumulation;
323 zoneId2[2] >>= tierAccumulation;
324
325 Vec3i boundaryId = zoneId1 + zoneId2;
326
327 // std::cout << "dominant: " << getZoneCategoryName(foo1) << ", extended: " << getZoneCategoryName(foo2) << std::endl;
328 // std::cout << "zone: " << getZoneCategoryName(calculateZoneCategory(boundaryId)) << std::endl;
329
330
332
333 UInt cornerShift = UInt(1) << (tierAccumulation-1);
334 Vec3i cornerId1 = cell.id[cellIndex1] + cornerShift;
335 Vec3i cornerId2 = cell.id[cellIndex2] + cornerShift;
336
337 cornerId1[0] >>= tierAccumulation;
338 cornerId1[1] >>= tierAccumulation;
339 cornerId1[2] >>= tierAccumulation;
340
341 cornerId2[0] >>= tierAccumulation;
342 cornerId2[1] >>= tierAccumulation;
343 cornerId2[2] >>= tierAccumulation;
344
345 if (cornerId1 == cornerId2)
346 {
347 // std::cout << "boundaryId: " << boundaryId << ", extended corner: " << (cornerId1 + cornerId2 - 1) << std::endl;
348 return cornerId1 + cornerId2 - 1;
349 }
350 else
351 {
352 return boundaryId;
353 }
354
355#if 0
357
358 Vec3i offset = cell.id[cellIndex1] - cell.id[cellIndex2];
359
360 if ((offset[0] & offset[1] & offset[2] & 0x1) && zoneType1 == ZONE_EDGE && zoneType2 == ZONE_EDGE && cell.zoneType[cellIndex1] != cell.zoneType[cellIndex2] * -1)
361 {
362 std::cout << "detected special edge/edge diagonal, cell1: " << cell.id[cellIndex1] << ", cell2: " << cell.id[cellIndex2] << std::endl;
363
364 const Vec3i& dir1 = getNeighborOffset(cell.zoneType[cellIndex1]);
365 const Vec3i& dir2 = getNeighborOffset(cell.zoneType[cellIndex2]);
366
367 Vec3i cornerId1 = cell.id[cellIndex1] + dir1 + dir2;
368 Vec3i cornerId2 = cell.id[cellIndex2] + dir1 + dir2;
369
370 // agxAssert(getZoneCategory(calculateZoneType(cornerId1, tierAccumulation)) == ZONE_CORNER);
371 // agxAssert(getZoneCategory(calculateZoneType(cornerId2, tierAccumulation)) == ZONE_CORNER);
372
373 cornerId1[0] >>= tierAccumulation;
374 cornerId1[1] >>= tierAccumulation;
375 cornerId1[2] >>= tierAccumulation;
376
377 cornerId2[0] >>= tierAccumulation;
378 cornerId2[1] >>= tierAccumulation;
379 cornerId2[2] >>= tierAccumulation;
380
381 return cornerId1 + cornerId2;
382 }
383
384 // if (zoneType1 <= ZONE_FACE || zoneType2 <= ZONE_FACE)
385 if (false)
386 {
387 Index parentIndex1 = getParentCell(cell, cellIndex1, tierAccumulation);
388 Index parentIndex2 = getParentCell(cell, cellIndex2, tierAccumulation);
389 return cell.id[parentIndex1] + cell.id[parentIndex2];
390 }
392
393 return boundaryId;
394#endif
395 }
396
398 {
399 Int mask = (Int)generateBitMask(tierAccumulation);
400
401 id[0] &= mask;
402 id[1] &= mask;
403 id[2] &= mask;
404
405 UInt zoneType = 0;
406 zoneType += (id[0] == mask ? 18 : (id[0] == 0 ? 0 : 9));
407 zoneType += (id[1] == mask ? 6 : (id[1] == 0 ? 0 : 3));
408 zoneType += (id[2] == mask ? 2 : (id[2] == 0 ? 0 : 1));
409
410 agxAssert(zoneType < 27);
411 return (UInt8)zoneType;
412 }
413
414
416
417 AGXPHYSICS_EXPORT extern NeighborCellPath __private_NeighborPathTable[8][32];
419
421 {
422 agxAssert(childIndex < 8);
423 if (childIndex < 8)
424 return __private_NeighborPathTable[childIndex];
425 else
426 return nullptr;
427 }
428
430 {
431 agxAssert(childIndex < 8);
432 if (childIndex < 8)
433 return __private_NeighborPathOrderTable[childIndex];
434 else
435 return nullptr;
436 }
437
438
439}}}
440
441
442#endif /* AGX_PHYSISCS_HIERARCHICAL_GRID_UTIL_H */
#define AGXPHYSICS_EXPORT
Data storage for a collection of entity instances of a specified EntityModel.
Definition: EntityStorage.h:73
agxData::EntityData * getData()
#define agxAssert(expr)
Definition: debug.h:143
#define AGX_FORCE_INLINE
Definition: macros.h:58
AGXPHYSICS_EXPORT const char * getZoneCategoryName(Index category)
AGXPHYSICS_EXPORT NeighborCellPath __private_NeighborPathTable[8][32]
AGXPHYSICS_EXPORT bool isNeighborOffset(const Vec3i &offset)
AGXPHYSICS_EXPORT ZoneCategory calculateZoneCategory(const Vec3i &zoneId)
const Vec3i __private_neighborTable[]
AGXPHYSICS_EXPORT Index alignCellTiers(CellData &cell, Index tier1, Index tier2, Index &cellIndex1, Index &cellIndex2)
Align cell indices to the same tier.
UInt countNumContacts(ZoneDataT &contactZone, Index zoneIndex)
AGXPHYSICS_EXPORT Index calculateNeighborIndex(const Vec3i &offset)
AGXPHYSICS_EXPORT UInt8 calculateZoneType(Vec3i id, UInt tierAccumulation)
Calculates which one of the 27 internal zones the cell is part of.
AGXPHYSICS_EXPORT const UInt8 * getNeighborPathOrderTable(size_t childIndex)
const ZoneCategory __private_categoryTable[]
AGXPHYSICS_EXPORT UInt8 __private_NeighborPathOrderTable[8][32]
AGXPHYSICS_EXPORT ZoneCategory getZoneCategory(Index zoneType)
AGXPHYSICS_EXPORT const NeighborCellPath * getNeighborPathTable(size_t childIndex)
AGXPHYSICS_EXPORT Vec3i calculateBoundaryZoneId(CellData &cell, Index cellIndex1, Index cellIndex2, UInt tierAccumulation)
Corners and edges are extended to make all edges independent of each other, and the same for all face...
AGXPHYSICS_EXPORT const Vec2i & getNeighborOffset2d(Index index)
ZoneCategory
The 27 internal zones are following categories (box features) and counts: Internal: 1 Face: 6 Edge: 1...
AGXPHYSICS_EXPORT Index getParentCell(CellData &cell, Index cellIndex, UInt level)
Return the parent cell N tiers above the specified cell.
AGXPHYSICS_EXPORT const Vec3i & getNeighborOffset(Index index)
The following ordering of neighbor coordinates is used for all cell/zone interactions.
const Vec2i __private_neighborTable_2D[]
The agx namespace contains the dynamics/math part of the AGX Dynamics API.
Vec2T< Int > Vec2i
Definition: Vec2.h:40
uint64_t UInt
Definition: Integer.h:27
Vec3T< Int > Vec3i
Definition: agx/Vec3.h:43
uint8_t UInt8
Definition: Integer.h:30
AGXCORE_EXPORT const InvalidIndexStruct InvalidIndex
int64_t Int
Definition: Integer.h:28
UInt32 Index
Definition: Integer.h:44