52 const int kUnassignedBatch = -1;
55 for (
int iPhase = 0; iPhase <
m_phases.size(); ++iPhase)
58 bodyBatchId.
resize(bodies.
size(), kUnassignedBatch);
60 for (
int iBatch = phase.
begin; iBatch < phase.
end; ++iBatch)
63 for (
int iiCons =
batch.begin; iiCons <
batch.end; ++iiCons)
67 const btSolverBody& bodyA = bodies[cons.m_solverBodyIdA];
68 const btSolverBody& bodyB = bodies[cons.m_solverBodyIdB];
69 if (!bodyA.internalGetInvMass().isZero())
71 int thisBodyBatchId = bodyBatchId[cons.m_solverBodyIdA];
72 if (thisBodyBatchId == kUnassignedBatch)
74 bodyBatchId[cons.m_solverBodyIdA] = iBatch;
76 else if (thisBodyBatchId != iBatch)
78 btAssert(!
"dynamic body is used in 2 different batches in the same phase");
82 if (!bodyB.internalGetInvMass().isZero())
84 int thisBodyBatchId = bodyBatchId[cons.m_solverBodyIdB];
85 if (thisBodyBatchId == kUnassignedBatch)
87 bodyBatchId[cons.m_solverBodyIdB] = iBatch;
89 else if (thisBodyBatchId != iBatch)
91 btAssert(!
"dynamic body is used in 2 different batches in the same phase");
105 const btVector3& color,
106 const btVector3& offset)
108 if (bc && bc->
m_debugDrawer && iBatch < bc->m_batches.size())
111 for (
int iiCon =
b.begin; iiCon <
b.end; ++iiCon)
115 int iBody0 = con.m_solverBodyIdA;
116 int iBody1 = con.m_solverBodyIdB;
117 btVector3 pos0 = bodies[iBody0].getWorldTransform().getOrigin() + offset;
118 btVector3 pos1 = bodies[iBody1].getWorldTransform().getOrigin() + offset;
128 const btVector3& color0,
129 const btVector3& color1,
130 const btVector3& offset)
136 for (
int iBatch = phase.
begin; iBatch < phase.
end; ++iBatch)
139 btVector3
col =
lerp(color0, color1, tt);
153 btVector3 bboxMax = -bboxMin;
154 for (
int iBody = 0; iBody < bodies.
size(); ++iBody)
156 const btVector3&
pos = bodies[iBody].getWorldTransform().getOrigin();
160 btVector3 bboxExtent = bboxMax - bboxMin;
161 btVector3 offsetBase =
btVector3(0, bboxExtent.y() * 1.1f, 0);
162 btVector3 offsetStep =
btVector3(0, 0, bboxExtent.z() * 1.1f);
163 int numPhases = bc->
m_phases.size();
164 for (
int iPhase = 0; iPhase < numPhases; ++iPhase)
169 btVector3 offset = offsetBase + offsetStep * (
float(iPhase) -
float(numPhases - 1) * 0.5);
180 for (
int i = 0; i < bodies.
size(); ++i)
183 bodyDynamicFlags[i] = (body.internalGetInvMass().x() >
btScalar(0));
222 for (
int i = iBegin; i < iEnd; ++i)
226 conInfo.
bodyIds[0] = con.m_solverBodyIdA;
227 conInfo.
bodyIds[1] = con.m_solverBodyIdB;
238 bool inParallel =
true;
242 int grainSize = 1200;
251 conInfo.
bodyIds[0] = con.m_solverBodyIdA;
252 conInfo.
bodyIds[1] = con.m_solverBodyIdB;
257 bool useRunLengthEncoding =
true;
258 if (useRunLengthEncoding)
274 int iBatch = constraintBatchIds[iCon];
279 btAssert(iDest >= 0 && iDest < numConstraintRows);
280 constraintBatchIds[iDest] = iBatch;
292 int iBatch = srcConstraintBatchIds[iCon];
297 btAssert(iDest >= 0 && iDest < numConstraintRows);
298 destConstraintBatchIds[iDest] = iBatch;
345 for (
int iBatch = iEndBatch - 1; iBatch >= iBeginBatch; --iBatch)
350 for (
int iDestBatch = iBatch - 1; iDestBatch >= iBeginBatch; --iDestBatch)
356 batch.numConstraints = 0;
357 batch.mergeIndex = iDestBatch;
367 for (
int iBatch = iBeginBatch; iBatch < iEndBatch; ++iBatch)
379 batch.mergeIndex = iMergeDest;
390 BT_PROFILE(
"updateConstraintBatchIdsForMerges");
394 int iBatch = constraintBatchIds[i];
397 if (batches[iBatch].mergeIndex !=
kNoMerge)
400 constraintBatchIds[i] = batches[iBatch].
mergeIndex;
419 BT_PROFILE(
"UpdateConstraintBatchIdsForMergesLoop");
426 BT_PROFILE(
"updateConstraintBatchIdsForMergesMt");
434 int lenA = a.end - a.begin;
435 int lenB =
b.end -
b.begin;
440 const int* constraintBatchIds,
442 int* constraintIdPerBatch,
446 BT_PROFILE(
"writeOutConstraintIndicesForRangeOfBatches");
449 int iBatch = constraintBatchIds[iCon];
450 if (iBatch >= batchBegin && iBatch < batchEnd)
452 int iDestCon = constraintIdPerBatch[iBatch];
453 constraintIdPerBatch[iBatch] = iDestCon + 1;
490 const int* constraintBatchIds,
492 int* constraintIdPerBatch,
493 int maxNumBatchesPerPhase,
497 bool inParallel =
true;
507 int iBatch = constraintBatchIds[iCon];
508 int iDestCon = constraintIdPerBatch[iBatch];
509 constraintIdPerBatch[iBatch] = iDestCon + 1;
518 int numPhases = bc->
m_phases.size();
521 for (
int iPhase = 0; iPhase < numPhases; ++iPhase)
523 const Range& phase = bc->
m_phases[iPhase];
524 int numBatches = phase.end - phase.begin;
525 float grainSize = std::floor((0.25f * numBatches /
float(numThreads)) + 0.0f);
531 const int* constraintBatchIds,
535 int maxNumBatchesPerPhase,
546 int* constraintIdPerBatch = batchWork;
548 for (
int iPhase = 0; iPhase < numPhases; ++iPhase)
550 int curPhaseBegin = bc->
m_batches.size();
551 int iBegin = iPhase * maxNumBatchesPerPhase;
552 int iEnd = iBegin + maxNumBatchesPerPhase;
553 for (
int i = iBegin; i < iEnd; ++i)
556 int curBatchBegin = iConstraint;
557 constraintIdPerBatch[i] = curBatchBegin;
562 bc->
m_batches.push_back(Range(curBatchBegin, iConstraint));
566 if (bc->
m_batches.size() > curPhaseBegin)
578 for (
int iPhase = 0; iPhase < bc->
m_phases.size(); ++iPhase)
581 const Range& curBatches = bc->
m_phases[iPhase];
585 for (
int i = 0; i < bc->
m_phases.size(); ++i)
625 Chunk& chunk = m_chunks[m_numChunks];
633 size_t totalSize = 0;
634 for (
int i = 0; i < m_numChunks; ++i)
636 totalSize += m_chunks[i].size;
642 size_t totalSize = 0;
643 for (
int i = 0; i < m_numChunks; ++i)
645 const Chunk& chunk = m_chunks[i];
646 char* chunkPtr =
static_cast<char*
>(mem) + totalSize;
647 *chunk.ptr = chunkPtr;
648 totalSize += chunk.size;
654 btVector3* bodyPositions,
655 bool* bodyDynamicFlags,
661 btVector3 consExtent =
btVector3(1, 1, 1) * 0.001;
670 if (bodyDynamicFlags[iBody0] && bodyDynamicFlags[iBody1])
672 btVector3 delta = bodyPositions[iBody1] - bodyPositions[iBody0];
673 consExtent.setMax(delta.absolute());
701 memset(
this, 0,
sizeof(*
this));
709 for (
int iCon = iConBegin; iCon < iConEnd; ++iCon)
715 iPhase &=
params.phaseMask;
718 if (
params.bodyDynamicFlags[iBody0] &&
params.bodyDynamicFlags[iBody1])
723 for (
int i = 0; i < 3; ++i)
727 if (coordMin != coordMax)
730 if ((coordMin & 1) == 0)
737 iPhase &=
params.phaseMask;
740 gridCoord[i] = coordMin;
745 if (!
params.bodyDynamicFlags[iBody0])
752 for (
int i = 0; i < 3; ++i)
754 gridCoord[i] = body0Coords.
m_ints[i];
761 for (
int i = 0; i < 3; ++i)
763 int coordOffset = (iPhase >> i) & 1;
764 chunkCoord[i] = (gridCoord[i] - coordOffset) / 2;
765 btClamp(chunkCoord[i], 0, gridChunkDim[i] - 1);
766 btAssert(chunkCoord[i] < gridChunkDim[i]);
768 int iBatch = iPhase *
params.maxNumBatchesPerPhase + chunkCoord[0] + chunkCoord[1] * gridChunkDim[0] + chunkCoord[2] * gridChunkDim[0] * gridChunkDim[1];
770 params.constraintBatchIds[iCon] = iBatch;
826 const int numPhases = 8;
830 const int maxGridChunkCount = 128;
831 int allocNumBatchesPerPhase = maxGridChunkCount;
832 int minNumBatchesPerPhase = 16;
833 int allocNumBatches = allocNumBatchesPerPhase * numPhases;
835 btVector3* bodyPositions =
NULL;
836 bool* bodyDynamicFlags =
NULL;
839 int* batchWork =
NULL;
841 int* constraintBatchIds =
NULL;
842 int* constraintRowBatchIds =
NULL;
845 memHelper.
addChunk((
void**)&bodyPositions,
sizeof(btVector3) * bodies.
size());
846 memHelper.
addChunk((
void**)&bodyDynamicFlags,
sizeof(
bool) * bodies.
size());
849 memHelper.
addChunk((
void**)&batchWork,
sizeof(
int) * allocNumBatches);
852 memHelper.
addChunk((
void**)&constraintRowBatchIds,
sizeof(
int) * numConstraintRows);
855 if (scratchMemory->
capacity() < scratchSize)
858 scratchMemory->
reserve(scratchSize + scratchSize / 16);
861 char* memPtr = &scratchMemory->
at(0);
870 btVector3 bboxMax = -bboxMin;
872 for (
int i = 0; i < bodies.
size(); ++i)
875 btVector3 bodyPos = body.getWorldTransform().getOrigin();
876 bool isDynamic = (body.internalGetInvMass().x() >
btScalar(0));
877 bodyPositions[i] = bodyPos;
878 bodyDynamicFlags[i] = isDynamic;
882 bboxMin.setMin(bodyPos);
883 bboxMax.setMax(bodyPos);
891 btVector3 gridExtent = bboxMax - bboxMin;
895 btVector3 gridCellSize = consExtent;
897 gridDim[0] =
int(1.0 + gridExtent.x() / gridCellSize.x());
898 gridDim[1] =
int(1.0 + gridExtent.y() / gridCellSize.y());
899 gridDim[2] =
int(1.0 + gridExtent.z() / gridCellSize.z());
903 bool collapseAxis = use2DGrid;
907 int iAxisToCollapse = 0;
908 int axisDim = gridDim[iAxisToCollapse];
910 for (
int i = 0; i < 3; ++i)
912 if (gridDim[i] < axisDim)
915 axisDim = gridDim[i];
919 gridCellSize[iAxisToCollapse] = gridExtent[iAxisToCollapse] * 2.0f;
920 phaseMask &= ~(1 << iAxisToCollapse);
923 int numGridChunks = 0;
927 gridDim[0] =
int(1.0 + gridExtent.x() / gridCellSize.x());
928 gridDim[1] =
int(1.0 + gridExtent.y() / gridCellSize.y());
929 gridDim[2] =
int(1.0 + gridExtent.z() / gridCellSize.z());
930 gridChunkDim[0] =
btMax(1, (gridDim[0] + 0) / 2);
931 gridChunkDim[1] =
btMax(1, (gridDim[1] + 0) / 2);
932 gridChunkDim[2] =
btMax(1, (gridDim[2] + 0) / 2);
933 numGridChunks = gridChunkDim[0] * gridChunkDim[1] * gridChunkDim[2];
934 float nChunks =
float(gridChunkDim[0]) *
float(gridChunkDim[1]) *
float(gridChunkDim[2]);
935 if (numGridChunks <= maxGridChunkCount && nChunks <= maxGridChunkCount)
939 gridCellSize *= 1.25;
941 btAssert(numGridChunks <= maxGridChunkCount);
942 int maxNumBatchesPerPhase = numGridChunks;
945 btVector3 invGridCellSize =
btVector3(1, 1, 1) / gridCellSize;
947 for (
int iBody = 0; iBody < bodies.
size(); ++iBody)
949 btIntVec3& coords = bodyGridCoords[iBody];
950 if (bodyDynamicFlags[iBody])
952 btVector3
v = (bodyPositions[iBody] - bboxMin) * invGridCellSize;
968 for (
int iPhase = 0; iPhase < numPhases; ++iPhase)
970 int batchBegin = iPhase * maxNumBatchesPerPhase;
971 int batchEnd = batchBegin + maxNumBatchesPerPhase;
972 for (
int iBatch = batchBegin; iBatch < batchEnd; ++iBatch)
981 params.bodyDynamicFlags = bodyDynamicFlags;
982 params.bodyGridCoords = bodyGridCoords;
984 params.conInfos = conInfos;
985 params.constraintBatchIds = constraintBatchIds;
986 params.gridChunkDim = gridChunkDim;
987 params.maxNumBatchesPerPhase = maxNumBatchesPerPhase;
988 params.numPhases = numPhases;
989 params.phaseMask = phaseMask;
990 bool inParallel =
true;
1005 int iBatch = constraintBatchIds[iCon];
1010 for (
int iPhase = 0; iPhase < numPhases; ++iPhase)
1013 if (iPhase == (iPhase & phaseMask))
1015 int iBeginBatch = iPhase * maxNumBatchesPerPhase;
1016 int iEndBatch = iBeginBatch + maxNumBatchesPerPhase;
1029 constraintRowBatchIds = constraintBatchIds;
1032 writeOutBatches(batchedConstraints, constraintRowBatchIds, numConstraintRows, batches, batchWork, maxNumBatchesPerPhase, numPhases);
1050 bc->
m_phases.resizeNoInitialize(0);
1057 bc->
m_phases.push_back(Range(0, 1));
ATTR_WARN_UNUSED_RESULT const BMVert * v
static void writeGrainSizes(btBatchedConstraints *bc)
static void updateConstraintBatchIdsForMergesMt(int *constraintBatchIds, int numConstraints, const btBatchInfo *batches, int numBatches)
static void initBatchedConstraintInfoArray(btAlignedObjectArray< btBatchedConstraintInfo > *outConInfos, btConstraintArray *constraints)
static void debugDrawAllBatches(const btBatchedConstraints *bc, btConstraintArray *constraints, const btAlignedObjectArray< btSolverBody > &bodies)
static void updateConstraintBatchIdsForMerges(int *constraintBatchIds, int numConstraints, const btBatchInfo *batches, int numBatches)
static void expandConstraintRowsInPlace(int *constraintBatchIds, const btBatchedConstraintInfo *conInfos, int numConstraints, int numConstraintRows)
static void setupSingleBatch(btBatchedConstraints *bc, int numConstraints)
static void writeOutConstraintIndicesMt(btBatchedConstraints *bc, const int *constraintBatchIds, int numConstraints, int *constraintIdPerBatch, int maxNumBatchesPerPhase, int numPhases)
static int runLengthEncodeConstraintInfo(btBatchedConstraintInfo *outConInfos, int numConstraints)
static void debugDrawPhase(const btBatchedConstraints *bc, btConstraintArray *constraints, const btAlignedObjectArray< btSolverBody > &bodies, int iPhase, const btVector3 &color0, const btVector3 &color1, const btVector3 &offset)
bool BatchCompare(const btBatchedConstraints::Range &a, const btBatchedConstraints::Range &b)
static void mergeSmallBatches(btBatchInfo *batches, int iBeginBatch, int iEndBatch, int minBatchSize, int maxBatchSize)
static void writeOutConstraintIndicesForRangeOfBatches(btBatchedConstraints *bc, const int *constraintBatchIds, int numConstraints, int *constraintIdPerBatch, int batchBegin, int batchEnd)
static void expandConstraintRowsMt(int *destConstraintBatchIds, const int *srcConstraintBatchIds, const btBatchedConstraintInfo *conInfos, int numConstraints, int numConstraintRows)
static void setupSpatialGridBatchesMt(btBatchedConstraints *batchedConstraints, btAlignedObjectArray< char > *scratchMemory, btConstraintArray *constraints, const btAlignedObjectArray< btSolverBody > &bodies, int minBatchSize, int maxBatchSize, bool use2DGrid)
static btVector3 findMaxDynamicConstraintExtent(btVector3 *bodyPositions, bool *bodyDynamicFlags, btBatchedConstraintInfo *conInfos, int numConstraints, int numBodies)
static void initBatchedBodyDynamicFlags(btAlignedObjectArray< bool > *outBodyDynamicFlags, const btAlignedObjectArray< btSolverBody > &bodies)
static void expandConstraintRows(int *destConstraintBatchIds, const int *srcConstraintBatchIds, const btBatchedConstraintInfo *conInfos, int numConstraints, int numConstraintRows)
static int initBatchedConstraintInfo(btBatchedConstraintInfo *outConInfos, btConstraintArray *constraints)
static void debugDrawSingleBatch(const btBatchedConstraints *bc, btConstraintArray *constraints, const btAlignedObjectArray< btSolverBody > &bodies, int iBatch, const btVector3 &color, const btVector3 &offset)
static void writeOutBatches(btBatchedConstraints *bc, const int *constraintBatchIds, int numConstraints, const btBatchInfo *batches, int *batchWork, int maxNumBatchesPerPhase, int numPhases)
static void assignConstraintsToGridBatches(const AssignConstraintsToGridBatchesParams ¶ms, int iConBegin, int iConEnd)
SIMD_FORCE_INLINE const T & btMin(const T &a, const T &b)
SIMD_FORCE_INLINE const T & btMax(const T &a, const T &b)
SIMD_FORCE_INLINE void btClamp(T &a, const T &lb, const T &ub)
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
#define SIMD_FORCE_INLINE
btSequentialImpulseConstraintSolverMt int btPersistentManifold int btTypedConstraint ** constraints
btSequentialImpulseConstraintSolverMt int btPersistentManifold int btTypedConstraint int numConstraints
btSequentialImpulseConstraintSolverMt int numBodies
btSolverBody
The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packe...
btSolverConstraint
1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and fr...
btITaskScheduler * btGetTaskScheduler()
void btParallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody &body)
btVector3
btVector3 can be used to represent 3D points and vectors. It has an un-used w component to suit 16-by...
void addChunk(void **ptr, size_t sz)
size_t getSizeToAllocate() const
void setChunkPointers(void *mem) const
PreallocatedMemoryHelper()
SIMD_FORCE_INLINE void reserve(int _Count)
SIMD_FORCE_INLINE int capacity() const
return the pre-allocated (reserved) elements, this is at least as large as the total number of elemen...
SIMD_FORCE_INLINE void resizeNoInitialize(int newsize)
SIMD_FORCE_INLINE int size() const
return the number of elements in the array
SIMD_FORCE_INLINE void resize(int newsize, const T &fillData=T())
SIMD_FORCE_INLINE const T & at(int n) const
SIMD_FORCE_INLINE void push_back(const T &_Val)
virtual void drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)=0
virtual int getNumThreads() const =0
local_group_size(16, 16) .push_constant(Type b
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
AssignConstraintsToGridBatchesLoop(const AssignConstraintsToGridBatchesParams ¶ms)
const AssignConstraintsToGridBatchesParams * m_params
void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
btBatchedConstraintInfo * conInfos
btIntVec3 * bodyGridCoords
AssignConstraintsToGridBatchesParams()
int maxNumBatchesPerPhase
const btBatchedConstraintInfo * m_conInfos
int * m_destConstraintBatchIds
const int * m_srcConstraintBatchIds
ExpandConstraintRowsLoop(int *destConstraintBatchIds, const int *srcConstraintBatchIds, const btBatchedConstraintInfo *conInfos, int numConstraintRows)
void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
btBatchedConstraintInfo * m_outConInfos
ReadSolverConstraintsLoop(btBatchedConstraintInfo *outConInfos, btConstraintArray *constraints)
btConstraintArray * m_constraints
void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
int m_maxNumBatchesPerPhase
WriteOutConstraintIndicesLoop(btBatchedConstraints *bc, const int *constraintBatchIds, int numConstraints, int *constraintIdPerBatch, int maxNumBatchesPerPhase)
btBatchedConstraints * m_batchedConstraints
void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
int * m_constraintIdPerBatch
const int * m_constraintBatchIds
bool validate(btConstraintArray *constraints, const btAlignedObjectArray< btSolverBody > &bodies) const
static bool s_debugDrawBatches
btAlignedObjectArray< Range > m_batches
btAlignedObjectArray< int > m_constraintIndices
void setup(btConstraintArray *constraints, const btAlignedObjectArray< btSolverBody > &bodies, BatchingMethod batchingMethod, int minBatchSize, int maxBatchSize, btAlignedObjectArray< char > *scratchMemory)
btAlignedObjectArray< char > m_phaseGrainSize
btAlignedObjectArray< int > m_phaseOrder
btAlignedObjectArray< Range > m_phases
btIDebugDraw * m_debugDrawer
@ BATCHING_METHOD_SPATIAL_GRID_2D
SIMD_FORCE_INLINE int & operator[](int i)
SIMD_FORCE_INLINE const int & operator[](int i) const