diff options
Diffstat (limited to 'thirdparty/bullet/BulletDynamics/ConstraintSolver')
41 files changed, 6787 insertions, 7497 deletions
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp index c82ba87f9f..b51dfaad3c 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp @@ -13,7 +13,6 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ - #include "btBatchedConstraints.h" #include "LinearMath/btIDebugDraw.h" @@ -21,606 +20,573 @@ subject to the following restrictions: #include "LinearMath/btStackAlloc.h" #include "LinearMath/btQuickprof.h" -#include <string.h> //for memset +#include <string.h> //for memset const int kNoMerge = -1; bool btBatchedConstraints::s_debugDrawBatches = false; - struct btBatchedConstraintInfo { - int constraintIndex; - int numConstraintRows; - int bodyIds[2]; + int constraintIndex; + int numConstraintRows; + int bodyIds[2]; }; - struct btBatchInfo { - int numConstraints; - int mergeIndex; + int numConstraints; + int mergeIndex; - btBatchInfo() : numConstraints(0), mergeIndex(kNoMerge) {} + btBatchInfo() : numConstraints(0), mergeIndex(kNoMerge) {} }; - bool btBatchedConstraints::validate(btConstraintArray* constraints, const btAlignedObjectArray<btSolverBody>& bodies) const { - // - // validate: for debugging only. Verify coloring of bodies, that no body is touched by more than one batch in any given phase - // - int errors = 0; - const int kUnassignedBatch = -1; - - btAlignedObjectArray<int> bodyBatchId; - for (int iPhase = 0; iPhase < m_phases.size(); ++iPhase) - { - bodyBatchId.resizeNoInitialize(0); - bodyBatchId.resize( bodies.size(), kUnassignedBatch ); - const Range& phase = m_phases[iPhase]; - for (int iBatch = phase.begin; iBatch < phase.end; ++iBatch) - { - const Range& batch = m_batches[iBatch]; - for (int iiCons = batch.begin; iiCons < batch.end; ++iiCons) - { - int iCons = m_constraintIndices[iiCons]; - const btSolverConstraint& cons = constraints->at(iCons); - const btSolverBody& bodyA = bodies[cons.m_solverBodyIdA]; - const btSolverBody& bodyB = bodies[cons.m_solverBodyIdB]; - if (! bodyA.internalGetInvMass().isZero()) - { - int thisBodyBatchId = bodyBatchId[cons.m_solverBodyIdA]; - if (thisBodyBatchId == kUnassignedBatch) - { - bodyBatchId[cons.m_solverBodyIdA] = iBatch; - } - else if (thisBodyBatchId != iBatch) - { - btAssert( !"dynamic body is used in 2 different batches in the same phase" ); - errors++; - } - } - if (! bodyB.internalGetInvMass().isZero()) - { - int thisBodyBatchId = bodyBatchId[cons.m_solverBodyIdB]; - if (thisBodyBatchId == kUnassignedBatch) - { - bodyBatchId[cons.m_solverBodyIdB] = iBatch; - } - else if (thisBodyBatchId != iBatch) - { - btAssert( !"dynamic body is used in 2 different batches in the same phase" ); - errors++; - } - } - } - } - } - return errors == 0; + // + // validate: for debugging only. Verify coloring of bodies, that no body is touched by more than one batch in any given phase + // + int errors = 0; + const int kUnassignedBatch = -1; + + btAlignedObjectArray<int> bodyBatchId; + for (int iPhase = 0; iPhase < m_phases.size(); ++iPhase) + { + bodyBatchId.resizeNoInitialize(0); + bodyBatchId.resize(bodies.size(), kUnassignedBatch); + const Range& phase = m_phases[iPhase]; + for (int iBatch = phase.begin; iBatch < phase.end; ++iBatch) + { + const Range& batch = m_batches[iBatch]; + for (int iiCons = batch.begin; iiCons < batch.end; ++iiCons) + { + int iCons = m_constraintIndices[iiCons]; + const btSolverConstraint& cons = constraints->at(iCons); + const btSolverBody& bodyA = bodies[cons.m_solverBodyIdA]; + const btSolverBody& bodyB = bodies[cons.m_solverBodyIdB]; + if (!bodyA.internalGetInvMass().isZero()) + { + int thisBodyBatchId = bodyBatchId[cons.m_solverBodyIdA]; + if (thisBodyBatchId == kUnassignedBatch) + { + bodyBatchId[cons.m_solverBodyIdA] = iBatch; + } + else if (thisBodyBatchId != iBatch) + { + btAssert(!"dynamic body is used in 2 different batches in the same phase"); + errors++; + } + } + if (!bodyB.internalGetInvMass().isZero()) + { + int thisBodyBatchId = bodyBatchId[cons.m_solverBodyIdB]; + if (thisBodyBatchId == kUnassignedBatch) + { + bodyBatchId[cons.m_solverBodyIdB] = iBatch; + } + else if (thisBodyBatchId != iBatch) + { + btAssert(!"dynamic body is used in 2 different batches in the same phase"); + errors++; + } + } + } + } + } + return errors == 0; } - -static void debugDrawSingleBatch( const btBatchedConstraints* bc, - btConstraintArray* constraints, - const btAlignedObjectArray<btSolverBody>& bodies, - int iBatch, - const btVector3& color, - const btVector3& offset - ) +static void debugDrawSingleBatch(const btBatchedConstraints* bc, + btConstraintArray* constraints, + const btAlignedObjectArray<btSolverBody>& bodies, + int iBatch, + const btVector3& color, + const btVector3& offset) { - if (bc && bc->m_debugDrawer && iBatch < bc->m_batches.size()) - { - const btBatchedConstraints::Range& b = bc->m_batches[iBatch]; - for (int iiCon = b.begin; iiCon < b.end; ++iiCon) - { - int iCon = bc->m_constraintIndices[iiCon]; - const btSolverConstraint& con = constraints->at(iCon); - int iBody0 = con.m_solverBodyIdA; - int iBody1 = con.m_solverBodyIdB; - btVector3 pos0 = bodies[iBody0].getWorldTransform().getOrigin() + offset; - btVector3 pos1 = bodies[iBody1].getWorldTransform().getOrigin() + offset; - bc->m_debugDrawer->drawLine(pos0, pos1, color); - } - } + if (bc && bc->m_debugDrawer && iBatch < bc->m_batches.size()) + { + const btBatchedConstraints::Range& b = bc->m_batches[iBatch]; + for (int iiCon = b.begin; iiCon < b.end; ++iiCon) + { + int iCon = bc->m_constraintIndices[iiCon]; + const btSolverConstraint& con = constraints->at(iCon); + int iBody0 = con.m_solverBodyIdA; + int iBody1 = con.m_solverBodyIdB; + btVector3 pos0 = bodies[iBody0].getWorldTransform().getOrigin() + offset; + btVector3 pos1 = bodies[iBody1].getWorldTransform().getOrigin() + offset; + bc->m_debugDrawer->drawLine(pos0, pos1, color); + } + } } - -static void debugDrawPhase( const btBatchedConstraints* bc, - btConstraintArray* constraints, - const btAlignedObjectArray<btSolverBody>& bodies, - int iPhase, - const btVector3& color0, - const btVector3& color1, - const btVector3& offset - ) +static void debugDrawPhase(const btBatchedConstraints* bc, + btConstraintArray* constraints, + const btAlignedObjectArray<btSolverBody>& bodies, + int iPhase, + const btVector3& color0, + const btVector3& color1, + const btVector3& offset) { - BT_PROFILE( "debugDrawPhase" ); - if ( bc && bc->m_debugDrawer && iPhase < bc->m_phases.size() ) - { - const btBatchedConstraints::Range& phase = bc->m_phases[iPhase]; - for (int iBatch = phase.begin; iBatch < phase.end; ++iBatch) - { - float tt = float(iBatch - phase.begin) / float(btMax(1, phase.end - phase.begin - 1)); - btVector3 col = lerp(color0, color1, tt); - debugDrawSingleBatch(bc, constraints, bodies, iBatch, col, offset); - } - } + BT_PROFILE("debugDrawPhase"); + if (bc && bc->m_debugDrawer && iPhase < bc->m_phases.size()) + { + const btBatchedConstraints::Range& phase = bc->m_phases[iPhase]; + for (int iBatch = phase.begin; iBatch < phase.end; ++iBatch) + { + float tt = float(iBatch - phase.begin) / float(btMax(1, phase.end - phase.begin - 1)); + btVector3 col = lerp(color0, color1, tt); + debugDrawSingleBatch(bc, constraints, bodies, iBatch, col, offset); + } + } } - -static void debugDrawAllBatches( const btBatchedConstraints* bc, - btConstraintArray* constraints, - const btAlignedObjectArray<btSolverBody>& bodies - ) +static void debugDrawAllBatches(const btBatchedConstraints* bc, + btConstraintArray* constraints, + const btAlignedObjectArray<btSolverBody>& bodies) { - BT_PROFILE( "debugDrawAllBatches" ); - if ( bc && bc->m_debugDrawer && bc->m_phases.size() > 0 ) - { - btVector3 bboxMin(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT); - btVector3 bboxMax = -bboxMin; - for (int iBody = 0; iBody < bodies.size(); ++iBody) - { - const btVector3& pos = bodies[iBody].getWorldTransform().getOrigin(); - bboxMin.setMin(pos); - bboxMax.setMax(pos); - } - btVector3 bboxExtent = bboxMax - bboxMin; - btVector3 offsetBase = btVector3( 0, bboxExtent.y()*1.1f, 0 ); - btVector3 offsetStep = btVector3( 0, 0, bboxExtent.z()*1.1f ); - int numPhases = bc->m_phases.size(); - for (int iPhase = 0; iPhase < numPhases; ++iPhase) - { - float b = float(iPhase)/float(numPhases-1); - btVector3 color0 = btVector3(1,0,b); - btVector3 color1 = btVector3(0,1,b); - btVector3 offset = offsetBase + offsetStep*(float(iPhase) - float(numPhases-1)*0.5); - debugDrawPhase(bc, constraints, bodies, iPhase, color0, color1, offset); - } - } + BT_PROFILE("debugDrawAllBatches"); + if (bc && bc->m_debugDrawer && bc->m_phases.size() > 0) + { + btVector3 bboxMin(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT); + btVector3 bboxMax = -bboxMin; + for (int iBody = 0; iBody < bodies.size(); ++iBody) + { + const btVector3& pos = bodies[iBody].getWorldTransform().getOrigin(); + bboxMin.setMin(pos); + bboxMax.setMax(pos); + } + btVector3 bboxExtent = bboxMax - bboxMin; + btVector3 offsetBase = btVector3(0, bboxExtent.y() * 1.1f, 0); + btVector3 offsetStep = btVector3(0, 0, bboxExtent.z() * 1.1f); + int numPhases = bc->m_phases.size(); + for (int iPhase = 0; iPhase < numPhases; ++iPhase) + { + float b = float(iPhase) / float(numPhases - 1); + btVector3 color0 = btVector3(1, 0, b); + btVector3 color1 = btVector3(0, 1, b); + btVector3 offset = offsetBase + offsetStep * (float(iPhase) - float(numPhases - 1) * 0.5); + debugDrawPhase(bc, constraints, bodies, iPhase, color0, color1, offset); + } + } } - static void initBatchedBodyDynamicFlags(btAlignedObjectArray<bool>* outBodyDynamicFlags, const btAlignedObjectArray<btSolverBody>& bodies) { - BT_PROFILE("initBatchedBodyDynamicFlags"); - btAlignedObjectArray<bool>& bodyDynamicFlags = *outBodyDynamicFlags; - bodyDynamicFlags.resizeNoInitialize(bodies.size()); - for (int i = 0; i < bodies.size(); ++i) - { - const btSolverBody& body = bodies[ i ]; - bodyDynamicFlags[i] = ( body.internalGetInvMass().x() > btScalar( 0 ) ); - } + BT_PROFILE("initBatchedBodyDynamicFlags"); + btAlignedObjectArray<bool>& bodyDynamicFlags = *outBodyDynamicFlags; + bodyDynamicFlags.resizeNoInitialize(bodies.size()); + for (int i = 0; i < bodies.size(); ++i) + { + const btSolverBody& body = bodies[i]; + bodyDynamicFlags[i] = (body.internalGetInvMass().x() > btScalar(0)); + } } - static int runLengthEncodeConstraintInfo(btBatchedConstraintInfo* outConInfos, int numConstraints) { - BT_PROFILE("runLengthEncodeConstraintInfo"); - // detect and run-length encode constraint rows that repeat the same bodies - int iDest = 0; - int iSrc = 0; - while (iSrc < numConstraints) - { - const btBatchedConstraintInfo& srcConInfo = outConInfos[iSrc]; - btBatchedConstraintInfo& conInfo = outConInfos[iDest]; - conInfo.constraintIndex = iSrc; - conInfo.bodyIds[0] = srcConInfo.bodyIds[0]; - conInfo.bodyIds[1] = srcConInfo.bodyIds[1]; - while (iSrc < numConstraints && outConInfos[iSrc].bodyIds[0] == srcConInfo.bodyIds[0] && outConInfos[iSrc].bodyIds[1] == srcConInfo.bodyIds[1]) - { - ++iSrc; - } - conInfo.numConstraintRows = iSrc - conInfo.constraintIndex; - ++iDest; - } - return iDest; + BT_PROFILE("runLengthEncodeConstraintInfo"); + // detect and run-length encode constraint rows that repeat the same bodies + int iDest = 0; + int iSrc = 0; + while (iSrc < numConstraints) + { + const btBatchedConstraintInfo& srcConInfo = outConInfos[iSrc]; + btBatchedConstraintInfo& conInfo = outConInfos[iDest]; + conInfo.constraintIndex = iSrc; + conInfo.bodyIds[0] = srcConInfo.bodyIds[0]; + conInfo.bodyIds[1] = srcConInfo.bodyIds[1]; + while (iSrc < numConstraints && outConInfos[iSrc].bodyIds[0] == srcConInfo.bodyIds[0] && outConInfos[iSrc].bodyIds[1] == srcConInfo.bodyIds[1]) + { + ++iSrc; + } + conInfo.numConstraintRows = iSrc - conInfo.constraintIndex; + ++iDest; + } + return iDest; } - struct ReadSolverConstraintsLoop : public btIParallelForBody { - btBatchedConstraintInfo* m_outConInfos; - btConstraintArray* m_constraints; - - ReadSolverConstraintsLoop( btBatchedConstraintInfo* outConInfos, btConstraintArray* constraints ) - { - m_outConInfos = outConInfos; - m_constraints = constraints; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - for (int i = iBegin; i < iEnd; ++i) - { - btBatchedConstraintInfo& conInfo = m_outConInfos[i]; - const btSolverConstraint& con = m_constraints->at( i ); - conInfo.bodyIds[0] = con.m_solverBodyIdA; - conInfo.bodyIds[1] = con.m_solverBodyIdB; - conInfo.constraintIndex = i; - conInfo.numConstraintRows = 1; - } - } + btBatchedConstraintInfo* m_outConInfos; + btConstraintArray* m_constraints; + + ReadSolverConstraintsLoop(btBatchedConstraintInfo* outConInfos, btConstraintArray* constraints) + { + m_outConInfos = outConInfos; + m_constraints = constraints; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + for (int i = iBegin; i < iEnd; ++i) + { + btBatchedConstraintInfo& conInfo = m_outConInfos[i]; + const btSolverConstraint& con = m_constraints->at(i); + conInfo.bodyIds[0] = con.m_solverBodyIdA; + conInfo.bodyIds[1] = con.m_solverBodyIdB; + conInfo.constraintIndex = i; + conInfo.numConstraintRows = 1; + } + } }; - static int initBatchedConstraintInfo(btBatchedConstraintInfo* outConInfos, btConstraintArray* constraints) { - BT_PROFILE("initBatchedConstraintInfo"); - int numConstraints = constraints->size(); - bool inParallel = true; - if (inParallel) - { - ReadSolverConstraintsLoop loop(outConInfos, constraints); - int grainSize = 1200; - btParallelFor(0, numConstraints, grainSize, loop); - } - else - { - for (int i = 0; i < numConstraints; ++i) - { - btBatchedConstraintInfo& conInfo = outConInfos[i]; - const btSolverConstraint& con = constraints->at( i ); - conInfo.bodyIds[0] = con.m_solverBodyIdA; - conInfo.bodyIds[1] = con.m_solverBodyIdB; - conInfo.constraintIndex = i; - conInfo.numConstraintRows = 1; - } - } - bool useRunLengthEncoding = true; - if (useRunLengthEncoding) - { - numConstraints = runLengthEncodeConstraintInfo(outConInfos, numConstraints); - } - return numConstraints; + BT_PROFILE("initBatchedConstraintInfo"); + int numConstraints = constraints->size(); + bool inParallel = true; + if (inParallel) + { + ReadSolverConstraintsLoop loop(outConInfos, constraints); + int grainSize = 1200; + btParallelFor(0, numConstraints, grainSize, loop); + } + else + { + for (int i = 0; i < numConstraints; ++i) + { + btBatchedConstraintInfo& conInfo = outConInfos[i]; + const btSolverConstraint& con = constraints->at(i); + conInfo.bodyIds[0] = con.m_solverBodyIdA; + conInfo.bodyIds[1] = con.m_solverBodyIdB; + conInfo.constraintIndex = i; + conInfo.numConstraintRows = 1; + } + } + bool useRunLengthEncoding = true; + if (useRunLengthEncoding) + { + numConstraints = runLengthEncodeConstraintInfo(outConInfos, numConstraints); + } + return numConstraints; } - static void expandConstraintRowsInPlace(int* constraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraints, int numConstraintRows) { - BT_PROFILE("expandConstraintRowsInPlace"); - if (numConstraintRows > numConstraints) - { - // we walk the array in reverse to avoid overwriteing - for (int iCon = numConstraints - 1; iCon >= 0; --iCon) - { - const btBatchedConstraintInfo& conInfo = conInfos[iCon]; - int iBatch = constraintBatchIds[iCon]; - for (int i = conInfo.numConstraintRows - 1; i >= 0; --i) - { - int iDest = conInfo.constraintIndex + i; - btAssert(iDest >= iCon); - btAssert(iDest >= 0 && iDest < numConstraintRows); - constraintBatchIds[iDest] = iBatch; - } - } - } + BT_PROFILE("expandConstraintRowsInPlace"); + if (numConstraintRows > numConstraints) + { + // we walk the array in reverse to avoid overwriteing + for (int iCon = numConstraints - 1; iCon >= 0; --iCon) + { + const btBatchedConstraintInfo& conInfo = conInfos[iCon]; + int iBatch = constraintBatchIds[iCon]; + for (int i = conInfo.numConstraintRows - 1; i >= 0; --i) + { + int iDest = conInfo.constraintIndex + i; + btAssert(iDest >= iCon); + btAssert(iDest >= 0 && iDest < numConstraintRows); + constraintBatchIds[iDest] = iBatch; + } + } + } } - static void expandConstraintRows(int* destConstraintBatchIds, const int* srcConstraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraints, int numConstraintRows) { - BT_PROFILE("expandConstraintRows"); - for ( int iCon = 0; iCon < numConstraints; ++iCon ) - { - const btBatchedConstraintInfo& conInfo = conInfos[ iCon ]; - int iBatch = srcConstraintBatchIds[ iCon ]; - for ( int i = 0; i < conInfo.numConstraintRows; ++i ) - { - int iDest = conInfo.constraintIndex + i; - btAssert( iDest >= iCon ); - btAssert( iDest >= 0 && iDest < numConstraintRows ); - destConstraintBatchIds[ iDest ] = iBatch; - } - } + BT_PROFILE("expandConstraintRows"); + for (int iCon = 0; iCon < numConstraints; ++iCon) + { + const btBatchedConstraintInfo& conInfo = conInfos[iCon]; + int iBatch = srcConstraintBatchIds[iCon]; + for (int i = 0; i < conInfo.numConstraintRows; ++i) + { + int iDest = conInfo.constraintIndex + i; + btAssert(iDest >= iCon); + btAssert(iDest >= 0 && iDest < numConstraintRows); + destConstraintBatchIds[iDest] = iBatch; + } + } } - struct ExpandConstraintRowsLoop : public btIParallelForBody { - int* m_destConstraintBatchIds; - const int* m_srcConstraintBatchIds; - const btBatchedConstraintInfo* m_conInfos; - int m_numConstraintRows; - - ExpandConstraintRowsLoop( int* destConstraintBatchIds, const int* srcConstraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraintRows) - { - m_destConstraintBatchIds = destConstraintBatchIds; - m_srcConstraintBatchIds = srcConstraintBatchIds; - m_conInfos = conInfos; - m_numConstraintRows = numConstraintRows; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - expandConstraintRows(m_destConstraintBatchIds, m_srcConstraintBatchIds + iBegin, m_conInfos + iBegin, iEnd - iBegin, m_numConstraintRows); - } + int* m_destConstraintBatchIds; + const int* m_srcConstraintBatchIds; + const btBatchedConstraintInfo* m_conInfos; + int m_numConstraintRows; + + ExpandConstraintRowsLoop(int* destConstraintBatchIds, const int* srcConstraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraintRows) + { + m_destConstraintBatchIds = destConstraintBatchIds; + m_srcConstraintBatchIds = srcConstraintBatchIds; + m_conInfos = conInfos; + m_numConstraintRows = numConstraintRows; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + expandConstraintRows(m_destConstraintBatchIds, m_srcConstraintBatchIds + iBegin, m_conInfos + iBegin, iEnd - iBegin, m_numConstraintRows); + } }; - static void expandConstraintRowsMt(int* destConstraintBatchIds, const int* srcConstraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraints, int numConstraintRows) { - BT_PROFILE("expandConstraintRowsMt"); - ExpandConstraintRowsLoop loop(destConstraintBatchIds, srcConstraintBatchIds, conInfos, numConstraintRows); - int grainSize = 600; - btParallelFor(0, numConstraints, grainSize, loop); + BT_PROFILE("expandConstraintRowsMt"); + ExpandConstraintRowsLoop loop(destConstraintBatchIds, srcConstraintBatchIds, conInfos, numConstraintRows); + int grainSize = 600; + btParallelFor(0, numConstraints, grainSize, loop); } - static void initBatchedConstraintInfoArray(btAlignedObjectArray<btBatchedConstraintInfo>* outConInfos, btConstraintArray* constraints) { - BT_PROFILE("initBatchedConstraintInfoArray"); - btAlignedObjectArray<btBatchedConstraintInfo>& conInfos = *outConInfos; - int numConstraints = constraints->size(); - conInfos.resizeNoInitialize(numConstraints); + BT_PROFILE("initBatchedConstraintInfoArray"); + btAlignedObjectArray<btBatchedConstraintInfo>& conInfos = *outConInfos; + int numConstraints = constraints->size(); + conInfos.resizeNoInitialize(numConstraints); - int newSize = initBatchedConstraintInfo(&outConInfos->at(0), constraints); - conInfos.resizeNoInitialize(newSize); + int newSize = initBatchedConstraintInfo(&outConInfos->at(0), constraints); + conInfos.resizeNoInitialize(newSize); } - static void mergeSmallBatches(btBatchInfo* batches, int iBeginBatch, int iEndBatch, int minBatchSize, int maxBatchSize) { - BT_PROFILE("mergeSmallBatches"); - for ( int iBatch = iEndBatch - 1; iBatch >= iBeginBatch; --iBatch ) - { - btBatchInfo& batch = batches[ iBatch ]; - if ( batch.mergeIndex == kNoMerge && batch.numConstraints > 0 && batch.numConstraints < minBatchSize ) - { - for ( int iDestBatch = iBatch - 1; iDestBatch >= iBeginBatch; --iDestBatch ) - { - btBatchInfo& destBatch = batches[ iDestBatch ]; - if ( destBatch.mergeIndex == kNoMerge && ( destBatch.numConstraints + batch.numConstraints ) < maxBatchSize ) - { - destBatch.numConstraints += batch.numConstraints; - batch.numConstraints = 0; - batch.mergeIndex = iDestBatch; - break; - } - } - } - } - // flatten mergeIndexes - // e.g. in case where A was merged into B and then B was merged into C, we need A to point to C instead of B - // Note: loop goes forward through batches because batches always merge from higher indexes to lower, - // so by going from low to high it reduces the amount of trail-following - for ( int iBatch = iBeginBatch; iBatch < iEndBatch; ++iBatch ) - { - btBatchInfo& batch = batches[ iBatch ]; - if ( batch.mergeIndex != kNoMerge ) - { - int iMergeDest = batches[ batch.mergeIndex ].mergeIndex; - // follow trail of merges to the end - while ( iMergeDest != kNoMerge ) - { - int iNext = batches[ iMergeDest ].mergeIndex; - if ( iNext == kNoMerge ) - { - batch.mergeIndex = iMergeDest; - break; - } - iMergeDest = iNext; - } - } - } + BT_PROFILE("mergeSmallBatches"); + for (int iBatch = iEndBatch - 1; iBatch >= iBeginBatch; --iBatch) + { + btBatchInfo& batch = batches[iBatch]; + if (batch.mergeIndex == kNoMerge && batch.numConstraints > 0 && batch.numConstraints < minBatchSize) + { + for (int iDestBatch = iBatch - 1; iDestBatch >= iBeginBatch; --iDestBatch) + { + btBatchInfo& destBatch = batches[iDestBatch]; + if (destBatch.mergeIndex == kNoMerge && (destBatch.numConstraints + batch.numConstraints) < maxBatchSize) + { + destBatch.numConstraints += batch.numConstraints; + batch.numConstraints = 0; + batch.mergeIndex = iDestBatch; + break; + } + } + } + } + // flatten mergeIndexes + // e.g. in case where A was merged into B and then B was merged into C, we need A to point to C instead of B + // Note: loop goes forward through batches because batches always merge from higher indexes to lower, + // so by going from low to high it reduces the amount of trail-following + for (int iBatch = iBeginBatch; iBatch < iEndBatch; ++iBatch) + { + btBatchInfo& batch = batches[iBatch]; + if (batch.mergeIndex != kNoMerge) + { + int iMergeDest = batches[batch.mergeIndex].mergeIndex; + // follow trail of merges to the end + while (iMergeDest != kNoMerge) + { + int iNext = batches[iMergeDest].mergeIndex; + if (iNext == kNoMerge) + { + batch.mergeIndex = iMergeDest; + break; + } + iMergeDest = iNext; + } + } + } } - static void updateConstraintBatchIdsForMerges(int* constraintBatchIds, int numConstraints, const btBatchInfo* batches, int numBatches) { - BT_PROFILE("updateConstraintBatchIdsForMerges"); - // update batchIds to account for merges - for (int i = 0; i < numConstraints; ++i) - { - int iBatch = constraintBatchIds[i]; - btAssert(iBatch < numBatches); - // if this constraint references a batch that was merged into another batch - if (batches[iBatch].mergeIndex != kNoMerge) - { - // update batchId - constraintBatchIds[i] = batches[iBatch].mergeIndex; - } - } + BT_PROFILE("updateConstraintBatchIdsForMerges"); + // update batchIds to account for merges + for (int i = 0; i < numConstraints; ++i) + { + int iBatch = constraintBatchIds[i]; + btAssert(iBatch < numBatches); + // if this constraint references a batch that was merged into another batch + if (batches[iBatch].mergeIndex != kNoMerge) + { + // update batchId + constraintBatchIds[i] = batches[iBatch].mergeIndex; + } + } } - struct UpdateConstraintBatchIdsForMergesLoop : public btIParallelForBody { - int* m_constraintBatchIds; - const btBatchInfo* m_batches; - int m_numBatches; - - UpdateConstraintBatchIdsForMergesLoop( int* constraintBatchIds, const btBatchInfo* batches, int numBatches ) - { - m_constraintBatchIds = constraintBatchIds; - m_batches = batches; - m_numBatches = numBatches; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "UpdateConstraintBatchIdsForMergesLoop" ); - updateConstraintBatchIdsForMerges( m_constraintBatchIds + iBegin, iEnd - iBegin, m_batches, m_numBatches ); - } + int* m_constraintBatchIds; + const btBatchInfo* m_batches; + int m_numBatches; + + UpdateConstraintBatchIdsForMergesLoop(int* constraintBatchIds, const btBatchInfo* batches, int numBatches) + { + m_constraintBatchIds = constraintBatchIds; + m_batches = batches; + m_numBatches = numBatches; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("UpdateConstraintBatchIdsForMergesLoop"); + updateConstraintBatchIdsForMerges(m_constraintBatchIds + iBegin, iEnd - iBegin, m_batches, m_numBatches); + } }; - static void updateConstraintBatchIdsForMergesMt(int* constraintBatchIds, int numConstraints, const btBatchInfo* batches, int numBatches) { - BT_PROFILE( "updateConstraintBatchIdsForMergesMt" ); - UpdateConstraintBatchIdsForMergesLoop loop(constraintBatchIds, batches, numBatches); - int grainSize = 800; - btParallelFor(0, numConstraints, grainSize, loop); + BT_PROFILE("updateConstraintBatchIdsForMergesMt"); + UpdateConstraintBatchIdsForMergesLoop loop(constraintBatchIds, batches, numBatches); + int grainSize = 800; + btParallelFor(0, numConstraints, grainSize, loop); } - inline bool BatchCompare(const btBatchedConstraints::Range& a, const btBatchedConstraints::Range& b) { - int lenA = a.end - a.begin; - int lenB = b.end - b.begin; - return lenA > lenB; + int lenA = a.end - a.begin; + int lenB = b.end - b.begin; + return lenA > lenB; } - static void writeOutConstraintIndicesForRangeOfBatches(btBatchedConstraints* bc, - const int* constraintBatchIds, - int numConstraints, - int* constraintIdPerBatch, - int batchBegin, - int batchEnd - ) + const int* constraintBatchIds, + int numConstraints, + int* constraintIdPerBatch, + int batchBegin, + int batchEnd) { - BT_PROFILE("writeOutConstraintIndicesForRangeOfBatches"); - for ( int iCon = 0; iCon < numConstraints; ++iCon ) - { - int iBatch = constraintBatchIds[ iCon ]; - if (iBatch >= batchBegin && iBatch < batchEnd) - { - int iDestCon = constraintIdPerBatch[ iBatch ]; - constraintIdPerBatch[ iBatch ] = iDestCon + 1; - bc->m_constraintIndices[ iDestCon ] = iCon; - } - } + BT_PROFILE("writeOutConstraintIndicesForRangeOfBatches"); + for (int iCon = 0; iCon < numConstraints; ++iCon) + { + int iBatch = constraintBatchIds[iCon]; + if (iBatch >= batchBegin && iBatch < batchEnd) + { + int iDestCon = constraintIdPerBatch[iBatch]; + constraintIdPerBatch[iBatch] = iDestCon + 1; + bc->m_constraintIndices[iDestCon] = iCon; + } + } } - struct WriteOutConstraintIndicesLoop : public btIParallelForBody { - btBatchedConstraints* m_batchedConstraints; - const int* m_constraintBatchIds; - int m_numConstraints; - int* m_constraintIdPerBatch; - int m_maxNumBatchesPerPhase; - - WriteOutConstraintIndicesLoop( btBatchedConstraints* bc, const int* constraintBatchIds, int numConstraints, int* constraintIdPerBatch, int maxNumBatchesPerPhase ) - { - m_batchedConstraints = bc; - m_constraintBatchIds = constraintBatchIds; - m_numConstraints = numConstraints; - m_constraintIdPerBatch = constraintIdPerBatch; - m_maxNumBatchesPerPhase = maxNumBatchesPerPhase; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "WriteOutConstraintIndicesLoop" ); - int batchBegin = iBegin * m_maxNumBatchesPerPhase; - int batchEnd = iEnd * m_maxNumBatchesPerPhase; - writeOutConstraintIndicesForRangeOfBatches(m_batchedConstraints, - m_constraintBatchIds, - m_numConstraints, - m_constraintIdPerBatch, - batchBegin, - batchEnd - ); - } + btBatchedConstraints* m_batchedConstraints; + const int* m_constraintBatchIds; + int m_numConstraints; + int* m_constraintIdPerBatch; + int m_maxNumBatchesPerPhase; + + WriteOutConstraintIndicesLoop(btBatchedConstraints* bc, const int* constraintBatchIds, int numConstraints, int* constraintIdPerBatch, int maxNumBatchesPerPhase) + { + m_batchedConstraints = bc; + m_constraintBatchIds = constraintBatchIds; + m_numConstraints = numConstraints; + m_constraintIdPerBatch = constraintIdPerBatch; + m_maxNumBatchesPerPhase = maxNumBatchesPerPhase; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("WriteOutConstraintIndicesLoop"); + int batchBegin = iBegin * m_maxNumBatchesPerPhase; + int batchEnd = iEnd * m_maxNumBatchesPerPhase; + writeOutConstraintIndicesForRangeOfBatches(m_batchedConstraints, + m_constraintBatchIds, + m_numConstraints, + m_constraintIdPerBatch, + batchBegin, + batchEnd); + } }; - static void writeOutConstraintIndicesMt(btBatchedConstraints* bc, - const int* constraintBatchIds, - int numConstraints, - int* constraintIdPerBatch, - int maxNumBatchesPerPhase, - int numPhases - ) + const int* constraintBatchIds, + int numConstraints, + int* constraintIdPerBatch, + int maxNumBatchesPerPhase, + int numPhases) { - BT_PROFILE("writeOutConstraintIndicesMt"); - bool inParallel = true; - if (inParallel) - { - WriteOutConstraintIndicesLoop loop( bc, constraintBatchIds, numConstraints, constraintIdPerBatch, maxNumBatchesPerPhase ); - btParallelFor( 0, numPhases, 1, loop ); - } - else - { - for ( int iCon = 0; iCon < numConstraints; ++iCon ) - { - int iBatch = constraintBatchIds[ iCon ]; - int iDestCon = constraintIdPerBatch[ iBatch ]; - constraintIdPerBatch[ iBatch ] = iDestCon + 1; - bc->m_constraintIndices[ iDestCon ] = iCon; - } - } + BT_PROFILE("writeOutConstraintIndicesMt"); + bool inParallel = true; + if (inParallel) + { + WriteOutConstraintIndicesLoop loop(bc, constraintBatchIds, numConstraints, constraintIdPerBatch, maxNumBatchesPerPhase); + btParallelFor(0, numPhases, 1, loop); + } + else + { + for (int iCon = 0; iCon < numConstraints; ++iCon) + { + int iBatch = constraintBatchIds[iCon]; + int iDestCon = constraintIdPerBatch[iBatch]; + constraintIdPerBatch[iBatch] = iDestCon + 1; + bc->m_constraintIndices[iDestCon] = iCon; + } + } } - static void writeGrainSizes(btBatchedConstraints* bc) { - typedef btBatchedConstraints::Range Range; - int numPhases = bc->m_phases.size(); - bc->m_phaseGrainSize.resizeNoInitialize(numPhases); - int numThreads = btGetTaskScheduler()->getNumThreads(); - for (int iPhase = 0; iPhase < numPhases; ++iPhase) - { - const Range& phase = bc->m_phases[ iPhase ]; - int numBatches = phase.end - phase.begin; - float grainSize = floor((0.25f*numBatches / float(numThreads)) + 0.0f); - bc->m_phaseGrainSize[ iPhase ] = btMax(1, int(grainSize)); - } + typedef btBatchedConstraints::Range Range; + int numPhases = bc->m_phases.size(); + bc->m_phaseGrainSize.resizeNoInitialize(numPhases); + int numThreads = btGetTaskScheduler()->getNumThreads(); + for (int iPhase = 0; iPhase < numPhases; ++iPhase) + { + const Range& phase = bc->m_phases[iPhase]; + int numBatches = phase.end - phase.begin; + float grainSize = floor((0.25f * numBatches / float(numThreads)) + 0.0f); + bc->m_phaseGrainSize[iPhase] = btMax(1, int(grainSize)); + } } - static void writeOutBatches(btBatchedConstraints* bc, - const int* constraintBatchIds, - int numConstraints, - const btBatchInfo* batches, - int* batchWork, - int maxNumBatchesPerPhase, - int numPhases -) + const int* constraintBatchIds, + int numConstraints, + const btBatchInfo* batches, + int* batchWork, + int maxNumBatchesPerPhase, + int numPhases) { - BT_PROFILE("writeOutBatches"); - typedef btBatchedConstraints::Range Range; - bc->m_constraintIndices.reserve( numConstraints ); - bc->m_batches.resizeNoInitialize( 0 ); - bc->m_phases.resizeNoInitialize( 0 ); - - //int maxNumBatches = numPhases * maxNumBatchesPerPhase; - { - int* constraintIdPerBatch = batchWork; // for each batch, keep an index into the next available slot in the m_constraintIndices array - int iConstraint = 0; - for (int iPhase = 0; iPhase < numPhases; ++iPhase) - { - int curPhaseBegin = bc->m_batches.size(); - int iBegin = iPhase * maxNumBatchesPerPhase; - int iEnd = iBegin + maxNumBatchesPerPhase; - for ( int i = iBegin; i < iEnd; ++i ) - { - const btBatchInfo& batch = batches[ i ]; - int curBatchBegin = iConstraint; - constraintIdPerBatch[ i ] = curBatchBegin; // record the start of each batch in m_constraintIndices array - int numConstraints = batch.numConstraints; - iConstraint += numConstraints; - if ( numConstraints > 0 ) - { - bc->m_batches.push_back( Range( curBatchBegin, iConstraint ) ); - } - } - // if any batches were emitted this phase, - if ( bc->m_batches.size() > curPhaseBegin ) - { - // output phase - bc->m_phases.push_back( Range( curPhaseBegin, bc->m_batches.size() ) ); - } - } - - btAssert(iConstraint == numConstraints); - bc->m_constraintIndices.resizeNoInitialize( numConstraints ); - writeOutConstraintIndicesMt( bc, constraintBatchIds, numConstraints, constraintIdPerBatch, maxNumBatchesPerPhase, numPhases ); - } - // for each phase - for (int iPhase = 0; iPhase < bc->m_phases.size(); ++iPhase) - { - // sort the batches from largest to smallest (can be helpful to some task schedulers) - const Range& curBatches = bc->m_phases[iPhase]; - bc->m_batches.quickSortInternal(BatchCompare, curBatches.begin, curBatches.end-1); - } - bc->m_phaseOrder.resize(bc->m_phases.size()); - for (int i = 0; i < bc->m_phases.size(); ++i) - { - bc->m_phaseOrder[i] = i; - } - writeGrainSizes(bc); + BT_PROFILE("writeOutBatches"); + typedef btBatchedConstraints::Range Range; + bc->m_constraintIndices.reserve(numConstraints); + bc->m_batches.resizeNoInitialize(0); + bc->m_phases.resizeNoInitialize(0); + + //int maxNumBatches = numPhases * maxNumBatchesPerPhase; + { + int* constraintIdPerBatch = batchWork; // for each batch, keep an index into the next available slot in the m_constraintIndices array + int iConstraint = 0; + for (int iPhase = 0; iPhase < numPhases; ++iPhase) + { + int curPhaseBegin = bc->m_batches.size(); + int iBegin = iPhase * maxNumBatchesPerPhase; + int iEnd = iBegin + maxNumBatchesPerPhase; + for (int i = iBegin; i < iEnd; ++i) + { + const btBatchInfo& batch = batches[i]; + int curBatchBegin = iConstraint; + constraintIdPerBatch[i] = curBatchBegin; // record the start of each batch in m_constraintIndices array + int numConstraints = batch.numConstraints; + iConstraint += numConstraints; + if (numConstraints > 0) + { + bc->m_batches.push_back(Range(curBatchBegin, iConstraint)); + } + } + // if any batches were emitted this phase, + if (bc->m_batches.size() > curPhaseBegin) + { + // output phase + bc->m_phases.push_back(Range(curPhaseBegin, bc->m_batches.size())); + } + } + + btAssert(iConstraint == numConstraints); + bc->m_constraintIndices.resizeNoInitialize(numConstraints); + writeOutConstraintIndicesMt(bc, constraintBatchIds, numConstraints, constraintIdPerBatch, maxNumBatchesPerPhase, numPhases); + } + // for each phase + for (int iPhase = 0; iPhase < bc->m_phases.size(); ++iPhase) + { + // sort the batches from largest to smallest (can be helpful to some task schedulers) + const Range& curBatches = bc->m_phases[iPhase]; + bc->m_batches.quickSortInternal(BatchCompare, curBatches.begin, curBatches.end - 1); + } + bc->m_phaseOrder.resize(bc->m_phases.size()); + for (int i = 0; i < bc->m_phases.size(); ++i) + { + bc->m_phaseOrder[i] = i; + } + writeGrainSizes(bc); } - // // PreallocatedMemoryHelper -- helper object for allocating a number of chunks of memory in a single contiguous block. // It is generally more efficient to do a single larger allocation than many smaller allocations. @@ -639,191 +605,184 @@ static void writeOutBatches(btBatchedConstraints* bc, template <int N> class PreallocatedMemoryHelper { - struct Chunk - { - void** ptr; - size_t size; - }; - Chunk m_chunks[N]; - int m_numChunks; + struct Chunk + { + void** ptr; + size_t size; + }; + Chunk m_chunks[N]; + int m_numChunks; + public: - PreallocatedMemoryHelper() {m_numChunks=0;} - void addChunk( void** ptr, size_t sz ) - { - btAssert( m_numChunks < N ); - if ( m_numChunks < N ) - { - Chunk& chunk = m_chunks[ m_numChunks ]; - chunk.ptr = ptr; - chunk.size = sz; - m_numChunks++; - } - } - size_t getSizeToAllocate() const - { - size_t totalSize = 0; - for (int i = 0; i < m_numChunks; ++i) - { - totalSize += m_chunks[i].size; - } - return totalSize; - } - void setChunkPointers(void* mem) const - { - size_t totalSize = 0; - for (int i = 0; i < m_numChunks; ++i) - { - const Chunk& chunk = m_chunks[ i ]; - char* chunkPtr = static_cast<char*>(mem) + totalSize; - *chunk.ptr = chunkPtr; - totalSize += chunk.size; - } - } + PreallocatedMemoryHelper() { m_numChunks = 0; } + void addChunk(void** ptr, size_t sz) + { + btAssert(m_numChunks < N); + if (m_numChunks < N) + { + Chunk& chunk = m_chunks[m_numChunks]; + chunk.ptr = ptr; + chunk.size = sz; + m_numChunks++; + } + } + size_t getSizeToAllocate() const + { + size_t totalSize = 0; + for (int i = 0; i < m_numChunks; ++i) + { + totalSize += m_chunks[i].size; + } + return totalSize; + } + void setChunkPointers(void* mem) const + { + size_t totalSize = 0; + for (int i = 0; i < m_numChunks; ++i) + { + const Chunk& chunk = m_chunks[i]; + char* chunkPtr = static_cast<char*>(mem) + totalSize; + *chunk.ptr = chunkPtr; + totalSize += chunk.size; + } + } }; - - static btVector3 findMaxDynamicConstraintExtent( - btVector3* bodyPositions, - bool* bodyDynamicFlags, - btBatchedConstraintInfo* conInfos, - int numConstraints, - int numBodies - ) + btVector3* bodyPositions, + bool* bodyDynamicFlags, + btBatchedConstraintInfo* conInfos, + int numConstraints, + int numBodies) { - BT_PROFILE("findMaxDynamicConstraintExtent"); - btVector3 consExtent = btVector3(1,1,1) * 0.001; - for (int iCon = 0; iCon < numConstraints; ++iCon) - { - const btBatchedConstraintInfo& con = conInfos[ iCon ]; - int iBody0 = con.bodyIds[0]; - int iBody1 = con.bodyIds[1]; - btAssert(iBody0 >= 0 && iBody0 < numBodies); - btAssert(iBody1 >= 0 && iBody1 < numBodies); - // is it a dynamic constraint? - if (bodyDynamicFlags[iBody0] && bodyDynamicFlags[iBody1]) - { - btVector3 delta = bodyPositions[iBody1] - bodyPositions[iBody0]; - consExtent.setMax(delta.absolute()); - } - } - return consExtent; + BT_PROFILE("findMaxDynamicConstraintExtent"); + btVector3 consExtent = btVector3(1, 1, 1) * 0.001; + for (int iCon = 0; iCon < numConstraints; ++iCon) + { + const btBatchedConstraintInfo& con = conInfos[iCon]; + int iBody0 = con.bodyIds[0]; + int iBody1 = con.bodyIds[1]; + btAssert(iBody0 >= 0 && iBody0 < numBodies); + btAssert(iBody1 >= 0 && iBody1 < numBodies); + // is it a dynamic constraint? + if (bodyDynamicFlags[iBody0] && bodyDynamicFlags[iBody1]) + { + btVector3 delta = bodyPositions[iBody1] - bodyPositions[iBody0]; + consExtent.setMax(delta.absolute()); + } + } + return consExtent; } - struct btIntVec3 { - int m_ints[ 3 ]; + int m_ints[3]; - SIMD_FORCE_INLINE const int& operator[](int i) const {return m_ints[i];} - SIMD_FORCE_INLINE int& operator[](int i) {return m_ints[i];} + SIMD_FORCE_INLINE const int& operator[](int i) const { return m_ints[i]; } + SIMD_FORCE_INLINE int& operator[](int i) { return m_ints[i]; } }; - struct AssignConstraintsToGridBatchesParams { - bool* bodyDynamicFlags; - btIntVec3* bodyGridCoords; - int numBodies; - btBatchedConstraintInfo* conInfos; - int* constraintBatchIds; - btIntVec3 gridChunkDim; - int maxNumBatchesPerPhase; - int numPhases; - int phaseMask; - - AssignConstraintsToGridBatchesParams() - { - memset(this, 0, sizeof(*this)); - } + bool* bodyDynamicFlags; + btIntVec3* bodyGridCoords; + int numBodies; + btBatchedConstraintInfo* conInfos; + int* constraintBatchIds; + btIntVec3 gridChunkDim; + int maxNumBatchesPerPhase; + int numPhases; + int phaseMask; + + AssignConstraintsToGridBatchesParams() + { + memset(this, 0, sizeof(*this)); + } }; - static void assignConstraintsToGridBatches(const AssignConstraintsToGridBatchesParams& params, int iConBegin, int iConEnd) { - BT_PROFILE("assignConstraintsToGridBatches"); - // (can be done in parallel) - for ( int iCon = iConBegin; iCon < iConEnd; ++iCon ) - { - const btBatchedConstraintInfo& con = params.conInfos[ iCon ]; - int iBody0 = con.bodyIds[ 0 ]; - int iBody1 = con.bodyIds[ 1 ]; - int iPhase = iCon; //iBody0; // pseudorandom choice to distribute evenly amongst phases - iPhase &= params.phaseMask; - int gridCoord[ 3 ]; - // is it a dynamic constraint? - if ( params.bodyDynamicFlags[ iBody0 ] && params.bodyDynamicFlags[ iBody1 ] ) - { - const btIntVec3& body0Coords = params.bodyGridCoords[iBody0]; - const btIntVec3& body1Coords = params.bodyGridCoords[iBody1]; - // for each dimension x,y,z, - for (int i = 0; i < 3; ++i) - { - int coordMin = btMin(body0Coords.m_ints[i], body1Coords.m_ints[i]); - int coordMax = btMax(body0Coords.m_ints[i], body1Coords.m_ints[i]); - if (coordMin != coordMax) - { - btAssert( coordMax == coordMin + 1 ); - if ((coordMin&1) == 0) - { - iPhase &= ~(1 << i); // force bit off - } - else - { - iPhase |= (1 << i); // force bit on - iPhase &= params.phaseMask; - } - } - gridCoord[ i ] = coordMin; - } - } - else - { - if ( !params.bodyDynamicFlags[ iBody0 ] ) - { - iBody0 = con.bodyIds[ 1 ]; - } - btAssert(params.bodyDynamicFlags[ iBody0 ]); - const btIntVec3& body0Coords = params.bodyGridCoords[iBody0]; - // for each dimension x,y,z, - for ( int i = 0; i < 3; ++i ) - { - gridCoord[ i ] = body0Coords.m_ints[ i ]; - } - } - // calculate chunk coordinates - int chunkCoord[ 3 ]; - btIntVec3 gridChunkDim = params.gridChunkDim; - // for each dimension x,y,z, - for ( int i = 0; i < 3; ++i ) - { - int coordOffset = ( iPhase >> i ) & 1; - chunkCoord[ i ] = (gridCoord[ i ] - coordOffset)/2; - btClamp( chunkCoord[ i ], 0, gridChunkDim[ i ] - 1); - btAssert( chunkCoord[ i ] < gridChunkDim[ i ] ); - } - int iBatch = iPhase * params.maxNumBatchesPerPhase + chunkCoord[ 0 ] + chunkCoord[ 1 ] * gridChunkDim[ 0 ] + chunkCoord[ 2 ] * gridChunkDim[ 0 ] * gridChunkDim[ 1 ]; - btAssert(iBatch >= 0 && iBatch < params.maxNumBatchesPerPhase*params.numPhases); - params.constraintBatchIds[ iCon ] = iBatch; - } + BT_PROFILE("assignConstraintsToGridBatches"); + // (can be done in parallel) + for (int iCon = iConBegin; iCon < iConEnd; ++iCon) + { + const btBatchedConstraintInfo& con = params.conInfos[iCon]; + int iBody0 = con.bodyIds[0]; + int iBody1 = con.bodyIds[1]; + int iPhase = iCon; //iBody0; // pseudorandom choice to distribute evenly amongst phases + iPhase &= params.phaseMask; + int gridCoord[3]; + // is it a dynamic constraint? + if (params.bodyDynamicFlags[iBody0] && params.bodyDynamicFlags[iBody1]) + { + const btIntVec3& body0Coords = params.bodyGridCoords[iBody0]; + const btIntVec3& body1Coords = params.bodyGridCoords[iBody1]; + // for each dimension x,y,z, + for (int i = 0; i < 3; ++i) + { + int coordMin = btMin(body0Coords.m_ints[i], body1Coords.m_ints[i]); + int coordMax = btMax(body0Coords.m_ints[i], body1Coords.m_ints[i]); + if (coordMin != coordMax) + { + btAssert(coordMax == coordMin + 1); + if ((coordMin & 1) == 0) + { + iPhase &= ~(1 << i); // force bit off + } + else + { + iPhase |= (1 << i); // force bit on + iPhase &= params.phaseMask; + } + } + gridCoord[i] = coordMin; + } + } + else + { + if (!params.bodyDynamicFlags[iBody0]) + { + iBody0 = con.bodyIds[1]; + } + btAssert(params.bodyDynamicFlags[iBody0]); + const btIntVec3& body0Coords = params.bodyGridCoords[iBody0]; + // for each dimension x,y,z, + for (int i = 0; i < 3; ++i) + { + gridCoord[i] = body0Coords.m_ints[i]; + } + } + // calculate chunk coordinates + int chunkCoord[3]; + btIntVec3 gridChunkDim = params.gridChunkDim; + // for each dimension x,y,z, + for (int i = 0; i < 3; ++i) + { + int coordOffset = (iPhase >> i) & 1; + chunkCoord[i] = (gridCoord[i] - coordOffset) / 2; + btClamp(chunkCoord[i], 0, gridChunkDim[i] - 1); + btAssert(chunkCoord[i] < gridChunkDim[i]); + } + int iBatch = iPhase * params.maxNumBatchesPerPhase + chunkCoord[0] + chunkCoord[1] * gridChunkDim[0] + chunkCoord[2] * gridChunkDim[0] * gridChunkDim[1]; + btAssert(iBatch >= 0 && iBatch < params.maxNumBatchesPerPhase * params.numPhases); + params.constraintBatchIds[iCon] = iBatch; + } } - struct AssignConstraintsToGridBatchesLoop : public btIParallelForBody { - const AssignConstraintsToGridBatchesParams* m_params; - - AssignConstraintsToGridBatchesLoop( const AssignConstraintsToGridBatchesParams& params ) - { - m_params = ¶ms; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - assignConstraintsToGridBatches(*m_params, iBegin, iEnd); - } + const AssignConstraintsToGridBatchesParams* m_params; + + AssignConstraintsToGridBatchesLoop(const AssignConstraintsToGridBatchesParams& params) + { + m_params = ¶ms; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + assignConstraintsToGridBatches(*m_params, iBegin, iEnd); + } }; - // // setupSpatialGridBatchesMt -- generate batches using a uniform 3D grid // @@ -853,276 +812,269 @@ to 4. With fewer phases, there are more constraints per phase and this makes it */ // static void setupSpatialGridBatchesMt( - btBatchedConstraints* batchedConstraints, - btAlignedObjectArray<char>* scratchMemory, - btConstraintArray* constraints, - const btAlignedObjectArray<btSolverBody>& bodies, - int minBatchSize, - int maxBatchSize, - bool use2DGrid -) + btBatchedConstraints* batchedConstraints, + btAlignedObjectArray<char>* scratchMemory, + btConstraintArray* constraints, + const btAlignedObjectArray<btSolverBody>& bodies, + int minBatchSize, + int maxBatchSize, + bool use2DGrid) { - BT_PROFILE("setupSpatialGridBatchesMt"); - const int numPhases = 8; - int numConstraints = constraints->size(); - int numConstraintRows = constraints->size(); - - const int maxGridChunkCount = 128; - int allocNumBatchesPerPhase = maxGridChunkCount; - int minNumBatchesPerPhase = 16; - int allocNumBatches = allocNumBatchesPerPhase * numPhases; - - btVector3* bodyPositions = NULL; - bool* bodyDynamicFlags = NULL; - btIntVec3* bodyGridCoords = NULL; - btBatchInfo* batches = NULL; - int* batchWork = NULL; - btBatchedConstraintInfo* conInfos = NULL; - int* constraintBatchIds = NULL; - int* constraintRowBatchIds = NULL; - { - PreallocatedMemoryHelper<10> memHelper; - memHelper.addChunk( (void**) &bodyPositions, sizeof( btVector3 ) * bodies.size() ); - memHelper.addChunk( (void**) &bodyDynamicFlags, sizeof( bool ) * bodies.size() ); - memHelper.addChunk( (void**) &bodyGridCoords, sizeof( btIntVec3 ) * bodies.size() ); - memHelper.addChunk( (void**) &batches, sizeof( btBatchInfo )* allocNumBatches ); - memHelper.addChunk( (void**) &batchWork, sizeof( int )* allocNumBatches ); - memHelper.addChunk( (void**) &conInfos, sizeof( btBatchedConstraintInfo ) * numConstraints ); - memHelper.addChunk( (void**) &constraintBatchIds, sizeof( int ) * numConstraints ); - memHelper.addChunk( (void**) &constraintRowBatchIds, sizeof( int ) * numConstraintRows ); - size_t scratchSize = memHelper.getSizeToAllocate(); - // if we need to reallocate - if (scratchMemory->capacity() < scratchSize) - { - // allocate 6.25% extra to avoid repeated reallocs - scratchMemory->reserve( scratchSize + scratchSize/16 ); - } - scratchMemory->resizeNoInitialize( scratchSize ); - char* memPtr = &scratchMemory->at(0); - memHelper.setChunkPointers( memPtr ); - } - - numConstraints = initBatchedConstraintInfo(conInfos, constraints); - - // compute bounding box around all dynamic bodies - // (could be done in parallel) - btVector3 bboxMin(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT); - btVector3 bboxMax = -bboxMin; - //int dynamicBodyCount = 0; - for (int i = 0; i < bodies.size(); ++i) - { - const btSolverBody& body = bodies[i]; - btVector3 bodyPos = body.getWorldTransform().getOrigin(); - bool isDynamic = ( body.internalGetInvMass().x() > btScalar( 0 ) ); - bodyPositions[i] = bodyPos; - bodyDynamicFlags[i] = isDynamic; - if (isDynamic) - { - //dynamicBodyCount++; - bboxMin.setMin(bodyPos); - bboxMax.setMax(bodyPos); - } - } - - // find max extent of all dynamic constraints - // (could be done in parallel) - btVector3 consExtent = findMaxDynamicConstraintExtent(bodyPositions, bodyDynamicFlags, conInfos, numConstraints, bodies.size()); - - btVector3 gridExtent = bboxMax - bboxMin; - - btVector3 gridCellSize = consExtent; - int gridDim[3]; - gridDim[ 0 ] = int( 1.0 + gridExtent.x() / gridCellSize.x() ); - gridDim[ 1 ] = int( 1.0 + gridExtent.y() / gridCellSize.y() ); - gridDim[ 2 ] = int( 1.0 + gridExtent.z() / gridCellSize.z() ); - - // if we can collapse an axis, it will cut our number of phases in half which could be more efficient - int phaseMask = 7; - bool collapseAxis = use2DGrid; - if ( collapseAxis ) - { - // pick the smallest axis to collapse, leaving us with the greatest number of cells in our grid - int iAxisToCollapse = 0; - int axisDim = gridDim[iAxisToCollapse]; - //for each dimension - for ( int i = 0; i < 3; ++i ) - { - if (gridDim[i] < axisDim) - { - iAxisToCollapse = i; - axisDim = gridDim[i]; - } - } - // collapse it - gridCellSize[iAxisToCollapse] = gridExtent[iAxisToCollapse] * 2.0f; - phaseMask &= ~(1 << iAxisToCollapse); - } - - int numGridChunks = 0; - btIntVec3 gridChunkDim; // each chunk is 2x2x2 group of cells - while (true) - { - gridDim[0] = int( 1.0 + gridExtent.x() / gridCellSize.x() ); - gridDim[1] = int( 1.0 + gridExtent.y() / gridCellSize.y() ); - gridDim[2] = int( 1.0 + gridExtent.z() / gridCellSize.z() ); - gridChunkDim[ 0 ] = btMax( 1, ( gridDim[ 0 ] + 0 ) / 2 ); - gridChunkDim[ 1 ] = btMax( 1, ( gridDim[ 1 ] + 0 ) / 2 ); - gridChunkDim[ 2 ] = btMax( 1, ( gridDim[ 2 ] + 0 ) / 2 ); - numGridChunks = gridChunkDim[ 0 ] * gridChunkDim[ 1 ] * gridChunkDim[ 2 ]; - float nChunks = float(gridChunkDim[0]) * float(gridChunkDim[1]) * float(gridChunkDim[2]); // suceptible to integer overflow - if ( numGridChunks <= maxGridChunkCount && nChunks <= maxGridChunkCount ) - { - break; - } - gridCellSize *= 1.25; // should roughly cut numCells in half - } - btAssert(numGridChunks <= maxGridChunkCount ); - int maxNumBatchesPerPhase = numGridChunks; - - // for each dynamic body, compute grid coords - btVector3 invGridCellSize = btVector3(1,1,1)/gridCellSize; - // (can be done in parallel) - for (int iBody = 0; iBody < bodies.size(); ++iBody) - { - btIntVec3& coords = bodyGridCoords[iBody]; - if (bodyDynamicFlags[iBody]) - { - btVector3 v = ( bodyPositions[ iBody ] - bboxMin )*invGridCellSize; - coords.m_ints[0] = int(v.x()); - coords.m_ints[1] = int(v.y()); - coords.m_ints[2] = int(v.z()); - btAssert(coords.m_ints[0] >= 0 && coords.m_ints[0] < gridDim[0]); - btAssert(coords.m_ints[1] >= 0 && coords.m_ints[1] < gridDim[1]); - btAssert(coords.m_ints[2] >= 0 && coords.m_ints[2] < gridDim[2]); - } - else - { - coords.m_ints[0] = -1; - coords.m_ints[1] = -1; - coords.m_ints[2] = -1; - } - } - - for (int iPhase = 0; iPhase < numPhases; ++iPhase) - { - int batchBegin = iPhase * maxNumBatchesPerPhase; - int batchEnd = batchBegin + maxNumBatchesPerPhase; - for ( int iBatch = batchBegin; iBatch < batchEnd; ++iBatch ) - { - btBatchInfo& batch = batches[ iBatch ]; - batch = btBatchInfo(); - } - } - - { - AssignConstraintsToGridBatchesParams params; - params.bodyDynamicFlags = bodyDynamicFlags; - params.bodyGridCoords = bodyGridCoords; - params.numBodies = bodies.size(); - params.conInfos = conInfos; - params.constraintBatchIds = constraintBatchIds; - params.gridChunkDim = gridChunkDim; - params.maxNumBatchesPerPhase = maxNumBatchesPerPhase; - params.numPhases = numPhases; - params.phaseMask = phaseMask; - bool inParallel = true; - if (inParallel) - { - AssignConstraintsToGridBatchesLoop loop(params); - int grainSize = 250; - btParallelFor(0, numConstraints, grainSize, loop); - } - else - { - assignConstraintsToGridBatches( params, 0, numConstraints ); - } - } - for ( int iCon = 0; iCon < numConstraints; ++iCon ) - { - const btBatchedConstraintInfo& con = conInfos[ iCon ]; - int iBatch = constraintBatchIds[ iCon ]; - btBatchInfo& batch = batches[iBatch]; - batch.numConstraints += con.numConstraintRows; - } - - for (int iPhase = 0; iPhase < numPhases; ++iPhase) - { - // if phase is legit, - if (iPhase == (iPhase&phaseMask)) - { - int iBeginBatch = iPhase * maxNumBatchesPerPhase; - int iEndBatch = iBeginBatch + maxNumBatchesPerPhase; - mergeSmallBatches( batches, iBeginBatch, iEndBatch, minBatchSize, maxBatchSize ); - } - } - // all constraints have been assigned a batchId - updateConstraintBatchIdsForMergesMt(constraintBatchIds, numConstraints, batches, maxNumBatchesPerPhase*numPhases); - - if (numConstraintRows > numConstraints) - { - expandConstraintRowsMt(&constraintRowBatchIds[0], &constraintBatchIds[0], &conInfos[0], numConstraints, numConstraintRows); - } - else - { - constraintRowBatchIds = constraintBatchIds; - } - - writeOutBatches(batchedConstraints, constraintRowBatchIds, numConstraintRows, batches, batchWork, maxNumBatchesPerPhase, numPhases); - btAssert(batchedConstraints->validate(constraints, bodies)); + BT_PROFILE("setupSpatialGridBatchesMt"); + const int numPhases = 8; + int numConstraints = constraints->size(); + int numConstraintRows = constraints->size(); + + const int maxGridChunkCount = 128; + int allocNumBatchesPerPhase = maxGridChunkCount; + int minNumBatchesPerPhase = 16; + int allocNumBatches = allocNumBatchesPerPhase * numPhases; + + btVector3* bodyPositions = NULL; + bool* bodyDynamicFlags = NULL; + btIntVec3* bodyGridCoords = NULL; + btBatchInfo* batches = NULL; + int* batchWork = NULL; + btBatchedConstraintInfo* conInfos = NULL; + int* constraintBatchIds = NULL; + int* constraintRowBatchIds = NULL; + { + PreallocatedMemoryHelper<10> memHelper; + memHelper.addChunk((void**)&bodyPositions, sizeof(btVector3) * bodies.size()); + memHelper.addChunk((void**)&bodyDynamicFlags, sizeof(bool) * bodies.size()); + memHelper.addChunk((void**)&bodyGridCoords, sizeof(btIntVec3) * bodies.size()); + memHelper.addChunk((void**)&batches, sizeof(btBatchInfo) * allocNumBatches); + memHelper.addChunk((void**)&batchWork, sizeof(int) * allocNumBatches); + memHelper.addChunk((void**)&conInfos, sizeof(btBatchedConstraintInfo) * numConstraints); + memHelper.addChunk((void**)&constraintBatchIds, sizeof(int) * numConstraints); + memHelper.addChunk((void**)&constraintRowBatchIds, sizeof(int) * numConstraintRows); + size_t scratchSize = memHelper.getSizeToAllocate(); + // if we need to reallocate + if (scratchMemory->capacity() < scratchSize) + { + // allocate 6.25% extra to avoid repeated reallocs + scratchMemory->reserve(scratchSize + scratchSize / 16); + } + scratchMemory->resizeNoInitialize(scratchSize); + char* memPtr = &scratchMemory->at(0); + memHelper.setChunkPointers(memPtr); + } + + numConstraints = initBatchedConstraintInfo(conInfos, constraints); + + // compute bounding box around all dynamic bodies + // (could be done in parallel) + btVector3 bboxMin(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT); + btVector3 bboxMax = -bboxMin; + //int dynamicBodyCount = 0; + for (int i = 0; i < bodies.size(); ++i) + { + const btSolverBody& body = bodies[i]; + btVector3 bodyPos = body.getWorldTransform().getOrigin(); + bool isDynamic = (body.internalGetInvMass().x() > btScalar(0)); + bodyPositions[i] = bodyPos; + bodyDynamicFlags[i] = isDynamic; + if (isDynamic) + { + //dynamicBodyCount++; + bboxMin.setMin(bodyPos); + bboxMax.setMax(bodyPos); + } + } + + // find max extent of all dynamic constraints + // (could be done in parallel) + btVector3 consExtent = findMaxDynamicConstraintExtent(bodyPositions, bodyDynamicFlags, conInfos, numConstraints, bodies.size()); + + btVector3 gridExtent = bboxMax - bboxMin; + + btVector3 gridCellSize = consExtent; + int gridDim[3]; + gridDim[0] = int(1.0 + gridExtent.x() / gridCellSize.x()); + gridDim[1] = int(1.0 + gridExtent.y() / gridCellSize.y()); + gridDim[2] = int(1.0 + gridExtent.z() / gridCellSize.z()); + + // if we can collapse an axis, it will cut our number of phases in half which could be more efficient + int phaseMask = 7; + bool collapseAxis = use2DGrid; + if (collapseAxis) + { + // pick the smallest axis to collapse, leaving us with the greatest number of cells in our grid + int iAxisToCollapse = 0; + int axisDim = gridDim[iAxisToCollapse]; + //for each dimension + for (int i = 0; i < 3; ++i) + { + if (gridDim[i] < axisDim) + { + iAxisToCollapse = i; + axisDim = gridDim[i]; + } + } + // collapse it + gridCellSize[iAxisToCollapse] = gridExtent[iAxisToCollapse] * 2.0f; + phaseMask &= ~(1 << iAxisToCollapse); + } + + int numGridChunks = 0; + btIntVec3 gridChunkDim; // each chunk is 2x2x2 group of cells + while (true) + { + gridDim[0] = int(1.0 + gridExtent.x() / gridCellSize.x()); + gridDim[1] = int(1.0 + gridExtent.y() / gridCellSize.y()); + gridDim[2] = int(1.0 + gridExtent.z() / gridCellSize.z()); + gridChunkDim[0] = btMax(1, (gridDim[0] + 0) / 2); + gridChunkDim[1] = btMax(1, (gridDim[1] + 0) / 2); + gridChunkDim[2] = btMax(1, (gridDim[2] + 0) / 2); + numGridChunks = gridChunkDim[0] * gridChunkDim[1] * gridChunkDim[2]; + float nChunks = float(gridChunkDim[0]) * float(gridChunkDim[1]) * float(gridChunkDim[2]); // suceptible to integer overflow + if (numGridChunks <= maxGridChunkCount && nChunks <= maxGridChunkCount) + { + break; + } + gridCellSize *= 1.25; // should roughly cut numCells in half + } + btAssert(numGridChunks <= maxGridChunkCount); + int maxNumBatchesPerPhase = numGridChunks; + + // for each dynamic body, compute grid coords + btVector3 invGridCellSize = btVector3(1, 1, 1) / gridCellSize; + // (can be done in parallel) + for (int iBody = 0; iBody < bodies.size(); ++iBody) + { + btIntVec3& coords = bodyGridCoords[iBody]; + if (bodyDynamicFlags[iBody]) + { + btVector3 v = (bodyPositions[iBody] - bboxMin) * invGridCellSize; + coords.m_ints[0] = int(v.x()); + coords.m_ints[1] = int(v.y()); + coords.m_ints[2] = int(v.z()); + btAssert(coords.m_ints[0] >= 0 && coords.m_ints[0] < gridDim[0]); + btAssert(coords.m_ints[1] >= 0 && coords.m_ints[1] < gridDim[1]); + btAssert(coords.m_ints[2] >= 0 && coords.m_ints[2] < gridDim[2]); + } + else + { + coords.m_ints[0] = -1; + coords.m_ints[1] = -1; + coords.m_ints[2] = -1; + } + } + + for (int iPhase = 0; iPhase < numPhases; ++iPhase) + { + int batchBegin = iPhase * maxNumBatchesPerPhase; + int batchEnd = batchBegin + maxNumBatchesPerPhase; + for (int iBatch = batchBegin; iBatch < batchEnd; ++iBatch) + { + btBatchInfo& batch = batches[iBatch]; + batch = btBatchInfo(); + } + } + + { + AssignConstraintsToGridBatchesParams params; + params.bodyDynamicFlags = bodyDynamicFlags; + params.bodyGridCoords = bodyGridCoords; + params.numBodies = bodies.size(); + params.conInfos = conInfos; + params.constraintBatchIds = constraintBatchIds; + params.gridChunkDim = gridChunkDim; + params.maxNumBatchesPerPhase = maxNumBatchesPerPhase; + params.numPhases = numPhases; + params.phaseMask = phaseMask; + bool inParallel = true; + if (inParallel) + { + AssignConstraintsToGridBatchesLoop loop(params); + int grainSize = 250; + btParallelFor(0, numConstraints, grainSize, loop); + } + else + { + assignConstraintsToGridBatches(params, 0, numConstraints); + } + } + for (int iCon = 0; iCon < numConstraints; ++iCon) + { + const btBatchedConstraintInfo& con = conInfos[iCon]; + int iBatch = constraintBatchIds[iCon]; + btBatchInfo& batch = batches[iBatch]; + batch.numConstraints += con.numConstraintRows; + } + + for (int iPhase = 0; iPhase < numPhases; ++iPhase) + { + // if phase is legit, + if (iPhase == (iPhase & phaseMask)) + { + int iBeginBatch = iPhase * maxNumBatchesPerPhase; + int iEndBatch = iBeginBatch + maxNumBatchesPerPhase; + mergeSmallBatches(batches, iBeginBatch, iEndBatch, minBatchSize, maxBatchSize); + } + } + // all constraints have been assigned a batchId + updateConstraintBatchIdsForMergesMt(constraintBatchIds, numConstraints, batches, maxNumBatchesPerPhase * numPhases); + + if (numConstraintRows > numConstraints) + { + expandConstraintRowsMt(&constraintRowBatchIds[0], &constraintBatchIds[0], &conInfos[0], numConstraints, numConstraintRows); + } + else + { + constraintRowBatchIds = constraintBatchIds; + } + + writeOutBatches(batchedConstraints, constraintRowBatchIds, numConstraintRows, batches, batchWork, maxNumBatchesPerPhase, numPhases); + btAssert(batchedConstraints->validate(constraints, bodies)); } - static void setupSingleBatch( - btBatchedConstraints* bc, - int numConstraints -) + btBatchedConstraints* bc, + int numConstraints) { - BT_PROFILE("setupSingleBatch"); - typedef btBatchedConstraints::Range Range; - - bc->m_constraintIndices.resize( numConstraints ); - for ( int i = 0; i < numConstraints; ++i ) - { - bc->m_constraintIndices[ i ] = i; - } - - bc->m_batches.resizeNoInitialize( 0 ); - bc->m_phases.resizeNoInitialize( 0 ); - bc->m_phaseOrder.resizeNoInitialize( 0 ); - bc->m_phaseGrainSize.resizeNoInitialize( 0 ); - - if (numConstraints > 0) - { - bc->m_batches.push_back( Range( 0, numConstraints ) ); - bc->m_phases.push_back( Range( 0, 1 ) ); - bc->m_phaseOrder.push_back(0); - bc->m_phaseGrainSize.push_back(1); - } + BT_PROFILE("setupSingleBatch"); + typedef btBatchedConstraints::Range Range; + + bc->m_constraintIndices.resize(numConstraints); + for (int i = 0; i < numConstraints; ++i) + { + bc->m_constraintIndices[i] = i; + } + + bc->m_batches.resizeNoInitialize(0); + bc->m_phases.resizeNoInitialize(0); + bc->m_phaseOrder.resizeNoInitialize(0); + bc->m_phaseGrainSize.resizeNoInitialize(0); + + if (numConstraints > 0) + { + bc->m_batches.push_back(Range(0, numConstraints)); + bc->m_phases.push_back(Range(0, 1)); + bc->m_phaseOrder.push_back(0); + bc->m_phaseGrainSize.push_back(1); + } } - void btBatchedConstraints::setup( - btConstraintArray* constraints, - const btAlignedObjectArray<btSolverBody>& bodies, - BatchingMethod batchingMethod, - int minBatchSize, - int maxBatchSize, - btAlignedObjectArray<char>* scratchMemory - ) + btConstraintArray* constraints, + const btAlignedObjectArray<btSolverBody>& bodies, + BatchingMethod batchingMethod, + int minBatchSize, + int maxBatchSize, + btAlignedObjectArray<char>* scratchMemory) { - if (constraints->size() >= minBatchSize*4) - { - bool use2DGrid = batchingMethod == BATCHING_METHOD_SPATIAL_GRID_2D; - setupSpatialGridBatchesMt( this, scratchMemory, constraints, bodies, minBatchSize, maxBatchSize, use2DGrid ); - if (s_debugDrawBatches) - { - debugDrawAllBatches( this, constraints, bodies ); - } - } - else - { - setupSingleBatch( this, constraints->size() ); - } + if (constraints->size() >= minBatchSize * 4) + { + bool use2DGrid = batchingMethod == BATCHING_METHOD_SPATIAL_GRID_2D; + setupSpatialGridBatchesMt(this, scratchMemory, constraints, bodies, minBatchSize, maxBatchSize, use2DGrid); + if (s_debugDrawBatches) + { + debugDrawAllBatches(this, constraints, bodies); + } + } + else + { + setupSingleBatch(this, constraints->size()); + } } - - diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.h index 0fd8f31dd4..5d982ca370 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.h @@ -21,46 +21,42 @@ subject to the following restrictions: #include "BulletDynamics/ConstraintSolver/btSolverBody.h" #include "BulletDynamics/ConstraintSolver/btSolverConstraint.h" - class btIDebugDraw; struct btBatchedConstraints { - enum BatchingMethod - { - BATCHING_METHOD_SPATIAL_GRID_2D, - BATCHING_METHOD_SPATIAL_GRID_3D, - BATCHING_METHOD_COUNT - }; - struct Range - { - int begin; - int end; - - Range() : begin( 0 ), end( 0 ) {} - Range( int _beg, int _end ) : begin( _beg ), end( _end ) {} - }; - - btAlignedObjectArray<int> m_constraintIndices; - btAlignedObjectArray<Range> m_batches; // each batch is a range of indices in the m_constraintIndices array - btAlignedObjectArray<Range> m_phases; // each phase is range of indices in the m_batches array - btAlignedObjectArray<char> m_phaseGrainSize; // max grain size for each phase - btAlignedObjectArray<int> m_phaseOrder; // phases can be done in any order, so we can randomize the order here - btIDebugDraw* m_debugDrawer; - - static bool s_debugDrawBatches; - - btBatchedConstraints() {m_debugDrawer=NULL;} - void setup( btConstraintArray* constraints, - const btAlignedObjectArray<btSolverBody>& bodies, - BatchingMethod batchingMethod, - int minBatchSize, - int maxBatchSize, - btAlignedObjectArray<char>* scratchMemory - ); - bool validate( btConstraintArray* constraints, const btAlignedObjectArray<btSolverBody>& bodies ) const; + enum BatchingMethod + { + BATCHING_METHOD_SPATIAL_GRID_2D, + BATCHING_METHOD_SPATIAL_GRID_3D, + BATCHING_METHOD_COUNT + }; + struct Range + { + int begin; + int end; + + Range() : begin(0), end(0) {} + Range(int _beg, int _end) : begin(_beg), end(_end) {} + }; + + btAlignedObjectArray<int> m_constraintIndices; + btAlignedObjectArray<Range> m_batches; // each batch is a range of indices in the m_constraintIndices array + btAlignedObjectArray<Range> m_phases; // each phase is range of indices in the m_batches array + btAlignedObjectArray<char> m_phaseGrainSize; // max grain size for each phase + btAlignedObjectArray<int> m_phaseOrder; // phases can be done in any order, so we can randomize the order here + btIDebugDraw* m_debugDrawer; + + static bool s_debugDrawBatches; + + btBatchedConstraints() { m_debugDrawer = NULL; } + void setup(btConstraintArray* constraints, + const btAlignedObjectArray<btSolverBody>& bodies, + BatchingMethod batchingMethod, + int minBatchSize, + int maxBatchSize, + btAlignedObjectArray<char>* scratchMemory); + bool validate(btConstraintArray* constraints, const btAlignedObjectArray<btSolverBody>& bodies) const; }; - -#endif // BT_BATCHED_CONSTRAINTS_H - +#endif // BT_BATCHED_CONSTRAINTS_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp index 0572256f74..10678b2a61 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp @@ -15,49 +15,37 @@ subject to the following restrictions: Written by: Marcus Hennix */ - #include "btConeTwistConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" #include "LinearMath/btMinMax.h" #include <new> - - //#define CONETWIST_USE_OBSOLETE_SOLVER true #define CONETWIST_USE_OBSOLETE_SOLVER false #define CONETWIST_DEF_FIX_THRESH btScalar(.05f) - SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis, const btMatrix3x3& invInertiaWorld) { btVector3 vec = axis * invInertiaWorld; return axis.dot(vec); } - - - -btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, - const btTransform& rbAFrame,const btTransform& rbBFrame) - :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), - m_angularOnly(false), - m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER) +btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA, btRigidBody& rbB, + const btTransform& rbAFrame, const btTransform& rbBFrame) + : btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA, rbB), m_rbAFrame(rbAFrame), m_rbBFrame(rbBFrame), m_angularOnly(false), m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER) { init(); } -btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame) - :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame), - m_angularOnly(false), - m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER) +btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA, const btTransform& rbAFrame) + : btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA), m_rbAFrame(rbAFrame), m_angularOnly(false), m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER) { m_rbBFrame = m_rbAFrame; m_rbBFrame.setOrigin(btVector3(0., 0., 0.)); - init(); + init(); } - void btConeTwistConstraint::init() { m_angularOnly = false; @@ -75,30 +63,29 @@ void btConeTwistConstraint::init() m_angCFM = btScalar(0.f); } - -void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info) +void btConeTwistConstraint::getInfo1(btConstraintInfo1* info) { if (m_useSolveConstraintObsolete) { info->m_numConstraintRows = 0; info->nub = 0; - } + } else { info->m_numConstraintRows = 3; info->nub = 3; - calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld()); - if(m_solveSwingLimit) + calcAngleInfo2(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld()); + if (m_solveSwingLimit) { info->m_numConstraintRows++; info->nub--; - if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) + if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) { info->m_numConstraintRows++; info->nub--; } } - if(m_solveTwistLimit) + if (m_solveTwistLimit) { info->m_numConstraintRows++; info->nub--; @@ -106,90 +93,88 @@ void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info) } } -void btConeTwistConstraint::getInfo1NonVirtual (btConstraintInfo1* info) +void btConeTwistConstraint::getInfo1NonVirtual(btConstraintInfo1* info) { //always reserve 6 rows: object transform is not available on SPU info->m_numConstraintRows = 6; info->nub = 0; - } - -void btConeTwistConstraint::getInfo2 (btConstraintInfo2* info) +void btConeTwistConstraint::getInfo2(btConstraintInfo2* info) { - getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld()); + getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld()); } -void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB) +void btConeTwistConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB) { - calcAngleInfo2(transA,transB,invInertiaWorldA,invInertiaWorldB); - + calcAngleInfo2(transA, transB, invInertiaWorldA, invInertiaWorldB); + btAssert(!m_useSolveConstraintObsolete); - // set jacobian - info->m_J1linearAxis[0] = 1; - info->m_J1linearAxis[info->rowskip+1] = 1; - info->m_J1linearAxis[2*info->rowskip+2] = 1; + // set jacobian + info->m_J1linearAxis[0] = 1; + info->m_J1linearAxis[info->rowskip + 1] = 1; + info->m_J1linearAxis[2 * info->rowskip + 2] = 1; btVector3 a1 = transA.getBasis() * m_rbAFrame.getOrigin(); { btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); - btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip); - btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip); + btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * info->rowskip); btVector3 a1neg = -a1; - a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); + a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2); } - info->m_J2linearAxis[0] = -1; - info->m_J2linearAxis[info->rowskip+1] = -1; - info->m_J2linearAxis[2*info->rowskip+2] = -1; + info->m_J2linearAxis[0] = -1; + info->m_J2linearAxis[info->rowskip + 1] = -1; + info->m_J2linearAxis[2 * info->rowskip + 2] = -1; btVector3 a2 = transB.getBasis() * m_rbBFrame.getOrigin(); { btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); - btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip); - btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip); - a2.getSkewSymmetricMatrix(angular0,angular1,angular2); + btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * info->rowskip); + a2.getSkewSymmetricMatrix(angular0, angular1, angular2); } - // set right hand side + // set right hand side btScalar linERP = (m_flags & BT_CONETWIST_FLAGS_LIN_ERP) ? m_linERP : info->erp; - btScalar k = info->fps * linERP; - int j; - for (j=0; j<3; j++) - { - info->m_constraintError[j*info->rowskip] = k * (a2[j] + transB.getOrigin()[j] - a1[j] - transA.getOrigin()[j]); - info->m_lowerLimit[j*info->rowskip] = -SIMD_INFINITY; - info->m_upperLimit[j*info->rowskip] = SIMD_INFINITY; - if(m_flags & BT_CONETWIST_FLAGS_LIN_CFM) + btScalar k = info->fps * linERP; + int j; + for (j = 0; j < 3; j++) + { + info->m_constraintError[j * info->rowskip] = k * (a2[j] + transB.getOrigin()[j] - a1[j] - transA.getOrigin()[j]); + info->m_lowerLimit[j * info->rowskip] = -SIMD_INFINITY; + info->m_upperLimit[j * info->rowskip] = SIMD_INFINITY; + if (m_flags & BT_CONETWIST_FLAGS_LIN_CFM) { - info->cfm[j*info->rowskip] = m_linCFM; + info->cfm[j * info->rowskip] = m_linCFM; } - } + } int row = 3; - int srow = row * info->rowskip; + int srow = row * info->rowskip; btVector3 ax1; // angular limits - if(m_solveSwingLimit) + if (m_solveSwingLimit) { - btScalar *J1 = info->m_J1angularAxis; - btScalar *J2 = info->m_J2angularAxis; - if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) + btScalar* J1 = info->m_J1angularAxis; + btScalar* J2 = info->m_J2angularAxis; + if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) { - btTransform trA = transA*m_rbAFrame; + btTransform trA = transA * m_rbAFrame; btVector3 p = trA.getBasis().getColumn(1); btVector3 q = trA.getBasis().getColumn(2); int srow1 = srow + info->rowskip; - J1[srow+0] = p[0]; - J1[srow+1] = p[1]; - J1[srow+2] = p[2]; - J1[srow1+0] = q[0]; - J1[srow1+1] = q[1]; - J1[srow1+2] = q[2]; - J2[srow+0] = -p[0]; - J2[srow+1] = -p[1]; - J2[srow+2] = -p[2]; - J2[srow1+0] = -q[0]; - J2[srow1+1] = -q[1]; - J2[srow1+2] = -q[2]; + J1[srow + 0] = p[0]; + J1[srow + 1] = p[1]; + J1[srow + 2] = p[2]; + J1[srow1 + 0] = q[0]; + J1[srow1 + 1] = q[1]; + J1[srow1 + 2] = q[2]; + J2[srow + 0] = -p[0]; + J2[srow + 1] = -p[1]; + J2[srow + 2] = -p[2]; + J2[srow1 + 0] = -q[0]; + J2[srow1 + 1] = -q[1]; + J2[srow1 + 2] = -q[2]; btScalar fact = info->fps * m_relaxationFactor; - info->m_constraintError[srow] = fact * m_swingAxis.dot(p); - info->m_constraintError[srow1] = fact * m_swingAxis.dot(q); + info->m_constraintError[srow] = fact * m_swingAxis.dot(p); + info->m_constraintError[srow1] = fact * m_swingAxis.dot(q); info->m_lowerLimit[srow] = -SIMD_INFINITY; info->m_upperLimit[srow] = SIMD_INFINITY; info->m_lowerLimit[srow1] = -SIMD_INFINITY; @@ -199,16 +184,16 @@ void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const bt else { ax1 = m_swingAxis * m_relaxationFactor * m_relaxationFactor; - J1[srow+0] = ax1[0]; - J1[srow+1] = ax1[1]; - J1[srow+2] = ax1[2]; - J2[srow+0] = -ax1[0]; - J2[srow+1] = -ax1[1]; - J2[srow+2] = -ax1[2]; + J1[srow + 0] = ax1[0]; + J1[srow + 1] = ax1[1]; + J1[srow + 2] = ax1[2]; + J2[srow + 0] = -ax1[0]; + J2[srow + 1] = -ax1[1]; + J2[srow + 2] = -ax1[2]; btScalar k = info->fps * m_biasFactor; info->m_constraintError[srow] = k * m_swingCorrection; - if(m_flags & BT_CONETWIST_FLAGS_ANG_CFM) + if (m_flags & BT_CONETWIST_FLAGS_ANG_CFM) { info->cfm[srow] = m_angCFM; } @@ -218,36 +203,35 @@ void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const bt srow += info->rowskip; } } - if(m_solveTwistLimit) + if (m_solveTwistLimit) { ax1 = m_twistAxis * m_relaxationFactor * m_relaxationFactor; - btScalar *J1 = info->m_J1angularAxis; - btScalar *J2 = info->m_J2angularAxis; - J1[srow+0] = ax1[0]; - J1[srow+1] = ax1[1]; - J1[srow+2] = ax1[2]; - J2[srow+0] = -ax1[0]; - J2[srow+1] = -ax1[1]; - J2[srow+2] = -ax1[2]; + btScalar* J1 = info->m_J1angularAxis; + btScalar* J2 = info->m_J2angularAxis; + J1[srow + 0] = ax1[0]; + J1[srow + 1] = ax1[1]; + J1[srow + 2] = ax1[2]; + J2[srow + 0] = -ax1[0]; + J2[srow + 1] = -ax1[1]; + J2[srow + 2] = -ax1[2]; btScalar k = info->fps * m_biasFactor; info->m_constraintError[srow] = k * m_twistCorrection; - if(m_flags & BT_CONETWIST_FLAGS_ANG_CFM) + if (m_flags & BT_CONETWIST_FLAGS_ANG_CFM) { info->cfm[srow] = m_angCFM; } - if(m_twistSpan > 0.0f) + if (m_twistSpan > 0.0f) { - - if(m_twistCorrection > 0.0f) + if (m_twistCorrection > 0.0f) { info->m_lowerLimit[srow] = 0; info->m_upperLimit[srow] = SIMD_INFINITY; - } + } else { info->m_lowerLimit[srow] = -SIMD_INFINITY; info->m_upperLimit[srow] = 0; - } + } } else { @@ -257,22 +241,20 @@ void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const bt srow += info->rowskip; } } - - -void btConeTwistConstraint::buildJacobian() +void btConeTwistConstraint::buildJacobian() { if (m_useSolveConstraintObsolete) { m_appliedImpulse = btScalar(0.); m_accTwistLimitImpulse = btScalar(0.); m_accSwingLimitImpulse = btScalar(0.); - m_accMotorImpulse = btVector3(0.,0.,0.); + m_accMotorImpulse = btVector3(0., 0., 0.); if (!m_angularOnly) { - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_rbBFrame.getOrigin(); btVector3 relPos = pivotBInW - pivotAInW; btVector3 normal[3]; @@ -282,71 +264,68 @@ void btConeTwistConstraint::buildJacobian() } else { - normal[0].setValue(btScalar(1.0),0,0); + normal[0].setValue(btScalar(1.0), 0, 0); } btPlaneSpace1(normal[0], normal[1], normal[2]); - for (int i=0;i<3;i++) + for (int i = 0; i < 3; i++) { new (&m_jac[i]) btJacobianEntry( - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - pivotAInW - m_rbA.getCenterOfMassPosition(), - pivotBInW - m_rbB.getCenterOfMassPosition(), - normal[i], - m_rbA.getInvInertiaDiagLocal(), - m_rbA.getInvMass(), - m_rbB.getInvInertiaDiagLocal(), - m_rbB.getInvMass()); + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normal[i], + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); } } - calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld()); + calcAngleInfo2(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld()); } } - - -void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) +void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA, btSolverBody& bodyB, btScalar timeStep) { - #ifndef __SPU__ +#ifndef __SPU__ if (m_useSolveConstraintObsolete) { - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_rbBFrame.getOrigin(); btScalar tau = btScalar(0.3); //linear part if (!m_angularOnly) { - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); btVector3 vel1; - bodyA.internalGetVelocityInLocalPointObsolete(rel_pos1,vel1); + bodyA.internalGetVelocityInLocalPointObsolete(rel_pos1, vel1); btVector3 vel2; - bodyB.internalGetVelocityInLocalPointObsolete(rel_pos2,vel2); + bodyB.internalGetVelocityInLocalPointObsolete(rel_pos2, vel2); btVector3 vel = vel1 - vel2; - for (int i=0;i<3;i++) - { + for (int i = 0; i < 3; i++) + { const btVector3& normal = m_jac[i].m_linearJointAxis; btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); btScalar rel_vel; rel_vel = normal.dot(vel); //positional error (zeroth order error) - btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal - btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; + btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal + btScalar impulse = depth * tau / timeStep * jacDiagABInv - rel_vel * jacDiagABInv; m_appliedImpulse += impulse; - + btVector3 ftorqueAxis1 = rel_pos1.cross(normal); btVector3 ftorqueAxis2 = rel_pos2.cross(normal); - bodyA.internalApplyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse); - bodyB.internalApplyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse); - + bodyA.internalApplyImpulse(normal * m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld() * ftorqueAxis1, impulse); + bodyB.internalApplyImpulse(normal * m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld() * ftorqueAxis2, -impulse); } } @@ -356,13 +335,17 @@ void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolver // compute current and predicted transforms btTransform trACur = m_rbA.getCenterOfMassTransform(); btTransform trBCur = m_rbB.getCenterOfMassTransform(); - btVector3 omegaA; bodyA.internalGetAngularVelocity(omegaA); - btVector3 omegaB; bodyB.internalGetAngularVelocity(omegaB); - btTransform trAPred; trAPred.setIdentity(); - btVector3 zerovec(0,0,0); + btVector3 omegaA; + bodyA.internalGetAngularVelocity(omegaA); + btVector3 omegaB; + bodyB.internalGetAngularVelocity(omegaB); + btTransform trAPred; + trAPred.setIdentity(); + btVector3 zerovec(0, 0, 0); btTransformUtil::integrateTransform( trACur, zerovec, omegaA, timeStep, trAPred); - btTransform trBPred; trBPred.setIdentity(); + btTransform trBPred; + trBPred.setIdentity(); btTransformUtil::integrateTransform( trBCur, zerovec, omegaB, timeStep, trBPred); @@ -374,7 +357,7 @@ void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolver // compute desired omegas in world btVector3 omegaADes, omegaBDes; - + btTransformUtil::calculateVelocity(trACur, trADes, timeStep, zerovec, omegaADes); btTransformUtil::calculateVelocity(trBCur, trBDes, timeStep, zerovec, omegaBDes); @@ -415,10 +398,10 @@ void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolver { btScalar fMaxImpulse = m_maxMotorImpulse; if (m_bNormalizedMotorStrength) - fMaxImpulse = fMaxImpulse/kAxisAInv; + fMaxImpulse = fMaxImpulse / kAxisAInv; btVector3 newUnclampedAccImpulse = m_accMotorImpulse + impulse; - btScalar newUnclampedMag = newUnclampedAccImpulse.length(); + btScalar newUnclampedMag = newUnclampedAccImpulse.length(); if (newUnclampedMag > fMaxImpulse) { newUnclampedAccImpulse.normalize(); @@ -428,31 +411,32 @@ void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolver m_accMotorImpulse += impulse; } - btScalar impulseMag = impulse.length(); - btVector3 impulseAxis = impulse / impulseMag; - - bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag); - bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag); + btScalar impulseMag = impulse.length(); + btVector3 impulseAxis = impulse / impulseMag; + bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * impulseAxis, impulseMag); + bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * impulseAxis, -impulseMag); } } - else if (m_damping > SIMD_EPSILON) // no motor: do a little damping + else if (m_damping > SIMD_EPSILON) // no motor: do a little damping { - btVector3 angVelA; bodyA.internalGetAngularVelocity(angVelA); - btVector3 angVelB; bodyB.internalGetAngularVelocity(angVelB); + btVector3 angVelA; + bodyA.internalGetAngularVelocity(angVelA); + btVector3 angVelB; + bodyB.internalGetAngularVelocity(angVelB); btVector3 relVel = angVelB - angVelA; if (relVel.length2() > SIMD_EPSILON) { btVector3 relVelAxis = relVel.normalized(); - btScalar m_kDamping = btScalar(1.) / - (getRigidBodyA().computeAngularImpulseDenominator(relVelAxis) + - getRigidBodyB().computeAngularImpulseDenominator(relVelAxis)); + btScalar m_kDamping = btScalar(1.) / + (getRigidBodyA().computeAngularImpulseDenominator(relVelAxis) + + getRigidBodyB().computeAngularImpulseDenominator(relVelAxis)); btVector3 impulse = m_damping * m_kDamping * relVel; - btScalar impulseMag = impulse.length(); + btScalar impulseMag = impulse.length(); btVector3 impulseAxis = impulse / impulseMag; - bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag); - bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag); + bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * impulseAxis, impulseMag); + bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * impulseAxis, -impulseMag); } } @@ -467,7 +451,7 @@ void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolver // solve swing limit if (m_solveSwingLimit) { - btScalar amplitude = m_swingLimitRatio * m_swingCorrection*m_biasFactor/timeStep; + btScalar amplitude = m_swingLimitRatio * m_swingCorrection * m_biasFactor / timeStep; btScalar relSwingVel = (angVelB - angVelA).dot(m_swingAxis); if (relSwingVel > 0) amplitude += m_swingLimitRatio * relSwingVel * m_relaxationFactor; @@ -475,7 +459,7 @@ void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolver // Clamp the accumulated impulse btScalar temp = m_accSwingLimitImpulse; - m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) ); + m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0)); impulseMag = m_accSwingLimitImpulse - temp; btVector3 impulse = m_swingAxis * impulseMag; @@ -491,47 +475,41 @@ void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolver impulseMag = impulse.length(); btVector3 noTwistSwingAxis = impulse / impulseMag; - bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*noTwistSwingAxis, impulseMag); - bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*noTwistSwingAxis, -impulseMag); + bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * noTwistSwingAxis, impulseMag); + bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * noTwistSwingAxis, -impulseMag); } - // solve twist limit if (m_solveTwistLimit) { - btScalar amplitude = m_twistLimitRatio * m_twistCorrection*m_biasFactor/timeStep; - btScalar relTwistVel = (angVelB - angVelA).dot( m_twistAxis ); - if (relTwistVel > 0) // only damp when moving towards limit (m_twistAxis flipping is important) + btScalar amplitude = m_twistLimitRatio * m_twistCorrection * m_biasFactor / timeStep; + btScalar relTwistVel = (angVelB - angVelA).dot(m_twistAxis); + if (relTwistVel > 0) // only damp when moving towards limit (m_twistAxis flipping is important) amplitude += m_twistLimitRatio * relTwistVel * m_relaxationFactor; btScalar impulseMag = amplitude * m_kTwist; // Clamp the accumulated impulse btScalar temp = m_accTwistLimitImpulse; - m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) ); + m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0)); impulseMag = m_accTwistLimitImpulse - temp; - // btVector3 impulse = m_twistAxis * impulseMag; + // btVector3 impulse = m_twistAxis * impulseMag; - bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*m_twistAxis,impulseMag); - bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*m_twistAxis,-impulseMag); - } + bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * m_twistAxis, impulseMag); + bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * m_twistAxis, -impulseMag); + } } } #else -btAssert(0); -#endif //__SPU__ + btAssert(0); +#endif //__SPU__ } - - - -void btConeTwistConstraint::updateRHS(btScalar timeStep) +void btConeTwistConstraint::updateRHS(btScalar timeStep) { (void)timeStep; - } - #ifndef __SPU__ void btConeTwistConstraint::calcAngleInfo() { @@ -540,15 +518,15 @@ void btConeTwistConstraint::calcAngleInfo() m_solveTwistLimit = false; m_solveSwingLimit = false; - btVector3 b1Axis1(0,0,0),b1Axis2(0,0,0),b1Axis3(0,0,0); - btVector3 b2Axis1(0,0,0),b2Axis2(0,0,0); + btVector3 b1Axis1(0, 0, 0), b1Axis2(0, 0, 0), b1Axis3(0, 0, 0); + btVector3 b2Axis1(0, 0, 0), b2Axis2(0, 0, 0); b1Axis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(0); b2Axis1 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(0); - btScalar swing1=btScalar(0.),swing2 = btScalar(0.); + btScalar swing1 = btScalar(0.), swing2 = btScalar(0.); - btScalar swx=btScalar(0.),swy = btScalar(0.); + btScalar swx = btScalar(0.), swy = btScalar(0.); btScalar thresh = btScalar(10.); btScalar fact; @@ -558,33 +536,33 @@ void btConeTwistConstraint::calcAngleInfo() b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1); swx = b2Axis1.dot(b1Axis1); swy = b2Axis1.dot(b1Axis2); - swing1 = btAtan2Fast(swy, swx); - fact = (swy*swy + swx*swx) * thresh * thresh; + swing1 = btAtan2Fast(swy, swx); + fact = (swy * swy + swx * swx) * thresh * thresh; fact = fact / (fact + btScalar(1.0)); - swing1 *= fact; + swing1 *= fact; } if (m_swingSpan2 >= btScalar(0.05f)) { - b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2); + b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2); swx = b2Axis1.dot(b1Axis1); swy = b2Axis1.dot(b1Axis3); - swing2 = btAtan2Fast(swy, swx); - fact = (swy*swy + swx*swx) * thresh * thresh; + swing2 = btAtan2Fast(swy, swx); + fact = (swy * swy + swx * swx) * thresh * thresh; fact = fact / (fact + btScalar(1.0)); - swing2 *= fact; + swing2 *= fact; } - btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1*m_swingSpan1); - btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2*m_swingSpan2); - btScalar EllipseAngle = btFabs(swing1*swing1)* RMaxAngle1Sq + btFabs(swing2*swing2) * RMaxAngle2Sq; + btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1 * m_swingSpan1); + btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2 * m_swingSpan2); + btScalar EllipseAngle = btFabs(swing1 * swing1) * RMaxAngle1Sq + btFabs(swing2 * swing2) * RMaxAngle2Sq; if (EllipseAngle > 1.0f) { - m_swingCorrection = EllipseAngle-1.0f; + m_swingCorrection = EllipseAngle - 1.0f; m_solveSwingLimit = true; // Calculate necessary axis & factors - m_swingAxis = b2Axis1.cross(b1Axis2* b2Axis1.dot(b1Axis2) + b1Axis3* b2Axis1.dot(b1Axis3)); + m_swingAxis = b2Axis1.cross(b1Axis2 * b2Axis1.dot(b1Axis2) + b1Axis3 * b2Axis1.dot(b1Axis3)); m_swingAxis.normalize(); btScalar swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f; m_swingAxis *= swingAxisSign; @@ -594,14 +572,14 @@ void btConeTwistConstraint::calcAngleInfo() if (m_twistSpan >= btScalar(0.)) { btVector3 b2Axis2 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(1); - btQuaternion rotationArc = shortestArcQuat(b2Axis1,b1Axis1); - btVector3 TwistRef = quatRotate(rotationArc,b2Axis2); - btScalar twist = btAtan2Fast( TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2) ); + btQuaternion rotationArc = shortestArcQuat(b2Axis1, b1Axis1); + btVector3 TwistRef = quatRotate(rotationArc, b2Axis2); + btScalar twist = btAtan2Fast(TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2)); m_twistAngle = twist; -// btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.); + // btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.); btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? btScalar(1.0f) : btScalar(0.); - if (twist <= -m_twistSpan*lockedFreeFactor) + if (twist <= -m_twistSpan * lockedFreeFactor) { m_twistCorrection = -(twist + m_twistSpan); m_solveTwistLimit = true; @@ -609,7 +587,7 @@ void btConeTwistConstraint::calcAngleInfo() m_twistAxis.normalize(); m_twistAxis *= -1.0f; } - else if (twist > m_twistSpan*lockedFreeFactor) + else if (twist > m_twistSpan * lockedFreeFactor) { m_twistCorrection = (twist - m_twistSpan); m_solveTwistLimit = true; @@ -618,13 +596,11 @@ void btConeTwistConstraint::calcAngleInfo() } } } -#endif //__SPU__ - -static btVector3 vTwist(1,0,0); // twist axis in constraint's space +#endif //__SPU__ +static btVector3 vTwist(1, 0, 0); // twist axis in constraint's space - -void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB) +void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB) { m_swingCorrection = btScalar(0.); m_twistLimitSign = btScalar(0.); @@ -632,7 +608,7 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr m_solveSwingLimit = false; // compute rotation of A wrt B (in constraint space) if (m_bMotorEnabled && (!m_useSolveConstraintObsolete)) - { // it is assumed that setMotorTarget() was alredy called + { // it is assumed that setMotorTarget() was alredy called // and motor target m_qTarget is within constraint limits // TODO : split rotation to pure swing and pure twist // compute desired transforms in world @@ -641,23 +617,22 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr btTransform trB = transB * m_rbBFrame; btTransform trDeltaAB = trB * trPose * trA.inverse(); btQuaternion qDeltaAB = trDeltaAB.getRotation(); - btVector3 swingAxis = btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z()); + btVector3 swingAxis = btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z()); btScalar swingAxisLen2 = swingAxis.length2(); - if(btFuzzyZero(swingAxisLen2)) + if (btFuzzyZero(swingAxisLen2)) { - return; + return; } m_swingAxis = swingAxis; m_swingAxis.normalize(); m_swingCorrection = qDeltaAB.getAngle(); - if(!btFuzzyZero(m_swingCorrection)) + if (!btFuzzyZero(m_swingCorrection)) { m_solveSwingLimit = true; } return; } - { // compute rotation of A wrt B (in constraint space) btQuaternion qA = transA.getRotation() * m_rbAFrame.getRotation(); @@ -665,13 +640,17 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr btQuaternion qAB = qB.inverse() * qA; // split rotation into cone and twist // (all this is done from B's perspective. Maybe I should be averaging axes...) - btVector3 vConeNoTwist = quatRotate(qAB, vTwist); vConeNoTwist.normalize(); - btQuaternion qABCone = shortestArcQuat(vTwist, vConeNoTwist); qABCone.normalize(); - btQuaternion qABTwist = qABCone.inverse() * qAB; qABTwist.normalize(); + btVector3 vConeNoTwist = quatRotate(qAB, vTwist); + vConeNoTwist.normalize(); + btQuaternion qABCone = shortestArcQuat(vTwist, vConeNoTwist); + qABCone.normalize(); + btQuaternion qABTwist = qABCone.inverse() * qAB; + qABTwist.normalize(); if (m_swingSpan1 >= m_fixThresh && m_swingSpan2 >= m_fixThresh) { - btScalar swingAngle, swingLimit = 0; btVector3 swingAxis; + btScalar swingAngle, swingLimit = 0; + btVector3 swingAxis; computeConeLimitInfo(qABCone, swingAngle, swingAxis, swingLimit); if (swingAngle > swingLimit * m_limitSoftness) @@ -684,9 +663,9 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr m_swingLimitRatio = 1.f; if (swingAngle < swingLimit && m_limitSoftness < 1.f - SIMD_EPSILON) { - m_swingLimitRatio = (swingAngle - swingLimit * m_limitSoftness)/ + m_swingLimitRatio = (swingAngle - swingLimit * m_limitSoftness) / (swingLimit - swingLimit * m_limitSoftness); - } + } // swing correction tries to get back to soft limit m_swingCorrection = swingAngle - (swingLimit * m_limitSoftness); @@ -694,14 +673,14 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr // adjustment of swing axis (based on ellipse normal) adjustSwingAxisToUseEllipseNormal(swingAxis); - // Calculate necessary axis & factors + // Calculate necessary axis & factors m_swingAxis = quatRotate(qB, -swingAxis); - m_twistAxisA.setValue(0,0,0); + m_twistAxisA.setValue(0, 0, 0); - m_kSwing = btScalar(1.) / - (computeAngularImpulseDenominator(m_swingAxis,invInertiaWorldA) + - computeAngularImpulseDenominator(m_swingAxis,invInertiaWorldB)); + m_kSwing = btScalar(1.) / + (computeAngularImpulseDenominator(m_swingAxis, invInertiaWorldA) + + computeAngularImpulseDenominator(m_swingAxis, invInertiaWorldB)); } } else @@ -717,9 +696,9 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr btScalar x = ivB.dot(ivA); btScalar y = ivB.dot(jvA); btScalar z = ivB.dot(kvA); - if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) - { // fixed. We'll need to add one more row to constraint - if((!btFuzzyZero(y)) || (!(btFuzzyZero(z)))) + if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh)) + { // fixed. We'll need to add one more row to constraint + if ((!btFuzzyZero(y)) || (!(btFuzzyZero(z)))) { m_solveSwingLimit = true; m_swingAxis = -ivB.cross(ivA); @@ -727,47 +706,47 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr } else { - if(m_swingSpan1 < m_fixThresh) - { // hinge around Y axis -// if(!(btFuzzyZero(y))) - if((!(btFuzzyZero(x))) || (!(btFuzzyZero(z)))) + if (m_swingSpan1 < m_fixThresh) + { // hinge around Y axis + // if(!(btFuzzyZero(y))) + if ((!(btFuzzyZero(x))) || (!(btFuzzyZero(z)))) { m_solveSwingLimit = true; - if(m_swingSpan2 >= m_fixThresh) + if (m_swingSpan2 >= m_fixThresh) { y = btScalar(0.f); btScalar span2 = btAtan2(z, x); - if(span2 > m_swingSpan2) + if (span2 > m_swingSpan2) { x = btCos(m_swingSpan2); z = btSin(m_swingSpan2); } - else if(span2 < -m_swingSpan2) + else if (span2 < -m_swingSpan2) { - x = btCos(m_swingSpan2); + x = btCos(m_swingSpan2); z = -btSin(m_swingSpan2); } } } } else - { // hinge around Z axis -// if(!btFuzzyZero(z)) - if((!(btFuzzyZero(x))) || (!(btFuzzyZero(y)))) + { // hinge around Z axis + // if(!btFuzzyZero(z)) + if ((!(btFuzzyZero(x))) || (!(btFuzzyZero(y)))) { m_solveSwingLimit = true; - if(m_swingSpan1 >= m_fixThresh) + if (m_swingSpan1 >= m_fixThresh) { z = btScalar(0.f); btScalar span1 = btAtan2(y, x); - if(span1 > m_swingSpan1) + if (span1 > m_swingSpan1) { x = btCos(m_swingSpan1); y = btSin(m_swingSpan1); } - else if(span1 < -m_swingSpan1) + else if (span1 < -m_swingSpan1) { - x = btCos(m_swingSpan1); + x = btCos(m_swingSpan1); y = -btSin(m_swingSpan1); } } @@ -778,10 +757,10 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr target[2] = x * ivA[2] + y * jvA[2] + z * kvA[2]; target.normalize(); m_swingAxis = -ivB.cross(target); - m_swingCorrection = m_swingAxis.length(); + m_swingCorrection = m_swingAxis.length(); - if (!btFuzzyZero(m_swingCorrection)) - m_swingAxis.normalize(); + if (!btFuzzyZero(m_swingCorrection)) + m_swingAxis.normalize(); } } @@ -790,15 +769,15 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr btVector3 twistAxis; computeTwistLimitInfo(qABTwist, m_twistAngle, twistAxis); - if (m_twistAngle > m_twistSpan*m_limitSoftness) + if (m_twistAngle > m_twistSpan * m_limitSoftness) { m_solveTwistLimit = true; m_twistLimitRatio = 1.f; if (m_twistAngle < m_twistSpan && m_limitSoftness < 1.f - SIMD_EPSILON) { - m_twistLimitRatio = (m_twistAngle - m_twistSpan * m_limitSoftness)/ - (m_twistSpan - m_twistSpan * m_limitSoftness); + m_twistLimitRatio = (m_twistAngle - m_twistSpan * m_limitSoftness) / + (m_twistSpan - m_twistSpan * m_limitSoftness); } // twist correction tries to get back to soft limit @@ -807,8 +786,8 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr m_twistAxis = quatRotate(qB, -twistAxis); m_kTwist = btScalar(1.) / - (computeAngularImpulseDenominator(m_twistAxis,invInertiaWorldA) + - computeAngularImpulseDenominator(m_twistAxis,invInertiaWorldB)); + (computeAngularImpulseDenominator(m_twistAxis, invInertiaWorldA) + + computeAngularImpulseDenominator(m_twistAxis, invInertiaWorldB)); } if (m_solveSwingLimit) @@ -821,15 +800,13 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr } } - - // given a cone rotation in constraint space, (pre: twist must already be removed) // this method computes its corresponding swing angle and axis. // more interestingly, it computes the cone/swing limit (angle) for this cone "pose". void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone, - btScalar& swingAngle, // out - btVector3& vSwingAxis, // out - btScalar& swingLimit) // out + btScalar& swingAngle, // out + btVector3& vSwingAxis, // out + btScalar& swingLimit) // out { swingAngle = qCone.getAngle(); if (swingAngle > SIMD_EPSILON) @@ -840,7 +817,7 @@ void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone, // non-zero twist?! this should never happen. btAssert(fabs(vSwingAxis.x()) <= SIMD_EPSILON)); #endif - + // Compute limit for given swing. tricky: // Given a swing axis, we're looking for the intersection with the bounding cone ellipse. // (Since we're dealing with angles, this ellipse is embedded on the surface of a sphere.) @@ -848,7 +825,7 @@ void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone, // For starters, compute the direction from center to surface of ellipse. // This is just the perpendicular (ie. rotate 2D vector by PI/2) of the swing axis. // (vSwingAxis is the cone rotation (in z,y); change vars and rotate to (x,y) coords.) - btScalar xEllipse = vSwingAxis.y(); + btScalar xEllipse = vSwingAxis.y(); btScalar yEllipse = -vSwingAxis.z(); // Now, we use the slope of the vector (using x/yEllipse) and find the length @@ -858,10 +835,10 @@ void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone, // a^2 b^2 // Do the math and it should be clear. - swingLimit = m_swingSpan1; // if xEllipse == 0, we have a pure vSwingAxis.z rotation: just use swingspan1 + swingLimit = m_swingSpan1; // if xEllipse == 0, we have a pure vSwingAxis.z rotation: just use swingspan1 if (fabs(xEllipse) > SIMD_EPSILON) { - btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse); + btScalar surfaceSlope2 = (yEllipse * yEllipse) / (xEllipse * xEllipse); btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2); norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1); btScalar swingLimit2 = (1 + surfaceSlope2) / norm; @@ -887,7 +864,7 @@ void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone, #if 0 btAssert(0); #endif - } + } } btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const @@ -903,10 +880,10 @@ btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btSc // a^2 b^2 // Do the math and it should be clear. - btScalar swingLimit = m_swingSpan1; // if xEllipse == 0, just use axis b (1) + btScalar swingLimit = m_swingSpan1; // if xEllipse == 0, just use axis b (1) if (fabs(xEllipse) > SIMD_EPSILON) { - btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse); + btScalar surfaceSlope2 = (yEllipse * yEllipse) / (xEllipse * xEllipse); btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2); norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1); btScalar swingLimit2 = (1 + surfaceSlope2) / norm; @@ -917,20 +894,20 @@ btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btSc // note: twist is x-axis, swing 1 and 2 are along the z and y axes respectively btVector3 vSwingAxis(0, xEllipse, -yEllipse); btQuaternion qSwing(vSwingAxis, swingLimit); - btVector3 vPointInConstraintSpace(fLength,0,0); + btVector3 vPointInConstraintSpace(fLength, 0, 0); return quatRotate(qSwing, vPointInConstraintSpace); } // given a twist rotation in constraint space, (pre: cone must already be removed) // this method computes its corresponding angle and axis. void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist, - btScalar& twistAngle, // out - btVector3& vTwistAxis) // out + btScalar& twistAngle, // out + btVector3& vTwistAxis) // out { btQuaternion qMinTwist = qTwist; twistAngle = qTwist.getAngle(); - if (twistAngle > SIMD_PI) // long way around. flip quat and recalculate. + if (twistAngle > SIMD_PI) // long way around. flip quat and recalculate. { qMinTwist = -(qTwist); twistAngle = qMinTwist.getAngle(); @@ -948,80 +925,79 @@ void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist, vTwistAxis.normalize(); } - void btConeTwistConstraint::adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const { // the swing axis is computed as the "twist-free" cone rotation, // but the cone limit is not circular, but elliptical (if swingspan1 != swingspan2). - // so, if we're outside the limits, the closest way back inside the cone isn't + // so, if we're outside the limits, the closest way back inside the cone isn't // along the vector back to the center. better (and more stable) to use the ellipse normal. // convert swing axis to direction from center to surface of ellipse // (ie. rotate 2D vector by PI/2) btScalar y = -vSwingAxis.z(); - btScalar z = vSwingAxis.y(); + btScalar z = vSwingAxis.y(); // do the math... - if (fabs(z) > SIMD_EPSILON) // avoid division by 0. and we don't need an update if z == 0. + if (fabs(z) > SIMD_EPSILON) // avoid division by 0. and we don't need an update if z == 0. { // compute gradient/normal of ellipse surface at current "point" - btScalar grad = y/z; + btScalar grad = y / z; grad *= m_swingSpan2 / m_swingSpan1; // adjust y/z to represent normal at point (instead of vector to point) if (y > 0) - y = fabs(grad * z); + y = fabs(grad * z); else y = -fabs(grad * z); // convert ellipse direction back to swing axis vSwingAxis.setZ(-y); - vSwingAxis.setY( z); + vSwingAxis.setY(z); vSwingAxis.normalize(); } } - - -void btConeTwistConstraint::setMotorTarget(const btQuaternion &q) +void btConeTwistConstraint::setMotorTarget(const btQuaternion& q) { //btTransform trACur = m_rbA.getCenterOfMassTransform(); //btTransform trBCur = m_rbB.getCenterOfMassTransform(); -// btTransform trABCur = trBCur.inverse() * trACur; -// btQuaternion qABCur = trABCur.getRotation(); -// btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame); + // btTransform trABCur = trBCur.inverse() * trACur; + // btQuaternion qABCur = trABCur.getRotation(); + // btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame); //btQuaternion qConstraintCur = trConstraintCur.getRotation(); btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * q * m_rbAFrame.getRotation(); setMotorTargetInConstraintSpace(qConstraint); } - -void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion &q) +void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion& q) { m_qTarget = q; // clamp motor target to within limits { - btScalar softness = 1.f;//m_limitSoftness; + btScalar softness = 1.f; //m_limitSoftness; // split into twist and cone btVector3 vTwisted = quatRotate(m_qTarget, vTwist); - btQuaternion qTargetCone = shortestArcQuat(vTwist, vTwisted); qTargetCone.normalize(); - btQuaternion qTargetTwist = qTargetCone.inverse() * m_qTarget; qTargetTwist.normalize(); + btQuaternion qTargetCone = shortestArcQuat(vTwist, vTwisted); + qTargetCone.normalize(); + btQuaternion qTargetTwist = qTargetCone.inverse() * m_qTarget; + qTargetTwist.normalize(); // clamp cone if (m_swingSpan1 >= btScalar(0.05f) && m_swingSpan2 >= btScalar(0.05f)) { - btScalar swingAngle, swingLimit; btVector3 swingAxis; + btScalar swingAngle, swingLimit; + btVector3 swingAxis; computeConeLimitInfo(qTargetCone, swingAngle, swingAxis, swingLimit); if (fabs(swingAngle) > SIMD_EPSILON) { - if (swingAngle > swingLimit*softness) - swingAngle = swingLimit*softness; - else if (swingAngle < -swingLimit*softness) - swingAngle = -swingLimit*softness; + if (swingAngle > swingLimit * softness) + swingAngle = swingLimit * softness; + else if (swingAngle < -swingLimit * softness) + swingAngle = -swingLimit * softness; qTargetCone = btQuaternion(swingAxis, swingAngle); } } @@ -1029,16 +1005,17 @@ void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion & // clamp twist if (m_twistSpan >= btScalar(0.05f)) { - btScalar twistAngle; btVector3 twistAxis; + btScalar twistAngle; + btVector3 twistAxis; computeTwistLimitInfo(qTargetTwist, twistAngle, twistAxis); if (fabs(twistAngle) > SIMD_EPSILON) { // eddy todo: limitSoftness used here??? - if (twistAngle > m_twistSpan*softness) - twistAngle = m_twistSpan*softness; - else if (twistAngle < -m_twistSpan*softness) - twistAngle = -m_twistSpan*softness; + if (twistAngle > m_twistSpan * softness) + twistAngle = m_twistSpan * softness; + else if (twistAngle < -m_twistSpan * softness) + twistAngle = -m_twistSpan * softness; qTargetTwist = btQuaternion(twistAxis, twistAngle); } } @@ -1047,15 +1024,15 @@ void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion & } } -///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). +///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). ///If no axis is provided, it uses the default axis for this constraint. void btConeTwistConstraint::setParam(int num, btScalar value, int axis) { - switch(num) + switch (num) { - case BT_CONSTRAINT_ERP : - case BT_CONSTRAINT_STOP_ERP : - if((axis >= 0) && (axis < 3)) + case BT_CONSTRAINT_ERP: + case BT_CONSTRAINT_STOP_ERP: + if ((axis >= 0) && (axis < 3)) { m_linERP = value; m_flags |= BT_CONETWIST_FLAGS_LIN_ERP; @@ -1065,9 +1042,9 @@ void btConeTwistConstraint::setParam(int num, btScalar value, int axis) m_biasFactor = value; } break; - case BT_CONSTRAINT_CFM : - case BT_CONSTRAINT_STOP_CFM : - if((axis >= 0) && (axis < 3)) + case BT_CONSTRAINT_CFM: + case BT_CONSTRAINT_STOP_CFM: + if ((axis >= 0) && (axis < 3)) { m_linCFM = value; m_flags |= BT_CONETWIST_FLAGS_LIN_CFM; @@ -1085,19 +1062,19 @@ void btConeTwistConstraint::setParam(int num, btScalar value, int axis) } ///return the local value of parameter -btScalar btConeTwistConstraint::getParam(int num, int axis) const +btScalar btConeTwistConstraint::getParam(int num, int axis) const { btScalar retVal = 0; - switch(num) + switch (num) { - case BT_CONSTRAINT_ERP : - case BT_CONSTRAINT_STOP_ERP : - if((axis >= 0) && (axis < 3)) + case BT_CONSTRAINT_ERP: + case BT_CONSTRAINT_STOP_ERP: + if ((axis >= 0) && (axis < 3)) { btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_ERP); retVal = m_linERP; } - else if((axis >= 3) && (axis < 6)) + else if ((axis >= 3) && (axis < 6)) { retVal = m_biasFactor; } @@ -1106,14 +1083,14 @@ btScalar btConeTwistConstraint::getParam(int num, int axis) const btAssertConstrParams(0); } break; - case BT_CONSTRAINT_CFM : - case BT_CONSTRAINT_STOP_CFM : - if((axis >= 0) && (axis < 3)) + case BT_CONSTRAINT_CFM: + case BT_CONSTRAINT_STOP_CFM: + if ((axis >= 0) && (axis < 3)) { btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_CFM); retVal = m_linCFM; } - else if((axis >= 3) && (axis < 6)) + else if ((axis >= 3) && (axis < 6)) { btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_ANG_CFM); retVal = m_angCFM; @@ -1123,21 +1100,16 @@ btScalar btConeTwistConstraint::getParam(int num, int axis) const btAssertConstrParams(0); } break; - default : + default: btAssertConstrParams(0); } return retVal; } - -void btConeTwistConstraint::setFrames(const btTransform & frameA, const btTransform & frameB) +void btConeTwistConstraint::setFrames(const btTransform& frameA, const btTransform& frameB) { m_rbAFrame = frameA; m_rbBFrame = frameB; buildJacobian(); //calculateTransforms(); } - - - - diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h index 7a33d01d1e..64f44df1cb 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h @@ -15,8 +15,6 @@ subject to the following restrictions: Written by: Marcus Hennix */ - - /* Overview: @@ -31,8 +29,6 @@ twist is along the x-axis, and swing 1 and 2 are along the z and y axes respectively. */ - - #ifndef BT_CONETWISTCONSTRAINT_H #define BT_CONETWISTCONSTRAINT_H @@ -41,13 +37,12 @@ and swing 1 and 2 are along the z and y axes respectively. #include "btTypedConstraint.h" #ifdef BT_USE_DOUBLE_PRECISION -#define btConeTwistConstraintData2 btConeTwistConstraintDoubleData -#define btConeTwistConstraintDataName "btConeTwistConstraintDoubleData" +#define btConeTwistConstraintData2 btConeTwistConstraintDoubleData +#define btConeTwistConstraintDataName "btConeTwistConstraintDoubleData" #else -#define btConeTwistConstraintData2 btConeTwistConstraintData -#define btConeTwistConstraintDataName "btConeTwistConstraintData" -#endif //BT_USE_DOUBLE_PRECISION - +#define btConeTwistConstraintData2 btConeTwistConstraintData +#define btConeTwistConstraintDataName "btConeTwistConstraintData" +#endif //BT_USE_DOUBLE_PRECISION class btRigidBody; @@ -59,103 +54,99 @@ enum btConeTwistFlags }; ///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc) -ATTRIBUTE_ALIGNED16(class) btConeTwistConstraint : public btTypedConstraint +ATTRIBUTE_ALIGNED16(class) +btConeTwistConstraint : public btTypedConstraint { #ifdef IN_PARALLELL_SOLVER public: #endif - btJacobianEntry m_jac[3]; //3 orthogonal linear constraints + btJacobianEntry m_jac[3]; //3 orthogonal linear constraints - btTransform m_rbAFrame; + btTransform m_rbAFrame; btTransform m_rbBFrame; - btScalar m_limitSoftness; - btScalar m_biasFactor; - btScalar m_relaxationFactor; + btScalar m_limitSoftness; + btScalar m_biasFactor; + btScalar m_relaxationFactor; - btScalar m_damping; + btScalar m_damping; - btScalar m_swingSpan1; - btScalar m_swingSpan2; - btScalar m_twistSpan; + btScalar m_swingSpan1; + btScalar m_swingSpan2; + btScalar m_twistSpan; - btScalar m_fixThresh; + btScalar m_fixThresh; - btVector3 m_swingAxis; - btVector3 m_twistAxis; + btVector3 m_swingAxis; + btVector3 m_twistAxis; - btScalar m_kSwing; - btScalar m_kTwist; + btScalar m_kSwing; + btScalar m_kTwist; - btScalar m_twistLimitSign; - btScalar m_swingCorrection; - btScalar m_twistCorrection; + btScalar m_twistLimitSign; + btScalar m_swingCorrection; + btScalar m_twistCorrection; - btScalar m_twistAngle; + btScalar m_twistAngle; - btScalar m_accSwingLimitImpulse; - btScalar m_accTwistLimitImpulse; + btScalar m_accSwingLimitImpulse; + btScalar m_accTwistLimitImpulse; - bool m_angularOnly; - bool m_solveTwistLimit; - bool m_solveSwingLimit; + bool m_angularOnly; + bool m_solveTwistLimit; + bool m_solveSwingLimit; - bool m_useSolveConstraintObsolete; + bool m_useSolveConstraintObsolete; // not yet used... - btScalar m_swingLimitRatio; - btScalar m_twistLimitRatio; - btVector3 m_twistAxisA; + btScalar m_swingLimitRatio; + btScalar m_twistLimitRatio; + btVector3 m_twistAxisA; // motor - bool m_bMotorEnabled; - bool m_bNormalizedMotorStrength; + bool m_bMotorEnabled; + bool m_bNormalizedMotorStrength; btQuaternion m_qTarget; - btScalar m_maxMotorImpulse; - btVector3 m_accMotorImpulse; - + btScalar m_maxMotorImpulse; + btVector3 m_accMotorImpulse; + // parameters - int m_flags; - btScalar m_linCFM; - btScalar m_linERP; - btScalar m_angCFM; - -protected: + int m_flags; + btScalar m_linCFM; + btScalar m_linERP; + btScalar m_angCFM; +protected: void init(); - void computeConeLimitInfo(const btQuaternion& qCone, // in - btScalar& swingAngle, btVector3& vSwingAxis, btScalar& swingLimit); // all outs + void computeConeLimitInfo(const btQuaternion& qCone, // in + btScalar& swingAngle, btVector3& vSwingAxis, btScalar& swingLimit); // all outs - void computeTwistLimitInfo(const btQuaternion& qTwist, // in - btScalar& twistAngle, btVector3& vTwistAxis); // all outs - - void adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const; + void computeTwistLimitInfo(const btQuaternion& qTwist, // in + btScalar& twistAngle, btVector3& vTwistAxis); // all outs + void adjustSwingAxisToUseEllipseNormal(btVector3 & vSwingAxis) const; public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame); - - btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame); + btConeTwistConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame); + + btConeTwistConstraint(btRigidBody & rbA, const btTransform& rbAFrame); + + virtual void buildJacobian(); - virtual void buildJacobian(); + virtual void getInfo1(btConstraintInfo1 * info); - virtual void getInfo1 (btConstraintInfo1* info); + void getInfo1NonVirtual(btConstraintInfo1 * info); - void getInfo1NonVirtual(btConstraintInfo1* info); - - virtual void getInfo2 (btConstraintInfo2* info); - - void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB); + virtual void getInfo2(btConstraintInfo2 * info); - virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep); + void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB); - - void updateRHS(btScalar timeStep); + virtual void solveConstraintObsolete(btSolverBody & bodyA, btSolverBody & bodyB, btScalar timeStep); + void updateRHS(btScalar timeStep); const btRigidBody& getRigidBodyA() const { @@ -166,64 +157,64 @@ public: return m_rbB; } - void setAngularOnly(bool angularOnly) + void setAngularOnly(bool angularOnly) { m_angularOnly = angularOnly; } - - bool getAngularOnly() const + + bool getAngularOnly() const { - return m_angularOnly; + return m_angularOnly; } - void setLimit(int limitIndex,btScalar limitValue) + void setLimit(int limitIndex, btScalar limitValue) { switch (limitIndex) { - case 3: + case 3: { m_twistSpan = limitValue; break; } - case 4: + case 4: { m_swingSpan2 = limitValue; break; } - case 5: + case 5: { m_swingSpan1 = limitValue; break; } - default: + default: { } }; } - btScalar getLimit(int limitIndex) const + btScalar getLimit(int limitIndex) const { switch (limitIndex) { - case 3: + case 3: { return m_twistSpan; break; } - case 4: + case 4: { return m_swingSpan2; break; } - case 5: + case 5: { return m_swingSpan1; break; } - default: + default: { - btAssert(0 && "Invalid limitIndex specified for btConeTwistConstraint"); - return 0.0; + btAssert(0 && "Invalid limitIndex specified for btConeTwistConstraint"); + return 0.0; } }; } @@ -239,18 +230,18 @@ public: // __relaxationFactor: // 0->1, recommend to stay near 1. // the lower the value, the less the constraint will fight velocities which violate the angular limits. - void setLimit(btScalar _swingSpan1,btScalar _swingSpan2,btScalar _twistSpan, btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) + void setLimit(btScalar _swingSpan1, btScalar _swingSpan2, btScalar _twistSpan, btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) { m_swingSpan1 = _swingSpan1; m_swingSpan2 = _swingSpan2; - m_twistSpan = _twistSpan; + m_twistSpan = _twistSpan; - m_limitSoftness = _softness; + m_limitSoftness = _softness; m_biasFactor = _biasFactor; m_relaxationFactor = _relaxationFactor; } - const btTransform& getAFrame() const { return m_rbAFrame; }; + const btTransform& getAFrame() const { return m_rbAFrame; }; const btTransform& getBFrame() const { return m_rbBFrame; }; inline int getSolveTwistLimit() @@ -269,7 +260,7 @@ public: } void calcAngleInfo(); - void calcAngleInfo2(const btTransform& transA, const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB); + void calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB); inline btScalar getSwingSpan1() const { @@ -308,8 +299,16 @@ public: bool isMotorEnabled() const { return m_bMotorEnabled; } btScalar getMaxMotorImpulse() const { return m_maxMotorImpulse; } bool isMaxMotorImpulseNormalized() const { return m_bNormalizedMotorStrength; } - void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = false; } - void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = true; } + void setMaxMotorImpulse(btScalar maxMotorImpulse) + { + m_maxMotorImpulse = maxMotorImpulse; + m_bNormalizedMotorStrength = false; + } + void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse) + { + m_maxMotorImpulse = maxMotorImpulse; + m_bNormalizedMotorStrength = true; + } btScalar getFixThresh() { return m_fixThresh; } void setFixThresh(btScalar fixThresh) { m_fixThresh = fixThresh; } @@ -318,17 +317,17 @@ public: // q: the desired rotation of bodyA wrt bodyB. // note: if q violates the joint limits, the internal target is clamped to avoid conflicting impulses (very bad for stability) // note: don't forget to enableMotor() - void setMotorTarget(const btQuaternion &q); + void setMotorTarget(const btQuaternion& q); const btQuaternion& getMotorTarget() const { return m_qTarget; } // same as above, but q is the desired rotation of frameA wrt frameB in constraint space - void setMotorTargetInConstraintSpace(const btQuaternion &q); + void setMotorTargetInConstraintSpace(const btQuaternion& q); btVector3 GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const; - ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). ///If no axis is provided, it uses the default axis for this constraint. - virtual void setParam(int num, btScalar value, int axis = -1); + virtual void setParam(int num, btScalar value, int axis = -1); virtual void setFrames(const btTransform& frameA, const btTransform& frameB); @@ -342,84 +341,74 @@ public: return m_rbBFrame; } - ///return the local value of parameter - virtual btScalar getParam(int num, int axis = -1) const; + virtual btScalar getParam(int num, int axis = -1) const; int getFlags() const { return m_flags; } - virtual int calculateSerializeBufferSize() const; + virtual int calculateSerializeBufferSize() const; ///fills the dataBuffer and returns the struct name (and 0 on failure) - virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; - + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; }; - - -struct btConeTwistConstraintDoubleData +struct btConeTwistConstraintDoubleData { - btTypedConstraintDoubleData m_typeConstraintData; + btTypedConstraintDoubleData m_typeConstraintData; btTransformDoubleData m_rbAFrame; btTransformDoubleData m_rbBFrame; //limits - double m_swingSpan1; - double m_swingSpan2; - double m_twistSpan; - double m_limitSoftness; - double m_biasFactor; - double m_relaxationFactor; - - double m_damping; - - - + double m_swingSpan1; + double m_swingSpan2; + double m_twistSpan; + double m_limitSoftness; + double m_biasFactor; + double m_relaxationFactor; + + double m_damping; }; #ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION ///this structure is not used, except for loading pre-2.82 .bullet files -struct btConeTwistConstraintData +struct btConeTwistConstraintData { - btTypedConstraintData m_typeConstraintData; + btTypedConstraintData m_typeConstraintData; btTransformFloatData m_rbAFrame; btTransformFloatData m_rbBFrame; //limits - float m_swingSpan1; - float m_swingSpan2; - float m_twistSpan; - float m_limitSoftness; - float m_biasFactor; - float m_relaxationFactor; - - float m_damping; - - char m_pad[4]; + float m_swingSpan1; + float m_swingSpan2; + float m_twistSpan; + float m_limitSoftness; + float m_biasFactor; + float m_relaxationFactor; + float m_damping; + + char m_pad[4]; }; -#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION +#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION // -SIMD_FORCE_INLINE int btConeTwistConstraint::calculateSerializeBufferSize() const +SIMD_FORCE_INLINE int btConeTwistConstraint::calculateSerializeBufferSize() const { return sizeof(btConeTwistConstraintData2); - } - - ///fills the dataBuffer and returns the struct name (and 0 on failure) -SIMD_FORCE_INLINE const char* btConeTwistConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btConeTwistConstraint::serialize(void* dataBuffer, btSerializer* serializer) const { - btConeTwistConstraintData2* cone = (btConeTwistConstraintData2*) dataBuffer; - btTypedConstraint::serialize(&cone->m_typeConstraintData,serializer); + btConeTwistConstraintData2* cone = (btConeTwistConstraintData2*)dataBuffer; + btTypedConstraint::serialize(&cone->m_typeConstraintData, serializer); m_rbAFrame.serialize(cone->m_rbAFrame); m_rbBFrame.serialize(cone->m_rbBFrame); - + cone->m_swingSpan1 = m_swingSpan1; cone->m_swingSpan2 = m_swingSpan2; cone->m_twistSpan = m_twistSpan; @@ -431,5 +420,4 @@ SIMD_FORCE_INLINE const char* btConeTwistConstraint::serialize(void* dataBuffer, return btConeTwistConstraintDataName; } - -#endif //BT_CONETWISTCONSTRAINT_H +#endif //BT_CONETWISTCONSTRAINT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h index 0491639f70..808433477c 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h @@ -26,41 +26,33 @@ struct btContactSolverInfo; struct btBroadphaseProxy; class btIDebugDraw; class btStackAlloc; -class btDispatcher; +class btDispatcher; /// btConstraintSolver provides solver interface - enum btConstraintSolverType { - BT_SEQUENTIAL_IMPULSE_SOLVER=1, - BT_MLCP_SOLVER=2, - BT_NNCG_SOLVER=4, - BT_MULTIBODY_SOLVER=8, + BT_SEQUENTIAL_IMPULSE_SOLVER = 1, + BT_MLCP_SOLVER = 2, + BT_NNCG_SOLVER = 4, + BT_MULTIBODY_SOLVER = 8, }; class btConstraintSolver { - public: - virtual ~btConstraintSolver() {} - - virtual void prepareSolve (int /* numBodies */, int /* numManifolds */) {;} + + virtual void prepareSolve(int /* numBodies */, int /* numManifolds */) { ; } ///solve a group of constraints - virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer,btDispatcher* dispatcher) = 0; + virtual btScalar solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, class btIDebugDraw* debugDrawer, btDispatcher* dispatcher) = 0; - virtual void allSolved (const btContactSolverInfo& /* info */,class btIDebugDraw* /* debugDrawer */) {;} + virtual void allSolved(const btContactSolverInfo& /* info */, class btIDebugDraw* /* debugDrawer */) { ; } ///clear internal cached data and reset random seed - virtual void reset() = 0; - - virtual btConstraintSolverType getSolverType() const=0; - + virtual void reset() = 0; + virtual btConstraintSolverType getSolverType() const = 0; }; - - - -#endif //BT_CONSTRAINT_SOLVER_H +#endif //BT_CONSTRAINT_SOLVER_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp index 1098d0c96b..4b22b2fff5 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp @@ -13,7 +13,6 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ - #include "btContactConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btVector3.h" @@ -22,44 +21,33 @@ subject to the following restrictions: #include "LinearMath/btMinMax.h" #include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" - - -btContactConstraint::btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB) -:btTypedConstraint(CONTACT_CONSTRAINT_TYPE,rbA,rbB), - m_contactManifold(*contactManifold) +btContactConstraint::btContactConstraint(btPersistentManifold* contactManifold, btRigidBody& rbA, btRigidBody& rbB) + : btTypedConstraint(CONTACT_CONSTRAINT_TYPE, rbA, rbB), + m_contactManifold(*contactManifold) { - } btContactConstraint::~btContactConstraint() { - } -void btContactConstraint::setContactManifold(btPersistentManifold* contactManifold) +void btContactConstraint::setContactManifold(btPersistentManifold* contactManifold) { m_contactManifold = *contactManifold; } -void btContactConstraint::getInfo1 (btConstraintInfo1* info) +void btContactConstraint::getInfo1(btConstraintInfo1* info) { - } -void btContactConstraint::getInfo2 (btConstraintInfo2* info) +void btContactConstraint::getInfo2(btConstraintInfo2* info) { - } -void btContactConstraint::buildJacobian() +void btContactConstraint::buildJacobian() { - } - - - - #include "btContactConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btVector3.h" @@ -68,64 +56,59 @@ void btContactConstraint::buildJacobian() #include "LinearMath/btMinMax.h" #include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" - - //response between two dynamic objects without friction and no restitution, assuming 0 penetration depth btScalar resolveSingleCollision( - btRigidBody* body1, - btCollisionObject* colObj2, - const btVector3& contactPositionWorld, - const btVector3& contactNormalOnB, - const btContactSolverInfo& solverInfo, - btScalar distance) + btRigidBody* body1, + btCollisionObject* colObj2, + const btVector3& contactPositionWorld, + const btVector3& contactNormalOnB, + const btContactSolverInfo& solverInfo, + btScalar distance) { btRigidBody* body2 = btRigidBody::upcast(colObj2); - - - const btVector3& normal = contactNormalOnB; - - btVector3 rel_pos1 = contactPositionWorld - body1->getWorldTransform().getOrigin(); - btVector3 rel_pos2 = contactPositionWorld - colObj2->getWorldTransform().getOrigin(); - - btVector3 vel1 = body1->getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2? body2->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); - btVector3 vel = vel1 - vel2; - btScalar rel_vel; - rel_vel = normal.dot(vel); - - btScalar combinedRestitution = 0.f; - btScalar restitution = combinedRestitution* -rel_vel; - - btScalar positionalError = solverInfo.m_erp *-distance /solverInfo.m_timeStep ; - btScalar velocityError = -(1.0f + restitution) * rel_vel;// * damping; - btScalar denom0 = body1->computeImpulseDenominator(contactPositionWorld,normal); - btScalar denom1 = body2? body2->computeImpulseDenominator(contactPositionWorld,normal) : 0.f; + + const btVector3& normal = contactNormalOnB; + + btVector3 rel_pos1 = contactPositionWorld - body1->getWorldTransform().getOrigin(); + btVector3 rel_pos2 = contactPositionWorld - colObj2->getWorldTransform().getOrigin(); + + btVector3 vel1 = body1->getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2 ? body2->getVelocityInLocalPoint(rel_pos2) : btVector3(0, 0, 0); + btVector3 vel = vel1 - vel2; + btScalar rel_vel; + rel_vel = normal.dot(vel); + + btScalar combinedRestitution = 0.f; + btScalar restitution = combinedRestitution * -rel_vel; + + btScalar positionalError = solverInfo.m_erp * -distance / solverInfo.m_timeStep; + btScalar velocityError = -(1.0f + restitution) * rel_vel; // * damping; + btScalar denom0 = body1->computeImpulseDenominator(contactPositionWorld, normal); + btScalar denom1 = body2 ? body2->computeImpulseDenominator(contactPositionWorld, normal) : 0.f; btScalar relaxation = 1.f; - btScalar jacDiagABInv = relaxation/(denom0+denom1); + btScalar jacDiagABInv = relaxation / (denom0 + denom1); - btScalar penetrationImpulse = positionalError * jacDiagABInv; - btScalar velocityImpulse = velocityError * jacDiagABInv; + btScalar penetrationImpulse = positionalError * jacDiagABInv; + btScalar velocityImpulse = velocityError * jacDiagABInv; - btScalar normalImpulse = penetrationImpulse+velocityImpulse; - normalImpulse = 0.f > normalImpulse ? 0.f: normalImpulse; + btScalar normalImpulse = penetrationImpulse + velocityImpulse; + normalImpulse = 0.f > normalImpulse ? 0.f : normalImpulse; - body1->applyImpulse(normal*(normalImpulse), rel_pos1); - if (body2) - body2->applyImpulse(-normal*(normalImpulse), rel_pos2); - - return normalImpulse; -} + body1->applyImpulse(normal * (normalImpulse), rel_pos1); + if (body2) + body2->applyImpulse(-normal * (normalImpulse), rel_pos2); + return normalImpulse; +} //bilateral constraint between two dynamic objects void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, - btRigidBody& body2, const btVector3& pos2, - btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep) + btRigidBody& body2, const btVector3& pos2, + btScalar distance, const btVector3& normal, btScalar& impulse, btScalar timeStep) { (void)timeStep; (void)distance; - btScalar normalLenSqr = normal.length2(); btAssert(btFabs(normalLenSqr) < btScalar(1.1)); if (normalLenSqr > btScalar(1.1)) @@ -133,45 +116,38 @@ void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, impulse = btScalar(0.); return; } - btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); + btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); //this jacobian entry could be re-used for all iterations - + btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); btVector3 vel = vel1 - vel2; - - btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(), - body2.getCenterOfMassTransform().getBasis().transpose(), - rel_pos1,rel_pos2,normal,body1.getInvInertiaDiagLocal(),body1.getInvMass(), - body2.getInvInertiaDiagLocal(),body2.getInvMass()); + btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(), + body2.getCenterOfMassTransform().getBasis().transpose(), + rel_pos1, rel_pos2, normal, body1.getInvInertiaDiagLocal(), body1.getInvMass(), + body2.getInvInertiaDiagLocal(), body2.getInvMass()); btScalar jacDiagAB = jac.getDiagonal(); btScalar jacDiagABInv = btScalar(1.) / jacDiagAB; - - btScalar rel_vel = jac.getRelativeVelocity( + + btScalar rel_vel = jac.getRelativeVelocity( body1.getLinearVelocity(), body1.getCenterOfMassTransform().getBasis().transpose() * body1.getAngularVelocity(), body2.getLinearVelocity(), - body2.getCenterOfMassTransform().getBasis().transpose() * body2.getAngularVelocity()); - - + body2.getCenterOfMassTransform().getBasis().transpose() * body2.getAngularVelocity()); rel_vel = normal.dot(vel); - + //todo: move this into proper structure btScalar contactDamping = btScalar(0.2); #ifdef ONLY_USE_LINEAR_MASS btScalar massTerm = btScalar(1.) / (body1.getInvMass() + body2.getInvMass()); - impulse = - contactDamping * rel_vel * massTerm; -#else + impulse = -contactDamping * rel_vel * massTerm; +#else btScalar velocityImpulse = -contactDamping * rel_vel * jacDiagABInv; impulse = velocityImpulse; #endif } - - - - diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h index adb2268353..255489be99 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h @@ -22,20 +22,17 @@ subject to the following restrictions: #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" ///btContactConstraint can be automatically created to solve contact constraints using the unified btTypedConstraint interface -ATTRIBUTE_ALIGNED16(class) btContactConstraint : public btTypedConstraint +ATTRIBUTE_ALIGNED16(class) +btContactConstraint : public btTypedConstraint { protected: - btPersistentManifold m_contactManifold; protected: - - - btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB); + btContactConstraint(btPersistentManifold * contactManifold, btRigidBody & rbA, btRigidBody & rbB); public: - - void setContactManifold(btPersistentManifold* contactManifold); + void setContactManifold(btPersistentManifold * contactManifold); btPersistentManifold* getContactManifold() { @@ -49,25 +46,20 @@ public: virtual ~btContactConstraint(); - virtual void getInfo1 (btConstraintInfo1* info); + virtual void getInfo1(btConstraintInfo1 * info); - virtual void getInfo2 (btConstraintInfo2* info); + virtual void getInfo2(btConstraintInfo2 * info); ///obsolete methods - virtual void buildJacobian(); - - + virtual void buildJacobian(); }; ///very basic collision resolution without friction -btScalar resolveSingleCollision(btRigidBody* body1, class btCollisionObject* colObj2, const btVector3& contactPositionWorld,const btVector3& contactNormalOnB, const struct btContactSolverInfo& solverInfo,btScalar distance); - +btScalar resolveSingleCollision(btRigidBody* body1, class btCollisionObject* colObj2, const btVector3& contactPositionWorld, const btVector3& contactNormalOnB, const struct btContactSolverInfo& solverInfo, btScalar distance); ///resolveSingleBilateral is an obsolete methods used for vehicle friction between two dynamic objects void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, - btRigidBody& body2, const btVector3& pos2, - btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep); - - + btRigidBody& body2, const btVector3& pos2, + btScalar distance, const btVector3& normal, btScalar& impulse, btScalar timeStep); -#endif //BT_CONTACT_CONSTRAINT_H +#endif //BT_CONTACT_CONSTRAINT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h index 93865cbc59..89f8db8b1a 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h @@ -18,7 +18,7 @@ subject to the following restrictions: #include "LinearMath/btScalar.h" -enum btSolverMode +enum btSolverMode { SOLVER_RANDMIZE_ORDER = 1, SOLVER_FRICTION_SEPARATE = 2, @@ -35,134 +35,129 @@ enum btSolverMode struct btContactSolverInfoData { - - - btScalar m_tau; - btScalar m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'. - btScalar m_friction; - btScalar m_timeStep; - btScalar m_restitution; - int m_numIterations; - btScalar m_maxErrorReduction; - btScalar m_sor;//successive over-relaxation term - btScalar m_erp;//error reduction for non-contact constraints - btScalar m_erp2;//error reduction for contact constraints - btScalar m_globalCfm;//constraint force mixing for contacts and non-contacts - btScalar m_frictionERP;//error reduction for friction constraints - btScalar m_frictionCFM;//constraint force mixing for friction constraints - - int m_splitImpulse; - btScalar m_splitImpulsePenetrationThreshold; - btScalar m_splitImpulseTurnErp; - btScalar m_linearSlop; - btScalar m_warmstartingFactor; - - int m_solverMode; - int m_restingContactRestitutionThreshold; - int m_minimumSolverBatchSize; - btScalar m_maxGyroscopicForce; - btScalar m_singleAxisRollingFrictionThreshold; - btScalar m_leastSquaresResidualThreshold; - btScalar m_restitutionVelocityThreshold; - + btScalar m_tau; + btScalar m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'. + btScalar m_friction; + btScalar m_timeStep; + btScalar m_restitution; + int m_numIterations; + btScalar m_maxErrorReduction; + btScalar m_sor; //successive over-relaxation term + btScalar m_erp; //error reduction for non-contact constraints + btScalar m_erp2; //error reduction for contact constraints + btScalar m_globalCfm; //constraint force mixing for contacts and non-contacts + btScalar m_frictionERP; //error reduction for friction constraints + btScalar m_frictionCFM; //constraint force mixing for friction constraints + + int m_splitImpulse; + btScalar m_splitImpulsePenetrationThreshold; + btScalar m_splitImpulseTurnErp; + btScalar m_linearSlop; + btScalar m_warmstartingFactor; + + int m_solverMode; + int m_restingContactRestitutionThreshold; + int m_minimumSolverBatchSize; + btScalar m_maxGyroscopicForce; + btScalar m_singleAxisRollingFrictionThreshold; + btScalar m_leastSquaresResidualThreshold; + btScalar m_restitutionVelocityThreshold; + bool m_jointFeedbackInWorldSpace; + bool m_jointFeedbackInJointFrame; }; struct btContactSolverInfo : public btContactSolverInfoData { - - - inline btContactSolverInfo() { m_tau = btScalar(0.6); m_damping = btScalar(1.0); m_friction = btScalar(0.3); - m_timeStep = btScalar(1.f/60.f); + m_timeStep = btScalar(1.f / 60.f); m_restitution = btScalar(0.); m_maxErrorReduction = btScalar(20.); m_numIterations = 10; m_erp = btScalar(0.2); m_erp2 = btScalar(0.2); m_globalCfm = btScalar(0.); - m_frictionERP = btScalar(0.2);//positional friction 'anchors' are disabled by default + m_frictionERP = btScalar(0.2); //positional friction 'anchors' are disabled by default m_frictionCFM = btScalar(0.); m_sor = btScalar(1.); m_splitImpulse = true; m_splitImpulsePenetrationThreshold = -.04f; m_splitImpulseTurnErp = 0.1f; m_linearSlop = btScalar(0.0); - m_warmstartingFactor=btScalar(0.85); + m_warmstartingFactor = btScalar(0.85); //m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD | SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION|SOLVER_USE_2_FRICTION_DIRECTIONS|SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;// | SOLVER_RANDMIZE_ORDER; - m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD;// | SOLVER_RANDMIZE_ORDER; - m_restingContactRestitutionThreshold = 2;//unused as of 2.81 - m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit - m_maxGyroscopicForce = 100.f; ///it is only used for 'explicit' version of gyroscopic force - m_singleAxisRollingFrictionThreshold = 1e30f;///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows. + m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD; // | SOLVER_RANDMIZE_ORDER; + m_restingContactRestitutionThreshold = 2; //unused as of 2.81 + m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit + m_maxGyroscopicForce = 100.f; ///it is only used for 'explicit' version of gyroscopic force + m_singleAxisRollingFrictionThreshold = 1e30f; ///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows. m_leastSquaresResidualThreshold = 0.f; - m_restitutionVelocityThreshold = 0.2f;//if the relative velocity is below this threshold, there is zero restitution + m_restitutionVelocityThreshold = 0.2f; //if the relative velocity is below this threshold, there is zero restitution + m_jointFeedbackInWorldSpace = false; + m_jointFeedbackInJointFrame = false; } }; ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 struct btContactSolverInfoDoubleData { - double m_tau; - double m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'. - double m_friction; - double m_timeStep; - double m_restitution; - double m_maxErrorReduction; - double m_sor; - double m_erp;//used as Baumgarte factor - double m_erp2;//used in Split Impulse - double m_globalCfm;//constraint force mixing - double m_splitImpulsePenetrationThreshold; - double m_splitImpulseTurnErp; - double m_linearSlop; - double m_warmstartingFactor; - double m_maxGyroscopicForce;///it is only used for 'explicit' version of gyroscopic force - double m_singleAxisRollingFrictionThreshold; - - int m_numIterations; - int m_solverMode; - int m_restingContactRestitutionThreshold; - int m_minimumSolverBatchSize; - int m_splitImpulse; - char m_padding[4]; - + double m_tau; + double m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'. + double m_friction; + double m_timeStep; + double m_restitution; + double m_maxErrorReduction; + double m_sor; + double m_erp; //used as Baumgarte factor + double m_erp2; //used in Split Impulse + double m_globalCfm; //constraint force mixing + double m_splitImpulsePenetrationThreshold; + double m_splitImpulseTurnErp; + double m_linearSlop; + double m_warmstartingFactor; + double m_maxGyroscopicForce; ///it is only used for 'explicit' version of gyroscopic force + double m_singleAxisRollingFrictionThreshold; + + int m_numIterations; + int m_solverMode; + int m_restingContactRestitutionThreshold; + int m_minimumSolverBatchSize; + int m_splitImpulse; + char m_padding[4]; }; ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 struct btContactSolverInfoFloatData { - float m_tau; - float m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'. - float m_friction; - float m_timeStep; - - float m_restitution; - float m_maxErrorReduction; - float m_sor; - float m_erp;//used as Baumgarte factor - - float m_erp2;//used in Split Impulse - float m_globalCfm;//constraint force mixing - float m_splitImpulsePenetrationThreshold; - float m_splitImpulseTurnErp; - - float m_linearSlop; - float m_warmstartingFactor; - float m_maxGyroscopicForce; - float m_singleAxisRollingFrictionThreshold; - - int m_numIterations; - int m_solverMode; - int m_restingContactRestitutionThreshold; - int m_minimumSolverBatchSize; - - int m_splitImpulse; - char m_padding[4]; + float m_tau; + float m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'. + float m_friction; + float m_timeStep; + + float m_restitution; + float m_maxErrorReduction; + float m_sor; + float m_erp; //used as Baumgarte factor + + float m_erp2; //used in Split Impulse + float m_globalCfm; //constraint force mixing + float m_splitImpulsePenetrationThreshold; + float m_splitImpulseTurnErp; + + float m_linearSlop; + float m_warmstartingFactor; + float m_maxGyroscopicForce; + float m_singleAxisRollingFrictionThreshold; + + int m_numIterations; + int m_solverMode; + int m_restingContactRestitutionThreshold; + int m_minimumSolverBatchSize; + + int m_splitImpulse; + char m_padding[4]; }; - - -#endif //BT_CONTACT_SOLVER_INFO +#endif //BT_CONTACT_SOLVER_INFO diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp index 75d81cc08c..bba102d905 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp @@ -13,25 +13,20 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ - #include "btFixedConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" #include <new> - -btFixedConstraint::btFixedConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& frameInA,const btTransform& frameInB) -:btGeneric6DofSpring2Constraint(rbA,rbB,frameInA,frameInB) +btFixedConstraint::btFixedConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB) + : btGeneric6DofSpring2Constraint(rbA, rbB, frameInA, frameInB) { - setAngularLowerLimit(btVector3(0,0,0)); - setAngularUpperLimit(btVector3(0,0,0)); - setLinearLowerLimit(btVector3(0,0,0)); - setLinearUpperLimit(btVector3(0,0,0)); + setAngularLowerLimit(btVector3(0, 0, 0)); + setAngularUpperLimit(btVector3(0, 0, 0)); + setLinearLowerLimit(btVector3(0, 0, 0)); + setLinearUpperLimit(btVector3(0, 0, 0)); } - - - -btFixedConstraint::~btFixedConstraint () +btFixedConstraint::~btFixedConstraint() { } diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.h index bff2008b28..6d474ea81d 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.h @@ -18,16 +18,13 @@ subject to the following restrictions: #include "btGeneric6DofSpring2Constraint.h" - -ATTRIBUTE_ALIGNED16(class) btFixedConstraint : public btGeneric6DofSpring2Constraint +ATTRIBUTE_ALIGNED16(class) +btFixedConstraint : public btGeneric6DofSpring2Constraint { - public: - btFixedConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& frameInA,const btTransform& frameInB); + btFixedConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB); - virtual ~btFixedConstraint(); - }; -#endif //BT_FIXED_CONSTRAINT_H +#endif //BT_FIXED_CONSTRAINT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.cpp index bcd457b673..7535c52c05 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.cpp @@ -17,38 +17,36 @@ subject to the following restrictions: #include "btGearConstraint.h" -btGearConstraint::btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA,const btVector3& axisInB, btScalar ratio) -:btTypedConstraint(GEAR_CONSTRAINT_TYPE,rbA,rbB), -m_axisInA(axisInA), -m_axisInB(axisInB), -m_ratio(ratio) +btGearConstraint::btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA, const btVector3& axisInB, btScalar ratio) + : btTypedConstraint(GEAR_CONSTRAINT_TYPE, rbA, rbB), + m_axisInA(axisInA), + m_axisInB(axisInB), + m_ratio(ratio) { } -btGearConstraint::~btGearConstraint () +btGearConstraint::~btGearConstraint() { } -void btGearConstraint::getInfo1 (btConstraintInfo1* info) +void btGearConstraint::getInfo1(btConstraintInfo1* info) { info->m_numConstraintRows = 1; info->nub = 1; } -void btGearConstraint::getInfo2 (btConstraintInfo2* info) +void btGearConstraint::getInfo2(btConstraintInfo2* info) { btVector3 globalAxisA, globalAxisB; - globalAxisA = m_rbA.getWorldTransform().getBasis()*this->m_axisInA; - globalAxisB = m_rbB.getWorldTransform().getBasis()*this->m_axisInB; + globalAxisA = m_rbA.getWorldTransform().getBasis() * this->m_axisInA; + globalAxisB = m_rbB.getWorldTransform().getBasis() * this->m_axisInB; info->m_J1angularAxis[0] = globalAxisA[0]; info->m_J1angularAxis[1] = globalAxisA[1]; info->m_J1angularAxis[2] = globalAxisA[2]; - info->m_J2angularAxis[0] = m_ratio*globalAxisB[0]; - info->m_J2angularAxis[1] = m_ratio*globalAxisB[1]; - info->m_J2angularAxis[2] = m_ratio*globalAxisB[2]; - + info->m_J2angularAxis[0] = m_ratio * globalAxisB[0]; + info->m_J2angularAxis[1] = m_ratio * globalAxisB[1]; + info->m_J2angularAxis[2] = m_ratio * globalAxisB[2]; } - diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.h index e4613455a2..64b15dfbce 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.h @@ -13,45 +13,40 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ - - #ifndef BT_GEAR_CONSTRAINT_H #define BT_GEAR_CONSTRAINT_H #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" - #ifdef BT_USE_DOUBLE_PRECISION -#define btGearConstraintData btGearConstraintDoubleData -#define btGearConstraintDataName "btGearConstraintDoubleData" +#define btGearConstraintData btGearConstraintDoubleData +#define btGearConstraintDataName "btGearConstraintDoubleData" #else -#define btGearConstraintData btGearConstraintFloatData -#define btGearConstraintDataName "btGearConstraintFloatData" -#endif //BT_USE_DOUBLE_PRECISION - - +#define btGearConstraintData btGearConstraintFloatData +#define btGearConstraintDataName "btGearConstraintFloatData" +#endif //BT_USE_DOUBLE_PRECISION ///The btGeatConstraint will couple the angular velocity for two bodies around given local axis and ratio. ///See Bullet/Demos/ConstraintDemo for an example use. class btGearConstraint : public btTypedConstraint { protected: - btVector3 m_axisInA; - btVector3 m_axisInB; - bool m_useFrameA; - btScalar m_ratio; + btVector3 m_axisInA; + btVector3 m_axisInB; + bool m_useFrameA; + btScalar m_ratio; public: - btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA,const btVector3& axisInB, btScalar ratio=1.f); - virtual ~btGearConstraint (); + btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA, const btVector3& axisInB, btScalar ratio = 1.f); + virtual ~btGearConstraint(); ///internal method used by the constraint solver, don't use them directly - virtual void getInfo1 (btConstraintInfo1* info); + virtual void getInfo1(btConstraintInfo1* info); ///internal method used by the constraint solver, don't use them directly - virtual void getInfo2 (btConstraintInfo2* info); + virtual void getInfo2(btConstraintInfo2* info); - void setAxisA(btVector3& axisA) + void setAxisA(btVector3& axisA) { m_axisInA = axisA; } @@ -76,68 +71,64 @@ public: return m_ratio; } - - virtual void setParam(int num, btScalar value, int axis = -1) + virtual void setParam(int num, btScalar value, int axis = -1) { - (void) num; - (void) value; - (void) axis; + (void)num; + (void)value; + (void)axis; btAssert(0); } ///return the local value of parameter - virtual btScalar getParam(int num, int axis = -1) const - { - (void) num; - (void) axis; + virtual btScalar getParam(int num, int axis = -1) const + { + (void)num; + (void)axis; btAssert(0); return 0.f; } - virtual int calculateSerializeBufferSize() const; + virtual int calculateSerializeBufferSize() const; ///fills the dataBuffer and returns the struct name (and 0 on failure) - virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; }; - - - ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 struct btGearConstraintFloatData { - btTypedConstraintFloatData m_typeConstraintData; + btTypedConstraintFloatData m_typeConstraintData; - btVector3FloatData m_axisInA; - btVector3FloatData m_axisInB; + btVector3FloatData m_axisInA; + btVector3FloatData m_axisInB; - float m_ratio; - char m_padding[4]; + float m_ratio; + char m_padding[4]; }; struct btGearConstraintDoubleData { - btTypedConstraintDoubleData m_typeConstraintData; + btTypedConstraintDoubleData m_typeConstraintData; - btVector3DoubleData m_axisInA; - btVector3DoubleData m_axisInB; + btVector3DoubleData m_axisInA; + btVector3DoubleData m_axisInB; - double m_ratio; + double m_ratio; }; -SIMD_FORCE_INLINE int btGearConstraint::calculateSerializeBufferSize() const +SIMD_FORCE_INLINE int btGearConstraint::calculateSerializeBufferSize() const { return sizeof(btGearConstraintData); } - ///fills the dataBuffer and returns the struct name (and 0 on failure) -SIMD_FORCE_INLINE const char* btGearConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btGearConstraint::serialize(void* dataBuffer, btSerializer* serializer) const { btGearConstraintData* gear = (btGearConstraintData*)dataBuffer; - btTypedConstraint::serialize(&gear->m_typeConstraintData,serializer); + btTypedConstraint::serialize(&gear->m_typeConstraintData, serializer); - m_axisInA.serialize( gear->m_axisInA ); - m_axisInB.serialize( gear->m_axisInB ); + m_axisInA.serialize(gear->m_axisInA); + m_axisInB.serialize(gear->m_axisInB); gear->m_ratio = m_ratio; @@ -152,9 +143,4 @@ SIMD_FORCE_INLINE const char* btGearConstraint::serialize(void* dataBuffer, btSe return btGearConstraintDataName; } - - - - - -#endif //BT_GEAR_CONSTRAINT_H +#endif //BT_GEAR_CONSTRAINT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp index c38b8353f0..1f54203532 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp @@ -25,83 +25,61 @@ http://gimpact.sf.net #include "LinearMath/btTransformUtil.h" #include <new> - - #define D6_USE_OBSOLETE_METHOD false #define D6_USE_FRAME_OFFSET true - - - - - btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) -: btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB) -, m_frameInA(frameInA) -, m_frameInB(frameInB), -m_useLinearReferenceFrameA(useLinearReferenceFrameA), -m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET), -m_flags(0), -m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD) + : btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB), m_frameInA(frameInA), m_frameInB(frameInB), m_useLinearReferenceFrameA(useLinearReferenceFrameA), m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET), m_flags(0), m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD) { calculateTransforms(); } - - btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB) - : btTypedConstraint(D6_CONSTRAINT_TYPE, getFixedBody(), rbB), - m_frameInB(frameInB), - m_useLinearReferenceFrameA(useLinearReferenceFrameB), - m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET), - m_flags(0), - m_useSolveConstraintObsolete(false) + : btTypedConstraint(D6_CONSTRAINT_TYPE, getFixedBody(), rbB), + m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameB), + m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET), + m_flags(0), + m_useSolveConstraintObsolete(false) { ///not providing rigidbody A means implicitly using worldspace for body A m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB; calculateTransforms(); } - - - #define GENERIC_D6_DISABLE_WARMSTARTING 1 - - btScalar btGetMatrixElem(const btMatrix3x3& mat, int index); btScalar btGetMatrixElem(const btMatrix3x3& mat, int index) { - int i = index%3; - int j = index/3; + int i = index % 3; + int j = index / 3; return mat[i][j]; } - - ///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html -bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz); -bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) +bool matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz); +bool matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz) { // // rot = cy*cz -cy*sz sy // // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx // // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy // - btScalar fi = btGetMatrixElem(mat,2); + btScalar fi = btGetMatrixElem(mat, 2); if (fi < btScalar(1.0f)) { if (fi > btScalar(-1.0f)) { - xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8)); - xyz[1] = btAsin(btGetMatrixElem(mat,2)); - xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); + xyz[0] = btAtan2(-btGetMatrixElem(mat, 5), btGetMatrixElem(mat, 8)); + xyz[1] = btAsin(btGetMatrixElem(mat, 2)); + xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0)); return true; } else { // WARNING. Not unique. XA - ZA = -atan2(r10,r11) - xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[0] = -btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4)); xyz[1] = -SIMD_HALF_PI; xyz[2] = btScalar(0.0); return false; @@ -110,7 +88,7 @@ bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) else { // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) - xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[0] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4)); xyz[1] = SIMD_HALF_PI; xyz[2] = 0.0; } @@ -121,52 +99,49 @@ bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) int btRotationalLimitMotor::testLimitValue(btScalar test_value) { - if(m_loLimit>m_hiLimit) + if (m_loLimit > m_hiLimit) { - m_currentLimit = 0;//Free from violation + m_currentLimit = 0; //Free from violation return 0; } if (test_value < m_loLimit) { - m_currentLimit = 1;//low limit violation - m_currentLimitError = test_value - m_loLimit; - if(m_currentLimitError>SIMD_PI) - m_currentLimitError-=SIMD_2_PI; - else if(m_currentLimitError<-SIMD_PI) - m_currentLimitError+=SIMD_2_PI; + m_currentLimit = 1; //low limit violation + m_currentLimitError = test_value - m_loLimit; + if (m_currentLimitError > SIMD_PI) + m_currentLimitError -= SIMD_2_PI; + else if (m_currentLimitError < -SIMD_PI) + m_currentLimitError += SIMD_2_PI; return 1; } - else if (test_value> m_hiLimit) + else if (test_value > m_hiLimit) { - m_currentLimit = 2;//High limit violation + m_currentLimit = 2; //High limit violation m_currentLimitError = test_value - m_hiLimit; - if(m_currentLimitError>SIMD_PI) - m_currentLimitError-=SIMD_2_PI; - else if(m_currentLimitError<-SIMD_PI) - m_currentLimitError+=SIMD_2_PI; + if (m_currentLimitError > SIMD_PI) + m_currentLimitError -= SIMD_2_PI; + else if (m_currentLimitError < -SIMD_PI) + m_currentLimitError += SIMD_2_PI; return 2; }; - m_currentLimit = 0;//Free from violation + m_currentLimit = 0; //Free from violation return 0; - } - - btScalar btRotationalLimitMotor::solveAngularLimits( - btScalar timeStep,btVector3& axis,btScalar jacDiagABInv, - btRigidBody * body0, btRigidBody * body1 ) + btScalar timeStep, btVector3& axis, btScalar jacDiagABInv, + btRigidBody* body0, btRigidBody* body1) { - if (needApplyTorques()==false) return 0.0f; + if (needApplyTorques() == false) return 0.0f; btScalar target_velocity = m_targetVelocity; btScalar maxMotorForce = m_maxMotorForce; //current error correction - if (m_currentLimit!=0) + if (m_currentLimit != 0) { - target_velocity = -m_stopERP*m_currentLimitError/(timeStep); + target_velocity = -m_stopERP * m_currentLimitError / (timeStep); maxMotorForce = m_maxLimitForce; } @@ -178,42 +153,37 @@ btScalar btRotationalLimitMotor::solveAngularLimits( btVector3 angVelB = body1->getAngularVelocity(); btVector3 vel_diff; - vel_diff = angVelA-angVelB; - - + vel_diff = angVelA - angVelB; btScalar rel_vel = axis.dot(vel_diff); // correction velocity - btScalar motor_relvel = m_limitSoftness*(target_velocity - m_damping*rel_vel); + btScalar motor_relvel = m_limitSoftness * (target_velocity - m_damping * rel_vel); - - if ( motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON ) + if (motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON) { - return 0.0f;//no need for applying force + return 0.0f; //no need for applying force } - // correction impulse - btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv; + btScalar unclippedMotorImpulse = (1 + m_bounce) * motor_relvel * jacDiagABInv; // clip correction impulse btScalar clippedMotorImpulse; ///@todo: should clip against accumulated impulse - if (unclippedMotorImpulse>0.0f) + if (unclippedMotorImpulse > 0.0f) { - clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse; + clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce ? maxMotorForce : unclippedMotorImpulse; } else { - clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse; + clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce : unclippedMotorImpulse; } - // sort with accumulated impulses - btScalar lo = btScalar(-BT_LARGE_FLOAT); - btScalar hi = btScalar(BT_LARGE_FLOAT); + btScalar lo = btScalar(-BT_LARGE_FLOAT); + btScalar hi = btScalar(BT_LARGE_FLOAT); btScalar oldaccumImpulse = m_accumulatedImpulse; btScalar sum = oldaccumImpulse + clippedMotorImpulse; @@ -227,59 +197,50 @@ btScalar btRotationalLimitMotor::solveAngularLimits( body1->applyTorqueImpulse(-motorImp); return clippedMotorImpulse; - - } //////////////////////////// End btRotationalLimitMotor //////////////////////////////////// - - - //////////////////////////// btTranslationalLimitMotor //////////////////////////////////// - int btTranslationalLimitMotor::testLimitValue(int limitIndex, btScalar test_value) { btScalar loLimit = m_lowerLimit[limitIndex]; btScalar hiLimit = m_upperLimit[limitIndex]; - if(loLimit > hiLimit) + if (loLimit > hiLimit) { - m_currentLimit[limitIndex] = 0;//Free from violation + m_currentLimit[limitIndex] = 0; //Free from violation m_currentLimitError[limitIndex] = btScalar(0.f); return 0; } if (test_value < loLimit) { - m_currentLimit[limitIndex] = 2;//low limit violation - m_currentLimitError[limitIndex] = test_value - loLimit; + m_currentLimit[limitIndex] = 2; //low limit violation + m_currentLimitError[limitIndex] = test_value - loLimit; return 2; } - else if (test_value> hiLimit) + else if (test_value > hiLimit) { - m_currentLimit[limitIndex] = 1;//High limit violation + m_currentLimit[limitIndex] = 1; //High limit violation m_currentLimitError[limitIndex] = test_value - hiLimit; return 1; }; - m_currentLimit[limitIndex] = 0;//Free from violation + m_currentLimit[limitIndex] = 0; //Free from violation m_currentLimitError[limitIndex] = btScalar(0.f); return 0; } - - btScalar btTranslationalLimitMotor::solveLinearAxis( btScalar timeStep, btScalar jacDiagABInv, - btRigidBody& body1,const btVector3 &pointInA, - btRigidBody& body2,const btVector3 &pointInB, + btRigidBody& body1, const btVector3& pointInA, + btRigidBody& body2, const btVector3& pointInB, int limit_index, - const btVector3 & axis_normal_on_a, - const btVector3 & anchorPos) + const btVector3& axis_normal_on_a, + const btVector3& anchorPos) { - ///find relative velocity // btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition(); // btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition(); @@ -292,14 +253,12 @@ btScalar btTranslationalLimitMotor::solveLinearAxis( btScalar rel_vel = axis_normal_on_a.dot(vel); - - /// apply displacement correction //positional error (zeroth order error) btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a); - btScalar lo = btScalar(-BT_LARGE_FLOAT); - btScalar hi = btScalar(BT_LARGE_FLOAT); + btScalar lo = btScalar(-BT_LARGE_FLOAT); + btScalar hi = btScalar(BT_LARGE_FLOAT); btScalar minLimit = m_lowerLimit[limit_index]; btScalar maxLimit = m_upperLimit[limit_index]; @@ -312,7 +271,6 @@ btScalar btTranslationalLimitMotor::solveLinearAxis( { depth -= maxLimit; lo = btScalar(0.); - } else { @@ -329,10 +287,7 @@ btScalar btTranslationalLimitMotor::solveLinearAxis( } } - btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv; - - - + btScalar normalImpulse = m_limitSoftness * (m_restitution * depth / timeStep - m_damping * rel_vel) * jacDiagABInv; btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index]; btScalar sum = oldNormalImpulse + normalImpulse; @@ -340,11 +295,9 @@ btScalar btTranslationalLimitMotor::solveLinearAxis( normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; btVector3 impulse_vector = axis_normal_on_a * normalImpulse; - body1.applyImpulse( impulse_vector, rel_pos1); + body1.applyImpulse(impulse_vector, rel_pos1); body2.applyImpulse(-impulse_vector, rel_pos2); - - return normalImpulse; } @@ -352,8 +305,8 @@ btScalar btTranslationalLimitMotor::solveLinearAxis( void btGeneric6DofConstraint::calculateAngleInfo() { - btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis(); - matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff); + btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse() * m_calculatedTransformB.getBasis(); + matrixToEulerXYZ(relative_frame, m_calculatedAxisAngleDiff); // in euler angle mode we do not actually constrain the angular velocity // along the axes axis[0] and axis[2] (although we do use axis[1]) : // @@ -378,31 +331,30 @@ void btGeneric6DofConstraint::calculateAngleInfo() m_calculatedAxis[0].normalize(); m_calculatedAxis[1].normalize(); m_calculatedAxis[2].normalize(); - } void btGeneric6DofConstraint::calculateTransforms() { - calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform()); } -void btGeneric6DofConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB) +void btGeneric6DofConstraint::calculateTransforms(const btTransform& transA, const btTransform& transB) { m_calculatedTransformA = transA * m_frameInA; m_calculatedTransformB = transB * m_frameInB; calculateLinearInfo(); calculateAngleInfo(); - if(m_useOffsetForConstraintFrame) - { // get weight factors depending on masses + if (m_useOffsetForConstraintFrame) + { // get weight factors depending on masses btScalar miA = getRigidBodyA().getInvMass(); btScalar miB = getRigidBodyB().getInvMass(); m_hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON); btScalar miS = miA + miB; - if(miS > btScalar(0.f)) + if (miS > btScalar(0.f)) { m_factA = miB / miS; } - else + else { m_factA = btScalar(0.5f); } @@ -410,39 +362,32 @@ void btGeneric6DofConstraint::calculateTransforms(const btTransform& transA,cons } } - - void btGeneric6DofConstraint::buildLinearJacobian( - btJacobianEntry & jacLinear,const btVector3 & normalWorld, - const btVector3 & pivotAInW,const btVector3 & pivotBInW) + btJacobianEntry& jacLinear, const btVector3& normalWorld, + const btVector3& pivotAInW, const btVector3& pivotBInW) { new (&jacLinear) btJacobianEntry( - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - pivotAInW - m_rbA.getCenterOfMassPosition(), - pivotBInW - m_rbB.getCenterOfMassPosition(), - normalWorld, - m_rbA.getInvInertiaDiagLocal(), - m_rbA.getInvMass(), - m_rbB.getInvInertiaDiagLocal(), - m_rbB.getInvMass()); + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normalWorld, + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); } - - void btGeneric6DofConstraint::buildAngularJacobian( - btJacobianEntry & jacAngular,const btVector3 & jointAxisW) + btJacobianEntry& jacAngular, const btVector3& jointAxisW) { - new (&jacAngular) btJacobianEntry(jointAxisW, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); - + new (&jacAngular) btJacobianEntry(jointAxisW, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); } - - bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index) { btScalar angle = m_calculatedAxisAngleDiff[axis_index]; @@ -453,23 +398,20 @@ bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index) return m_angularLimits[axis_index].needApplyTorques(); } - - void btGeneric6DofConstraint::buildJacobian() { #ifndef __SPU__ if (m_useSolveConstraintObsolete) { - // Clear accumulated impulses for the next simulation step m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); int i; - for(i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { m_angularLimits[i].m_accumulatedImpulse = btScalar(0.); } //calculates transform - calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform()); // const btVector3& pivotAInW = m_calculatedTransformA.getOrigin(); // const btVector3& pivotBInW = m_calculatedTransformB.getOrigin(); @@ -483,7 +425,7 @@ void btGeneric6DofConstraint::buildJacobian() btVector3 normalWorld; //linear part - for (i=0;i<3;i++) + for (i = 0; i < 3; i++) { if (m_linearLimits.isLimited(i)) { @@ -493,56 +435,53 @@ void btGeneric6DofConstraint::buildJacobian() normalWorld = m_calculatedTransformB.getBasis().getColumn(i); buildLinearJacobian( - m_jacLinear[i],normalWorld , - pivotAInW,pivotBInW); - + m_jacLinear[i], normalWorld, + pivotAInW, pivotBInW); } } // angular part - for (i=0;i<3;i++) + for (i = 0; i < 3; i++) { //calculates error angle if (testAngularLimitMotor(i)) { normalWorld = this->getAxis(i); // Create angular atom - buildAngularJacobian(m_jacAng[i],normalWorld); + buildAngularJacobian(m_jacAng[i], normalWorld); } } - } -#endif //__SPU__ - +#endif //__SPU__ } - -void btGeneric6DofConstraint::getInfo1 (btConstraintInfo1* info) +void btGeneric6DofConstraint::getInfo1(btConstraintInfo1* info) { if (m_useSolveConstraintObsolete) { info->m_numConstraintRows = 0; info->nub = 0; - } else + } + else { //prepare constraint - calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform()); info->m_numConstraintRows = 0; info->nub = 6; int i; //test linear limits - for(i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { - if(m_linearLimits.needApplyForce(i)) + if (m_linearLimits.needApplyForce(i)) { info->m_numConstraintRows++; info->nub--; } } //test angular limits - for (i=0;i<3 ;i++ ) + for (i = 0; i < 3; i++) { - if(testAngularLimitMotor(i)) + if (testAngularLimitMotor(i)) { info->m_numConstraintRows++; info->nub--; @@ -551,13 +490,14 @@ void btGeneric6DofConstraint::getInfo1 (btConstraintInfo1* info) } } -void btGeneric6DofConstraint::getInfo1NonVirtual (btConstraintInfo1* info) +void btGeneric6DofConstraint::getInfo1NonVirtual(btConstraintInfo1* info) { if (m_useSolveConstraintObsolete) { info->m_numConstraintRows = 0; info->nub = 0; - } else + } + else { //pre-allocate all 6 info->m_numConstraintRows = 6; @@ -565,8 +505,7 @@ void btGeneric6DofConstraint::getInfo1NonVirtual (btConstraintInfo1* info) } } - -void btGeneric6DofConstraint::getInfo2 (btConstraintInfo2* info) +void btGeneric6DofConstraint::getInfo2(btConstraintInfo2* info) { btAssert(!m_useSolveConstraintObsolete); @@ -577,136 +516,124 @@ void btGeneric6DofConstraint::getInfo2 (btConstraintInfo2* info) const btVector3& angVelA = m_rbA.getAngularVelocity(); const btVector3& angVelB = m_rbB.getAngularVelocity(); - if(m_useOffsetForConstraintFrame) - { // for stability better to solve angular limits first - int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB); - setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB); + if (m_useOffsetForConstraintFrame) + { // for stability better to solve angular limits first + int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB); + setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB); } else - { // leave old version for compatibility - int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB); - setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB); + { // leave old version for compatibility + int row = setLinearLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB); + setAngularLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB); } - } - -void btGeneric6DofConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB) +void btGeneric6DofConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB) { - btAssert(!m_useSolveConstraintObsolete); //prepare constraint - calculateTransforms(transA,transB); + calculateTransforms(transA, transB); int i; - for (i=0;i<3 ;i++ ) + for (i = 0; i < 3; i++) { testAngularLimitMotor(i); } - if(m_useOffsetForConstraintFrame) - { // for stability better to solve angular limits first - int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB); - setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB); + if (m_useOffsetForConstraintFrame) + { // for stability better to solve angular limits first + int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB); + setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB); } else - { // leave old version for compatibility - int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB); - setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB); + { // leave old version for compatibility + int row = setLinearLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB); + setAngularLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB); } } - - -int btGeneric6DofConstraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB) +int btGeneric6DofConstraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB) { -// int row = 0; + // int row = 0; //solve linear limits btRotationalLimitMotor limot; - for (int i=0;i<3 ;i++ ) + for (int i = 0; i < 3; i++) { - if(m_linearLimits.needApplyForce(i)) - { // re-use rotational motor code + if (m_linearLimits.needApplyForce(i)) + { // re-use rotational motor code limot.m_bounce = btScalar(0.f); limot.m_currentLimit = m_linearLimits.m_currentLimit[i]; limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i]; - limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i]; - limot.m_damping = m_linearLimits.m_damping; - limot.m_enableMotor = m_linearLimits.m_enableMotor[i]; - limot.m_hiLimit = m_linearLimits.m_upperLimit[i]; - limot.m_limitSoftness = m_linearLimits.m_limitSoftness; - limot.m_loLimit = m_linearLimits.m_lowerLimit[i]; - limot.m_maxLimitForce = btScalar(0.f); - limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i]; - limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i]; + limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i]; + limot.m_damping = m_linearLimits.m_damping; + limot.m_enableMotor = m_linearLimits.m_enableMotor[i]; + limot.m_hiLimit = m_linearLimits.m_upperLimit[i]; + limot.m_limitSoftness = m_linearLimits.m_limitSoftness; + limot.m_loLimit = m_linearLimits.m_lowerLimit[i]; + limot.m_maxLimitForce = btScalar(0.f); + limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i]; + limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i]; btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i); int flags = m_flags >> (i * BT_6DOF_FLAGS_AXIS_SHIFT); - limot.m_normalCFM = (flags & BT_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0]; - limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0]; - limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp; - if(m_useOffsetForConstraintFrame) + limot.m_normalCFM = (flags & BT_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0]; + limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0]; + limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp; + if (m_useOffsetForConstraintFrame) { int indx1 = (i + 1) % 3; int indx2 = (i + 2) % 3; - int rotAllowed = 1; // rotations around orthos to current axis - if(m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit) + int rotAllowed = 1; // rotations around orthos to current axis + if (m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit) { rotAllowed = 0; } - row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0, rotAllowed); + row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0, rotAllowed); } else { - row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0); + row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0); } } } return row; } - - -int btGeneric6DofConstraint::setAngularLimits(btConstraintInfo2 *info, int row_offset, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB) +int btGeneric6DofConstraint::setAngularLimits(btConstraintInfo2* info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB) { - btGeneric6DofConstraint * d6constraint = this; + btGeneric6DofConstraint* d6constraint = this; int row = row_offset; //solve angular limits - for (int i=0;i<3 ;i++ ) + for (int i = 0; i < 3; i++) { - if(d6constraint->getRotationalLimitMotor(i)->needApplyTorques()) + if (d6constraint->getRotationalLimitMotor(i)->needApplyTorques()) { btVector3 axis = d6constraint->getAxis(i); int flags = m_flags >> ((i + 3) * BT_6DOF_FLAGS_AXIS_SHIFT); - if(!(flags & BT_6DOF_FLAGS_CFM_NORM)) + if (!(flags & BT_6DOF_FLAGS_CFM_NORM)) { m_angularLimits[i].m_normalCFM = info->cfm[0]; } - if(!(flags & BT_6DOF_FLAGS_CFM_STOP)) + if (!(flags & BT_6DOF_FLAGS_CFM_STOP)) { m_angularLimits[i].m_stopCFM = info->cfm[0]; } - if(!(flags & BT_6DOF_FLAGS_ERP_STOP)) + if (!(flags & BT_6DOF_FLAGS_ERP_STOP)) { m_angularLimits[i].m_stopERP = info->erp; } row += get_limit_motor_info2(d6constraint->getRotationalLimitMotor(i), - transA,transB,linVelA,linVelB,angVelA,angVelB, info,row,axis,1); + transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 1); } } return row; } - - - -void btGeneric6DofConstraint::updateRHS(btScalar timeStep) +void btGeneric6DofConstraint::updateRHS(btScalar timeStep) { (void)timeStep; - } - void btGeneric6DofConstraint::setFrames(const btTransform& frameA, const btTransform& frameB) { m_frameInA = frameA; @@ -715,33 +642,27 @@ void btGeneric6DofConstraint::setFrames(const btTransform& frameA, const btTrans calculateTransforms(); } - - btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const { return m_calculatedAxis[axis_index]; } - -btScalar btGeneric6DofConstraint::getRelativePivotPosition(int axisIndex) const +btScalar btGeneric6DofConstraint::getRelativePivotPosition(int axisIndex) const { return m_calculatedLinearDiff[axisIndex]; } - btScalar btGeneric6DofConstraint::getAngle(int axisIndex) const { return m_calculatedAxisAngleDiff[axisIndex]; } - - void btGeneric6DofConstraint::calcAnchorPos(void) { btScalar imA = m_rbA.getInvMass(); btScalar imB = m_rbB.getInvMass(); btScalar weight; - if(imB == btScalar(0.0)) + if (imB == btScalar(0.0)) { weight = btScalar(1.0); } @@ -755,43 +676,39 @@ void btGeneric6DofConstraint::calcAnchorPos(void) return; } - - void btGeneric6DofConstraint::calculateLinearInfo() { m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin(); m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff; - for(int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i]; m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]); } } - - int btGeneric6DofConstraint::get_limit_motor_info2( - btRotationalLimitMotor * limot, - const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB, - btConstraintInfo2 *info, int row, btVector3& ax1, int rotational,int rotAllowed) -{ - int srow = row * info->rowskip; - bool powered = limot->m_enableMotor; - int limit = limot->m_currentLimit; - if (powered || limit) - { // if the joint is powered, or has joint limits, add in the extra row - btScalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis; - btScalar *J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis; - J1[srow+0] = ax1[0]; - J1[srow+1] = ax1[1]; - J1[srow+2] = ax1[2]; - - J2[srow+0] = -ax1[0]; - J2[srow+1] = -ax1[1]; - J2[srow+2] = -ax1[2]; - - if((!rotational)) - { + btRotationalLimitMotor* limot, + const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB, + btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed) +{ + int srow = row * info->rowskip; + bool powered = limot->m_enableMotor; + int limit = limot->m_currentLimit; + if (powered || limit) + { // if the joint is powered, or has joint limits, add in the extra row + btScalar* J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis; + btScalar* J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis; + J1[srow + 0] = ax1[0]; + J1[srow + 1] = ax1[1]; + J1[srow + 2] = ax1[2]; + + J2[srow + 0] = -ax1[0]; + J2[srow + 1] = -ax1[1]; + J2[srow + 2] = -ax1[2]; + + if ((!rotational)) + { if (m_useOffsetForConstraintFrame) { btVector3 tmpA, tmpB, relA, relB; @@ -814,55 +731,56 @@ int btGeneric6DofConstraint::get_limit_motor_info2( relB = orthoB - totalDist * m_factB; tmpA = relA.cross(ax1); tmpB = relB.cross(ax1); - if(m_hasStaticBody && (!rotAllowed)) + if (m_hasStaticBody && (!rotAllowed)) { tmpA *= m_factA; tmpB *= m_factB; } int i; - for (i=0; i<3; i++) info->m_J1angularAxis[srow+i] = tmpA[i]; - for (i=0; i<3; i++) info->m_J2angularAxis[srow+i] = -tmpB[i]; - } else + for (i = 0; i < 3; i++) info->m_J1angularAxis[srow + i] = tmpA[i]; + for (i = 0; i < 3; i++) info->m_J2angularAxis[srow + i] = -tmpB[i]; + } + else { - btVector3 ltd; // Linear Torque Decoupling vector + btVector3 ltd; // Linear Torque Decoupling vector btVector3 c = m_calculatedTransformB.getOrigin() - transA.getOrigin(); ltd = c.cross(ax1); - info->m_J1angularAxis[srow+0] = ltd[0]; - info->m_J1angularAxis[srow+1] = ltd[1]; - info->m_J1angularAxis[srow+2] = ltd[2]; + info->m_J1angularAxis[srow + 0] = ltd[0]; + info->m_J1angularAxis[srow + 1] = ltd[1]; + info->m_J1angularAxis[srow + 2] = ltd[2]; c = m_calculatedTransformB.getOrigin() - transB.getOrigin(); ltd = -c.cross(ax1); - info->m_J2angularAxis[srow+0] = ltd[0]; - info->m_J2angularAxis[srow+1] = ltd[1]; - info->m_J2angularAxis[srow+2] = ltd[2]; + info->m_J2angularAxis[srow + 0] = ltd[0]; + info->m_J2angularAxis[srow + 1] = ltd[1]; + info->m_J2angularAxis[srow + 2] = ltd[2]; } - } - // if we're limited low and high simultaneously, the joint motor is - // ineffective - if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = false; - info->m_constraintError[srow] = btScalar(0.f); - if (powered) - { + } + // if we're limited low and high simultaneously, the joint motor is + // ineffective + if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = false; + info->m_constraintError[srow] = btScalar(0.f); + if (powered) + { info->cfm[srow] = limot->m_normalCFM; - if(!limit) - { + if (!limit) + { btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity; - btScalar mot_fact = getMotorFactor( limot->m_currentPosition, - limot->m_loLimit, - limot->m_hiLimit, - tag_vel, - info->fps * limot->m_stopERP); + btScalar mot_fact = getMotorFactor(limot->m_currentPosition, + limot->m_loLimit, + limot->m_hiLimit, + tag_vel, + info->fps * limot->m_stopERP); info->m_constraintError[srow] += mot_fact * limot->m_targetVelocity; - info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps; - info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps; - } - } - if(limit) - { - btScalar k = info->fps * limot->m_stopERP; - if(!rotational) + info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps; + info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps; + } + } + if (limit) + { + btScalar k = info->fps * limot->m_stopERP; + if (!rotational) { info->m_constraintError[srow] += k * limot->m_currentLimitError; } @@ -871,116 +789,112 @@ int btGeneric6DofConstraint::get_limit_motor_info2( info->m_constraintError[srow] += -k * limot->m_currentLimitError; } info->cfm[srow] = limot->m_stopCFM; - if (limot->m_loLimit == limot->m_hiLimit) - { // limited low and high simultaneously - info->m_lowerLimit[srow] = -SIMD_INFINITY; - info->m_upperLimit[srow] = SIMD_INFINITY; - } - else - { - if (limit == 1) - { - info->m_lowerLimit[srow] = 0; - info->m_upperLimit[srow] = SIMD_INFINITY; - } - else - { - info->m_lowerLimit[srow] = -SIMD_INFINITY; - info->m_upperLimit[srow] = 0; - } - // deal with bounce - if (limot->m_bounce > 0) - { - // calculate joint velocity - btScalar vel; - if (rotational) - { - vel = angVelA.dot(ax1); -//make sure that if no body -> angVelB == zero vec -// if (body1) - vel -= angVelB.dot(ax1); - } - else - { - vel = linVelA.dot(ax1); -//make sure that if no body -> angVelB == zero vec -// if (body1) - vel -= linVelB.dot(ax1); - } - // only apply bounce if the velocity is incoming, and if the - // resulting c[] exceeds what we already have. - if (limit == 1) - { - if (vel < 0) - { - btScalar newc = -limot->m_bounce* vel; - if (newc > info->m_constraintError[srow]) + if (limot->m_loLimit == limot->m_hiLimit) + { // limited low and high simultaneously + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { + if (limit == 1) + { + info->m_lowerLimit[srow] = 0; + info->m_upperLimit[srow] = SIMD_INFINITY; + } + else + { + info->m_lowerLimit[srow] = -SIMD_INFINITY; + info->m_upperLimit[srow] = 0; + } + // deal with bounce + if (limot->m_bounce > 0) + { + // calculate joint velocity + btScalar vel; + if (rotational) + { + vel = angVelA.dot(ax1); + //make sure that if no body -> angVelB == zero vec + // if (body1) + vel -= angVelB.dot(ax1); + } + else + { + vel = linVelA.dot(ax1); + //make sure that if no body -> angVelB == zero vec + // if (body1) + vel -= linVelB.dot(ax1); + } + // only apply bounce if the velocity is incoming, and if the + // resulting c[] exceeds what we already have. + if (limit == 1) + { + if (vel < 0) + { + btScalar newc = -limot->m_bounce * vel; + if (newc > info->m_constraintError[srow]) info->m_constraintError[srow] = newc; - } - } - else - { - if (vel > 0) - { - btScalar newc = -limot->m_bounce * vel; - if (newc < info->m_constraintError[srow]) + } + } + else + { + if (vel > 0) + { + btScalar newc = -limot->m_bounce * vel; + if (newc < info->m_constraintError[srow]) info->m_constraintError[srow] = newc; - } - } - } - } - } - return 1; - } - else return 0; + } + } + } + } + } + return 1; + } + else + return 0; } - - - - - - ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). - ///If no axis is provided, it uses the default axis for this constraint. +///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). +///If no axis is provided, it uses the default axis for this constraint. void btGeneric6DofConstraint::setParam(int num, btScalar value, int axis) { - if((axis >= 0) && (axis < 3)) + if ((axis >= 0) && (axis < 3)) { - switch(num) + switch (num) { - case BT_CONSTRAINT_STOP_ERP : + case BT_CONSTRAINT_STOP_ERP: m_linearLimits.m_stopERP[axis] = value; m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); break; - case BT_CONSTRAINT_STOP_CFM : + case BT_CONSTRAINT_STOP_CFM: m_linearLimits.m_stopCFM[axis] = value; m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); break; - case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_CFM: m_linearLimits.m_normalCFM[axis] = value; m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); break; - default : + default: btAssertConstrParams(0); } } - else if((axis >=3) && (axis < 6)) + else if ((axis >= 3) && (axis < 6)) { - switch(num) + switch (num) { - case BT_CONSTRAINT_STOP_ERP : + case BT_CONSTRAINT_STOP_ERP: m_angularLimits[axis - 3].m_stopERP = value; m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); break; - case BT_CONSTRAINT_STOP_CFM : + case BT_CONSTRAINT_STOP_CFM: m_angularLimits[axis - 3].m_stopCFM = value; m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); break; - case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_CFM: m_angularLimits[axis - 3].m_normalCFM = value; m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT); break; - default : + default: btAssertConstrParams(0); } } @@ -990,47 +904,47 @@ void btGeneric6DofConstraint::setParam(int num, btScalar value, int axis) } } - ///return the local value of parameter -btScalar btGeneric6DofConstraint::getParam(int num, int axis) const +///return the local value of parameter +btScalar btGeneric6DofConstraint::getParam(int num, int axis) const { btScalar retVal = 0; - if((axis >= 0) && (axis < 3)) + if ((axis >= 0) && (axis < 3)) { - switch(num) + switch (num) { - case BT_CONSTRAINT_STOP_ERP : + case BT_CONSTRAINT_STOP_ERP: btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); retVal = m_linearLimits.m_stopERP[axis]; break; - case BT_CONSTRAINT_STOP_CFM : + case BT_CONSTRAINT_STOP_CFM: btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); retVal = m_linearLimits.m_stopCFM[axis]; break; - case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_CFM: btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); retVal = m_linearLimits.m_normalCFM[axis]; break; - default : + default: btAssertConstrParams(0); } } - else if((axis >=3) && (axis < 6)) + else if ((axis >= 3) && (axis < 6)) { - switch(num) + switch (num) { - case BT_CONSTRAINT_STOP_ERP : + case BT_CONSTRAINT_STOP_ERP: btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); retVal = m_angularLimits[axis - 3].m_stopERP; break; - case BT_CONSTRAINT_STOP_CFM : + case BT_CONSTRAINT_STOP_CFM: btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); retVal = m_angularLimits[axis - 3].m_stopCFM; break; - case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_CFM: btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT))); retVal = m_angularLimits[axis - 3].m_normalCFM; break; - default : + default: btAssertConstrParams(0); } } @@ -1041,23 +955,21 @@ btScalar btGeneric6DofConstraint::getParam(int num, int axis) const return retVal; } - - -void btGeneric6DofConstraint::setAxis(const btVector3& axis1,const btVector3& axis2) +void btGeneric6DofConstraint::setAxis(const btVector3& axis1, const btVector3& axis2) { btVector3 zAxis = axis1.normalized(); btVector3 yAxis = axis2.normalized(); - btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system - + btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system + btTransform frameInW; frameInW.setIdentity(); - frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], - xAxis[1], yAxis[1], zAxis[1], - xAxis[2], yAxis[2], zAxis[2]); - + frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); + // now get constraint frame in local coordinate systems m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW; m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW; - + calculateTransforms(); } diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h index b2ad45f749..b9e762e175 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h @@ -23,7 +23,6 @@ email: projectileman@yahoo.com http://gimpact.sf.net */ - #ifndef BT_GENERIC_6DOF_CONSTRAINT_H #define BT_GENERIC_6DOF_CONSTRAINT_H @@ -33,96 +32,91 @@ http://gimpact.sf.net class btRigidBody; - - #ifdef BT_USE_DOUBLE_PRECISION -#define btGeneric6DofConstraintData2 btGeneric6DofConstraintDoubleData2 -#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintDoubleData2" +#define btGeneric6DofConstraintData2 btGeneric6DofConstraintDoubleData2 +#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintDoubleData2" #else -#define btGeneric6DofConstraintData2 btGeneric6DofConstraintData -#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintData" -#endif //BT_USE_DOUBLE_PRECISION - +#define btGeneric6DofConstraintData2 btGeneric6DofConstraintData +#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintData" +#endif //BT_USE_DOUBLE_PRECISION //! Rotation Limit structure for generic joints class btRotationalLimitMotor { public: - //! limit_parameters - //!@{ - btScalar m_loLimit;//!< joint limit - btScalar m_hiLimit;//!< joint limit - btScalar m_targetVelocity;//!< target motor velocity - btScalar m_maxMotorForce;//!< max force on motor - btScalar m_maxLimitForce;//!< max force on limit - btScalar m_damping;//!< Damping. - btScalar m_limitSoftness;//! Relaxation factor - btScalar m_normalCFM;//!< Constraint force mixing factor - btScalar m_stopERP;//!< Error tolerance factor when joint is at limit - btScalar m_stopCFM;//!< Constraint force mixing factor when joint is at limit - btScalar m_bounce;//!< restitution factor - bool m_enableMotor; - - //!@} - - //! temp_variables - //!@{ - btScalar m_currentLimitError;//! How much is violated this limit - btScalar m_currentPosition; //! current value of angle - int m_currentLimit;//!< 0=free, 1=at lo limit, 2=at hi limit - btScalar m_accumulatedImpulse; - //!@} - - btRotationalLimitMotor() - { - m_accumulatedImpulse = 0.f; - m_targetVelocity = 0; - m_maxMotorForce = 6.0f; - m_maxLimitForce = 300.0f; - m_loLimit = 1.0f; - m_hiLimit = -1.0f; + //! limit_parameters + //!@{ + btScalar m_loLimit; //!< joint limit + btScalar m_hiLimit; //!< joint limit + btScalar m_targetVelocity; //!< target motor velocity + btScalar m_maxMotorForce; //!< max force on motor + btScalar m_maxLimitForce; //!< max force on limit + btScalar m_damping; //!< Damping. + btScalar m_limitSoftness; //! Relaxation factor + btScalar m_normalCFM; //!< Constraint force mixing factor + btScalar m_stopERP; //!< Error tolerance factor when joint is at limit + btScalar m_stopCFM; //!< Constraint force mixing factor when joint is at limit + btScalar m_bounce; //!< restitution factor + bool m_enableMotor; + + //!@} + + //! temp_variables + //!@{ + btScalar m_currentLimitError; //! How much is violated this limit + btScalar m_currentPosition; //! current value of angle + int m_currentLimit; //!< 0=free, 1=at lo limit, 2=at hi limit + btScalar m_accumulatedImpulse; + //!@} + + btRotationalLimitMotor() + { + m_accumulatedImpulse = 0.f; + m_targetVelocity = 0; + m_maxMotorForce = 6.0f; + m_maxLimitForce = 300.0f; + m_loLimit = 1.0f; + m_hiLimit = -1.0f; m_normalCFM = 0.f; m_stopERP = 0.2f; m_stopCFM = 0.f; - m_bounce = 0.0f; - m_damping = 1.0f; - m_limitSoftness = 0.5f; - m_currentLimit = 0; - m_currentLimitError = 0; - m_enableMotor = false; - } - - btRotationalLimitMotor(const btRotationalLimitMotor & limot) - { - m_targetVelocity = limot.m_targetVelocity; - m_maxMotorForce = limot.m_maxMotorForce; - m_limitSoftness = limot.m_limitSoftness; - m_loLimit = limot.m_loLimit; - m_hiLimit = limot.m_hiLimit; + m_bounce = 0.0f; + m_damping = 1.0f; + m_limitSoftness = 0.5f; + m_currentLimit = 0; + m_currentLimitError = 0; + m_enableMotor = false; + } + + btRotationalLimitMotor(const btRotationalLimitMotor& limot) + { + m_targetVelocity = limot.m_targetVelocity; + m_maxMotorForce = limot.m_maxMotorForce; + m_limitSoftness = limot.m_limitSoftness; + m_loLimit = limot.m_loLimit; + m_hiLimit = limot.m_hiLimit; m_normalCFM = limot.m_normalCFM; m_stopERP = limot.m_stopERP; - m_stopCFM = limot.m_stopCFM; - m_bounce = limot.m_bounce; - m_currentLimit = limot.m_currentLimit; - m_currentLimitError = limot.m_currentLimitError; - m_enableMotor = limot.m_enableMotor; - } - - + m_stopCFM = limot.m_stopCFM; + m_bounce = limot.m_bounce; + m_currentLimit = limot.m_currentLimit; + m_currentLimitError = limot.m_currentLimitError; + m_enableMotor = limot.m_enableMotor; + } //! Is limited - bool isLimited() const - { - if(m_loLimit > m_hiLimit) return false; - return true; - } + bool isLimited() const + { + if (m_loLimit > m_hiLimit) return false; + return true; + } //! Need apply correction - bool needApplyTorques() const - { - if(m_currentLimit == 0 && m_enableMotor == false) return false; - return true; - } + bool needApplyTorques() const + { + if (m_currentLimit == 0 && m_enableMotor == false) return false; + return true; + } //! calculates error /*! @@ -131,104 +125,98 @@ public: int testLimitValue(btScalar test_value); //! apply the correction impulses for two bodies - btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btRigidBody * body1); - + btScalar solveAngularLimits(btScalar timeStep, btVector3& axis, btScalar jacDiagABInv, btRigidBody* body0, btRigidBody* body1); }; - - class btTranslationalLimitMotor { public: - btVector3 m_lowerLimit;//!< the constraint lower limits - btVector3 m_upperLimit;//!< the constraint upper limits - btVector3 m_accumulatedImpulse; - //! Linear_Limit_parameters - //!@{ - btScalar m_limitSoftness;//!< Softness for linear limit - btScalar m_damping;//!< Damping for linear limit - btScalar m_restitution;//! Bounce parameter for linear limit - btVector3 m_normalCFM;//!< Constraint force mixing factor - btVector3 m_stopERP;//!< Error tolerance factor when joint is at limit - btVector3 m_stopCFM;//!< Constraint force mixing factor when joint is at limit - //!@} - bool m_enableMotor[3]; - btVector3 m_targetVelocity;//!< target motor velocity - btVector3 m_maxMotorForce;//!< max force on motor - btVector3 m_currentLimitError;//! How much is violated this limit - btVector3 m_currentLinearDiff;//! Current relative offset of constraint frames - int m_currentLimit[3];//!< 0=free, 1=at lower limit, 2=at upper limit - - btTranslationalLimitMotor() - { - m_lowerLimit.setValue(0.f,0.f,0.f); - m_upperLimit.setValue(0.f,0.f,0.f); - m_accumulatedImpulse.setValue(0.f,0.f,0.f); + btVector3 m_lowerLimit; //!< the constraint lower limits + btVector3 m_upperLimit; //!< the constraint upper limits + btVector3 m_accumulatedImpulse; + //! Linear_Limit_parameters + //!@{ + btScalar m_limitSoftness; //!< Softness for linear limit + btScalar m_damping; //!< Damping for linear limit + btScalar m_restitution; //! Bounce parameter for linear limit + btVector3 m_normalCFM; //!< Constraint force mixing factor + btVector3 m_stopERP; //!< Error tolerance factor when joint is at limit + btVector3 m_stopCFM; //!< Constraint force mixing factor when joint is at limit + //!@} + bool m_enableMotor[3]; + btVector3 m_targetVelocity; //!< target motor velocity + btVector3 m_maxMotorForce; //!< max force on motor + btVector3 m_currentLimitError; //! How much is violated this limit + btVector3 m_currentLinearDiff; //! Current relative offset of constraint frames + int m_currentLimit[3]; //!< 0=free, 1=at lower limit, 2=at upper limit + + btTranslationalLimitMotor() + { + m_lowerLimit.setValue(0.f, 0.f, 0.f); + m_upperLimit.setValue(0.f, 0.f, 0.f); + m_accumulatedImpulse.setValue(0.f, 0.f, 0.f); m_normalCFM.setValue(0.f, 0.f, 0.f); m_stopERP.setValue(0.2f, 0.2f, 0.2f); m_stopCFM.setValue(0.f, 0.f, 0.f); - m_limitSoftness = 0.7f; - m_damping = btScalar(1.0f); - m_restitution = btScalar(0.5f); - for(int i=0; i < 3; i++) + m_limitSoftness = 0.7f; + m_damping = btScalar(1.0f); + m_restitution = btScalar(0.5f); + for (int i = 0; i < 3; i++) { m_enableMotor[i] = false; m_targetVelocity[i] = btScalar(0.f); m_maxMotorForce[i] = btScalar(0.f); } - } + } - btTranslationalLimitMotor(const btTranslationalLimitMotor & other ) - { - m_lowerLimit = other.m_lowerLimit; - m_upperLimit = other.m_upperLimit; - m_accumulatedImpulse = other.m_accumulatedImpulse; + btTranslationalLimitMotor(const btTranslationalLimitMotor& other) + { + m_lowerLimit = other.m_lowerLimit; + m_upperLimit = other.m_upperLimit; + m_accumulatedImpulse = other.m_accumulatedImpulse; - m_limitSoftness = other.m_limitSoftness ; - m_damping = other.m_damping; - m_restitution = other.m_restitution; + m_limitSoftness = other.m_limitSoftness; + m_damping = other.m_damping; + m_restitution = other.m_restitution; m_normalCFM = other.m_normalCFM; m_stopERP = other.m_stopERP; m_stopCFM = other.m_stopCFM; - for(int i=0; i < 3; i++) + for (int i = 0; i < 3; i++) { m_enableMotor[i] = other.m_enableMotor[i]; m_targetVelocity[i] = other.m_targetVelocity[i]; m_maxMotorForce[i] = other.m_maxMotorForce[i]; } - } + } - //! Test limit + //! Test limit /*! - free means upper < lower, - locked means upper == lower - limited means upper > lower - limitIndex: first 3 are linear, next 3 are angular */ - inline bool isLimited(int limitIndex) const - { - return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); - } - inline bool needApplyForce(int limitIndex) const - { - if(m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false; - return true; - } + inline bool isLimited(int limitIndex) const + { + return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); + } + inline bool needApplyForce(int limitIndex) const + { + if (m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false; + return true; + } int testLimitValue(int limitIndex, btScalar test_value); - - btScalar solveLinearAxis( - btScalar timeStep, - btScalar jacDiagABInv, - btRigidBody& body1,const btVector3 &pointInA, - btRigidBody& body2,const btVector3 &pointInB, - int limit_index, - const btVector3 & axis_normal_on_a, - const btVector3 & anchorPos); - - + btScalar solveLinearAxis( + btScalar timeStep, + btScalar jacDiagABInv, + btRigidBody& body1, const btVector3& pointInA, + btRigidBody& body2, const btVector3& pointInB, + int limit_index, + const btVector3& axis_normal_on_a, + const btVector3& anchorPos); }; enum bt6DofFlags @@ -237,8 +225,7 @@ enum bt6DofFlags BT_6DOF_FLAGS_CFM_STOP = 2, BT_6DOF_FLAGS_ERP_STOP = 4 }; -#define BT_6DOF_FLAGS_AXIS_SHIFT 3 // bits per axis - +#define BT_6DOF_FLAGS_AXIS_SHIFT 3 // bits per axis /// btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space /*! @@ -276,254 +263,245 @@ This brings support for limit parameters and motors. </li> </ul> */ -ATTRIBUTE_ALIGNED16(class) btGeneric6DofConstraint : public btTypedConstraint +ATTRIBUTE_ALIGNED16(class) +btGeneric6DofConstraint : public btTypedConstraint { protected: - //! relative_frames - //!@{ - btTransform m_frameInA;//!< the constraint space w.r.t body A - btTransform m_frameInB;//!< the constraint space w.r.t body B - //!@} + //!@{ + btTransform m_frameInA; //!< the constraint space w.r.t body A + btTransform m_frameInB; //!< the constraint space w.r.t body B + //!@} - //! Jacobians - //!@{ - btJacobianEntry m_jacLinear[3];//!< 3 orthogonal linear constraints - btJacobianEntry m_jacAng[3];//!< 3 orthogonal angular constraints - //!@} + //! Jacobians + //!@{ + btJacobianEntry m_jacLinear[3]; //!< 3 orthogonal linear constraints + btJacobianEntry m_jacAng[3]; //!< 3 orthogonal angular constraints + //!@} //! Linear_Limit_parameters - //!@{ - btTranslationalLimitMotor m_linearLimits; - //!@} - - - //! hinge_parameters - //!@{ - btRotationalLimitMotor m_angularLimits[3]; + //!@{ + btTranslationalLimitMotor m_linearLimits; //!@} + //! hinge_parameters + //!@{ + btRotationalLimitMotor m_angularLimits[3]; + //!@} protected: - //! temporal variables - //!@{ - btScalar m_timeStep; - btTransform m_calculatedTransformA; - btTransform m_calculatedTransformB; - btVector3 m_calculatedAxisAngleDiff; - btVector3 m_calculatedAxis[3]; - btVector3 m_calculatedLinearDiff; - btScalar m_factA; - btScalar m_factB; - bool m_hasStaticBody; - - btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes + //! temporal variables + //!@{ + btScalar m_timeStep; + btTransform m_calculatedTransformA; + btTransform m_calculatedTransformB; + btVector3 m_calculatedAxisAngleDiff; + btVector3 m_calculatedAxis[3]; + btVector3 m_calculatedLinearDiff; + btScalar m_factA; + btScalar m_factB; + bool m_hasStaticBody; - bool m_useLinearReferenceFrameA; - bool m_useOffsetForConstraintFrame; - - int m_flags; + btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes - //!@} + bool m_useLinearReferenceFrameA; + bool m_useOffsetForConstraintFrame; - btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other) - { - btAssert(0); - (void) other; - return *this; - } + int m_flags; + //!@} - int setAngularLimits(btConstraintInfo2 *info, int row_offset,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB); + btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other) + { + btAssert(0); + (void)other; + return *this; + } - int setLinearLimits(btConstraintInfo2 *info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB); + int setAngularLimits(btConstraintInfo2 * info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB); - void buildLinearJacobian( - btJacobianEntry & jacLinear,const btVector3 & normalWorld, - const btVector3 & pivotAInW,const btVector3 & pivotBInW); + int setLinearLimits(btConstraintInfo2 * info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB); - void buildAngularJacobian(btJacobianEntry & jacAngular,const btVector3 & jointAxisW); + void buildLinearJacobian( + btJacobianEntry & jacLinear, const btVector3& normalWorld, + const btVector3& pivotAInW, const btVector3& pivotBInW); + + void buildAngularJacobian(btJacobianEntry & jacAngular, const btVector3& jointAxisW); // tests linear limits void calculateLinearInfo(); //! calcs the euler angles between the two bodies. - void calculateAngleInfo(); - - + void calculateAngleInfo(); public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - + ///for backwards compatibility during the transition to 'getInfo/getInfo2' - bool m_useSolveConstraintObsolete; + bool m_useSolveConstraintObsolete; + + btGeneric6DofConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA); + btGeneric6DofConstraint(btRigidBody & rbB, const btTransform& frameInB, bool useLinearReferenceFrameB); - btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); - btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB); - //! Calcs global transform of the offsets /*! Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies. \sa btGeneric6DofConstraint.getCalculatedTransformA , btGeneric6DofConstraint.getCalculatedTransformB, btGeneric6DofConstraint.calculateAngleInfo */ - void calculateTransforms(const btTransform& transA,const btTransform& transB); + void calculateTransforms(const btTransform& transA, const btTransform& transB); void calculateTransforms(); //! Gets the global transform of the offset for body A - /*! + /*! \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. */ - const btTransform & getCalculatedTransformA() const - { - return m_calculatedTransformA; - } + const btTransform& getCalculatedTransformA() const + { + return m_calculatedTransformA; + } - //! Gets the global transform of the offset for body B - /*! + //! Gets the global transform of the offset for body B + /*! \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. */ - const btTransform & getCalculatedTransformB() const - { - return m_calculatedTransformB; - } - - const btTransform & getFrameOffsetA() const - { - return m_frameInA; - } - - const btTransform & getFrameOffsetB() const - { - return m_frameInB; - } + const btTransform& getCalculatedTransformB() const + { + return m_calculatedTransformB; + } + const btTransform& getFrameOffsetA() const + { + return m_frameInA; + } - btTransform & getFrameOffsetA() - { - return m_frameInA; - } + const btTransform& getFrameOffsetB() const + { + return m_frameInB; + } - btTransform & getFrameOffsetB() - { - return m_frameInB; - } + btTransform& getFrameOffsetA() + { + return m_frameInA; + } + btTransform& getFrameOffsetB() + { + return m_frameInB; + } //! performs Jacobian calculation, and also calculates angle differences and axis - virtual void buildJacobian(); - - virtual void getInfo1 (btConstraintInfo1* info); + virtual void buildJacobian(); - void getInfo1NonVirtual (btConstraintInfo1* info); + virtual void getInfo1(btConstraintInfo1 * info); - virtual void getInfo2 (btConstraintInfo2* info); + void getInfo1NonVirtual(btConstraintInfo1 * info); - void getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB); + virtual void getInfo2(btConstraintInfo2 * info); + void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB); - void updateRHS(btScalar timeStep); + void updateRHS(btScalar timeStep); //! Get the rotation axis in global coordinates /*! \pre btGeneric6DofConstraint.buildJacobian must be called previously. */ - btVector3 getAxis(int axis_index) const; + btVector3 getAxis(int axis_index) const; - //! Get the relative Euler angle - /*! + //! Get the relative Euler angle + /*! \pre btGeneric6DofConstraint::calculateTransforms() must be called previously. */ - btScalar getAngle(int axis_index) const; + btScalar getAngle(int axis_index) const; //! Get the relative position of the constraint pivot - /*! + /*! \pre btGeneric6DofConstraint::calculateTransforms() must be called previously. */ btScalar getRelativePivotPosition(int axis_index) const; - void setFrames(const btTransform & frameA, const btTransform & frameB); + void setFrames(const btTransform& frameA, const btTransform& frameB); //! Test angular limit. /*! Calculates angular correction and returns true if limit needs to be corrected. \pre btGeneric6DofConstraint::calculateTransforms() must be called previously. */ - bool testAngularLimitMotor(int axis_index); + bool testAngularLimitMotor(int axis_index); - void setLinearLowerLimit(const btVector3& linearLower) - { - m_linearLimits.m_lowerLimit = linearLower; - } + void setLinearLowerLimit(const btVector3& linearLower) + { + m_linearLimits.m_lowerLimit = linearLower; + } - void getLinearLowerLimit(btVector3& linearLower) const + void getLinearLowerLimit(btVector3 & linearLower) const { linearLower = m_linearLimits.m_lowerLimit; } - void setLinearUpperLimit(const btVector3& linearUpper) + void setLinearUpperLimit(const btVector3& linearUpper) { m_linearLimits.m_upperLimit = linearUpper; } - void getLinearUpperLimit(btVector3& linearUpper) const + void getLinearUpperLimit(btVector3 & linearUpper) const { linearUpper = m_linearLimits.m_upperLimit; } - void setAngularLowerLimit(const btVector3& angularLower) - { - for(int i = 0; i < 3; i++) + void setAngularLowerLimit(const btVector3& angularLower) + { + for (int i = 0; i < 3; i++) m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]); - } + } - void getAngularLowerLimit(btVector3& angularLower) const + void getAngularLowerLimit(btVector3 & angularLower) const { - for(int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) angularLower[i] = m_angularLimits[i].m_loLimit; } - void setAngularUpperLimit(const btVector3& angularUpper) - { - for(int i = 0; i < 3; i++) + void setAngularUpperLimit(const btVector3& angularUpper) + { + for (int i = 0; i < 3; i++) m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]); - } + } - void getAngularUpperLimit(btVector3& angularUpper) const + void getAngularUpperLimit(btVector3 & angularUpper) const { - for(int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) angularUpper[i] = m_angularLimits[i].m_hiLimit; } //! Retrieves the angular limit informacion - btRotationalLimitMotor * getRotationalLimitMotor(int index) - { - return &m_angularLimits[index]; - } - - //! Retrieves the limit informacion - btTranslationalLimitMotor * getTranslationalLimitMotor() - { - return &m_linearLimits; - } - - //first 3 are linear, next 3 are angular - void setLimit(int axis, btScalar lo, btScalar hi) - { - if(axis<3) - { - m_linearLimits.m_lowerLimit[axis] = lo; - m_linearLimits.m_upperLimit[axis] = hi; - } - else - { + btRotationalLimitMotor* getRotationalLimitMotor(int index) + { + return &m_angularLimits[index]; + } + + //! Retrieves the limit informacion + btTranslationalLimitMotor* getTranslationalLimitMotor() + { + return &m_linearLimits; + } + + //first 3 are linear, next 3 are angular + void setLimit(int axis, btScalar lo, btScalar hi) + { + if (axis < 3) + { + m_linearLimits.m_lowerLimit[axis] = lo; + m_linearLimits.m_upperLimit[axis] = hi; + } + else + { lo = btNormalizeAngle(lo); hi = btNormalizeAngle(hi); - m_angularLimits[axis-3].m_loLimit = lo; - m_angularLimits[axis-3].m_hiLimit = hi; - } - } + m_angularLimits[axis - 3].m_loLimit = lo; + m_angularLimits[axis - 3].m_hiLimit = hi; + } + } //! Test limit /*! @@ -532,116 +510,106 @@ public: - limited means upper > lower - limitIndex: first 3 are linear, next 3 are angular */ - bool isLimited(int limitIndex) const - { - if(limitIndex<3) - { + bool isLimited(int limitIndex) const + { + if (limitIndex < 3) + { return m_linearLimits.isLimited(limitIndex); + } + return m_angularLimits[limitIndex - 3].isLimited(); + } - } - return m_angularLimits[limitIndex-3].isLimited(); - } - - virtual void calcAnchorPos(void); // overridable + virtual void calcAnchorPos(void); // overridable - int get_limit_motor_info2( btRotationalLimitMotor * limot, - const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB, - btConstraintInfo2 *info, int row, btVector3& ax1, int rotational, int rotAllowed = false); + int get_limit_motor_info2(btRotationalLimitMotor * limot, + const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB, + btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed = false); // access for UseFrameOffset bool getUseFrameOffset() const { return m_useOffsetForConstraintFrame; } void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; } - + bool getUseLinearReferenceFrameA() const { return m_useLinearReferenceFrameA; } void setUseLinearReferenceFrameA(bool linearReferenceFrameA) { m_useLinearReferenceFrameA = linearReferenceFrameA; } - ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). ///If no axis is provided, it uses the default axis for this constraint. - virtual void setParam(int num, btScalar value, int axis = -1); + virtual void setParam(int num, btScalar value, int axis = -1); ///return the local value of parameter - virtual btScalar getParam(int num, int axis = -1) const; + virtual btScalar getParam(int num, int axis = -1) const; - void setAxis( const btVector3& axis1, const btVector3& axis2); + void setAxis(const btVector3& axis1, const btVector3& axis2); - virtual int getFlags() const - { - return m_flags; + virtual int getFlags() const + { + return m_flags; } - virtual int calculateSerializeBufferSize() const; + virtual int calculateSerializeBufferSize() const; ///fills the dataBuffer and returns the struct name (and 0 on failure) - virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; - - + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; }; - struct btGeneric6DofConstraintData { - btTypedConstraintData m_typeConstraintData; - btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis. btTransformFloatData m_rbBFrame; - - btVector3FloatData m_linearUpperLimit; - btVector3FloatData m_linearLowerLimit; - - btVector3FloatData m_angularUpperLimit; - btVector3FloatData m_angularLowerLimit; - - int m_useLinearReferenceFrameA; + + btVector3FloatData m_linearUpperLimit; + btVector3FloatData m_linearLowerLimit; + + btVector3FloatData m_angularUpperLimit; + btVector3FloatData m_angularLowerLimit; + + int m_useLinearReferenceFrameA; int m_useOffsetForConstraintFrame; }; struct btGeneric6DofConstraintDoubleData2 { - btTypedConstraintDoubleData m_typeConstraintData; - btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTypedConstraintDoubleData m_typeConstraintData; + btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. btTransformDoubleData m_rbBFrame; - - btVector3DoubleData m_linearUpperLimit; - btVector3DoubleData m_linearLowerLimit; - - btVector3DoubleData m_angularUpperLimit; - btVector3DoubleData m_angularLowerLimit; - - int m_useLinearReferenceFrameA; + + btVector3DoubleData m_linearUpperLimit; + btVector3DoubleData m_linearLowerLimit; + + btVector3DoubleData m_angularUpperLimit; + btVector3DoubleData m_angularLowerLimit; + + int m_useLinearReferenceFrameA; int m_useOffsetForConstraintFrame; }; -SIMD_FORCE_INLINE int btGeneric6DofConstraint::calculateSerializeBufferSize() const +SIMD_FORCE_INLINE int btGeneric6DofConstraint::calculateSerializeBufferSize() const { return sizeof(btGeneric6DofConstraintData2); } - ///fills the dataBuffer and returns the struct name (and 0 on failure) -SIMD_FORCE_INLINE const char* btGeneric6DofConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btGeneric6DofConstraint::serialize(void* dataBuffer, btSerializer* serializer) const { - btGeneric6DofConstraintData2* dof = (btGeneric6DofConstraintData2*)dataBuffer; - btTypedConstraint::serialize(&dof->m_typeConstraintData,serializer); + btTypedConstraint::serialize(&dof->m_typeConstraintData, serializer); m_frameInA.serialize(dof->m_rbAFrame); m_frameInB.serialize(dof->m_rbBFrame); - int i; - for (i=0;i<3;i++) + for (i = 0; i < 3; i++) { - dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit; - dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit; + dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit; + dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit; dof->m_linearLowerLimit.m_floats[i] = m_linearLimits.m_lowerLimit[i]; dof->m_linearUpperLimit.m_floats[i] = m_linearLimits.m_upperLimit[i]; } - - dof->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA? 1 : 0; + + dof->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA ? 1 : 0; dof->m_useOffsetForConstraintFrame = m_useOffsetForConstraintFrame ? 1 : 0; return btGeneric6DofConstraintDataName; } - - - - -#endif //BT_GENERIC_6DOF_CONSTRAINT_H +#endif //BT_GENERIC_6DOF_CONSTRAINT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp index 540dcd18f7..49c8d9bbf7 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp @@ -37,67 +37,54 @@ email: projectileman@yahoo.com http://gimpact.sf.net */ - - #include "btGeneric6DofSpring2Constraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" #include <new> - - btGeneric6DofSpring2Constraint::btGeneric6DofSpring2Constraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, RotateOrder rotOrder) - : btTypedConstraint(D6_SPRING_2_CONSTRAINT_TYPE, rbA, rbB) - , m_frameInA(frameInA) - , m_frameInB(frameInB) - , m_rotateOrder(rotOrder) - , m_flags(0) + : btTypedConstraint(D6_SPRING_2_CONSTRAINT_TYPE, rbA, rbB), m_frameInA(frameInA), m_frameInB(frameInB), m_rotateOrder(rotOrder), m_flags(0) { calculateTransforms(); } - btGeneric6DofSpring2Constraint::btGeneric6DofSpring2Constraint(btRigidBody& rbB, const btTransform& frameInB, RotateOrder rotOrder) - : btTypedConstraint(D6_SPRING_2_CONSTRAINT_TYPE, getFixedBody(), rbB) - , m_frameInB(frameInB) - , m_rotateOrder(rotOrder) - , m_flags(0) + : btTypedConstraint(D6_SPRING_2_CONSTRAINT_TYPE, getFixedBody(), rbB), m_frameInB(frameInB), m_rotateOrder(rotOrder), m_flags(0) { ///not providing rigidbody A means implicitly using worldspace for body A m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB; calculateTransforms(); } - btScalar btGeneric6DofSpring2Constraint::btGetMatrixElem(const btMatrix3x3& mat, int index) { - int i = index%3; - int j = index/3; + int i = index % 3; + int j = index / 3; return mat[i][j]; } // MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html -bool btGeneric6DofSpring2Constraint::matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) +bool btGeneric6DofSpring2Constraint::matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz) { // rot = cy*cz -cy*sz sy // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy - btScalar fi = btGetMatrixElem(mat,2); + btScalar fi = btGetMatrixElem(mat, 2); if (fi < btScalar(1.0f)) { if (fi > btScalar(-1.0f)) { - xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8)); - xyz[1] = btAsin(btGetMatrixElem(mat,2)); - xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); + xyz[0] = btAtan2(-btGetMatrixElem(mat, 5), btGetMatrixElem(mat, 8)); + xyz[1] = btAsin(btGetMatrixElem(mat, 2)); + xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0)); return true; } else { // WARNING. Not unique. XA - ZA = -atan2(r10,r11) - xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[0] = -btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4)); xyz[1] = -SIMD_HALF_PI; xyz[2] = btScalar(0.0); return false; @@ -106,32 +93,32 @@ bool btGeneric6DofSpring2Constraint::matrixToEulerXYZ(const btMatrix3x3& mat,btV else { // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) - xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[0] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4)); xyz[1] = SIMD_HALF_PI; xyz[2] = 0.0; } return false; } -bool btGeneric6DofSpring2Constraint::matrixToEulerXZY(const btMatrix3x3& mat,btVector3& xyz) +bool btGeneric6DofSpring2Constraint::matrixToEulerXZY(const btMatrix3x3& mat, btVector3& xyz) { // rot = cy*cz -sz sy*cz // cy*cx*sz+sx*sy cx*cz sy*cx*sz-cy*sx // cy*sx*sz-cx*sy sx*cz sy*sx*sz+cx*cy - btScalar fi = btGetMatrixElem(mat,1); + btScalar fi = btGetMatrixElem(mat, 1); if (fi < btScalar(1.0f)) { if (fi > btScalar(-1.0f)) { - xyz[0] = btAtan2(btGetMatrixElem(mat,7),btGetMatrixElem(mat,4)); - xyz[1] = btAtan2(btGetMatrixElem(mat,2),btGetMatrixElem(mat,0)); - xyz[2] = btAsin(-btGetMatrixElem(mat,1)); + xyz[0] = btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 4)); + xyz[1] = btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 0)); + xyz[2] = btAsin(-btGetMatrixElem(mat, 1)); return true; } else { - xyz[0] = -btAtan2(-btGetMatrixElem(mat,6),btGetMatrixElem(mat,8)); + xyz[0] = -btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 8)); xyz[1] = btScalar(0.0); xyz[2] = SIMD_HALF_PI; return false; @@ -139,33 +126,33 @@ bool btGeneric6DofSpring2Constraint::matrixToEulerXZY(const btMatrix3x3& mat,btV } else { - xyz[0] = btAtan2(-btGetMatrixElem(mat,6),btGetMatrixElem(mat,8)); + xyz[0] = btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 8)); xyz[1] = 0.0; xyz[2] = -SIMD_HALF_PI; } return false; } -bool btGeneric6DofSpring2Constraint::matrixToEulerYXZ(const btMatrix3x3& mat,btVector3& xyz) +bool btGeneric6DofSpring2Constraint::matrixToEulerYXZ(const btMatrix3x3& mat, btVector3& xyz) { // rot = cy*cz+sy*sx*sz cz*sy*sx-cy*sz cx*sy // cx*sz cx*cz -sx // cy*sx*sz-cz*sy sy*sz+cy*cz*sx cy*cx - btScalar fi = btGetMatrixElem(mat,5); + btScalar fi = btGetMatrixElem(mat, 5); if (fi < btScalar(1.0f)) { if (fi > btScalar(-1.0f)) { - xyz[0] = btAsin(-btGetMatrixElem(mat,5)); - xyz[1] = btAtan2(btGetMatrixElem(mat,2),btGetMatrixElem(mat,8)); - xyz[2] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[0] = btAsin(-btGetMatrixElem(mat, 5)); + xyz[1] = btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 8)); + xyz[2] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4)); return true; } else { xyz[0] = SIMD_HALF_PI; - xyz[1] = -btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); + xyz[1] = -btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0)); xyz[2] = btScalar(0.0); return false; } @@ -173,32 +160,32 @@ bool btGeneric6DofSpring2Constraint::matrixToEulerYXZ(const btMatrix3x3& mat,btV else { xyz[0] = -SIMD_HALF_PI; - xyz[1] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); + xyz[1] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0)); xyz[2] = 0.0; } return false; } -bool btGeneric6DofSpring2Constraint::matrixToEulerYZX(const btMatrix3x3& mat,btVector3& xyz) +bool btGeneric6DofSpring2Constraint::matrixToEulerYZX(const btMatrix3x3& mat, btVector3& xyz) { // rot = cy*cz sy*sx-cy*cx*sz cx*sy+cy*sz*sx // sz cz*cx -cz*sx // -cz*sy cy*sx+cx*sy*sz cy*cx-sy*sz*sx - btScalar fi = btGetMatrixElem(mat,3); + btScalar fi = btGetMatrixElem(mat, 3); if (fi < btScalar(1.0f)) { if (fi > btScalar(-1.0f)) { - xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,4)); - xyz[1] = btAtan2(-btGetMatrixElem(mat,6),btGetMatrixElem(mat,0)); - xyz[2] = btAsin(btGetMatrixElem(mat,3)); + xyz[0] = btAtan2(-btGetMatrixElem(mat, 5), btGetMatrixElem(mat, 4)); + xyz[1] = btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 0)); + xyz[2] = btAsin(btGetMatrixElem(mat, 3)); return true; } else { xyz[0] = btScalar(0.0); - xyz[1] = -btAtan2(btGetMatrixElem(mat,7),btGetMatrixElem(mat,8)); + xyz[1] = -btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 8)); xyz[2] = -SIMD_HALF_PI; return false; } @@ -206,33 +193,33 @@ bool btGeneric6DofSpring2Constraint::matrixToEulerYZX(const btMatrix3x3& mat,btV else { xyz[0] = btScalar(0.0); - xyz[1] = btAtan2(btGetMatrixElem(mat,7),btGetMatrixElem(mat,8)); + xyz[1] = btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 8)); xyz[2] = SIMD_HALF_PI; } return false; } -bool btGeneric6DofSpring2Constraint::matrixToEulerZXY(const btMatrix3x3& mat,btVector3& xyz) +bool btGeneric6DofSpring2Constraint::matrixToEulerZXY(const btMatrix3x3& mat, btVector3& xyz) { // rot = cz*cy-sz*sx*sy -cx*sz cz*sy+cy*sz*sx // cy*sz+cz*sx*sy cz*cx sz*sy-cz*xy*sx // -cx*sy sx cx*cy - btScalar fi = btGetMatrixElem(mat,7); + btScalar fi = btGetMatrixElem(mat, 7); if (fi < btScalar(1.0f)) { if (fi > btScalar(-1.0f)) { - xyz[0] = btAsin(btGetMatrixElem(mat,7)); - xyz[1] = btAtan2(-btGetMatrixElem(mat,6),btGetMatrixElem(mat,8)); - xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,4)); + xyz[0] = btAsin(btGetMatrixElem(mat, 7)); + xyz[1] = btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 8)); + xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 4)); return true; } else { xyz[0] = -SIMD_HALF_PI; xyz[1] = btScalar(0.0); - xyz[2] = -btAtan2(btGetMatrixElem(mat,2),btGetMatrixElem(mat,0)); + xyz[2] = -btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 0)); return false; } } @@ -240,32 +227,32 @@ bool btGeneric6DofSpring2Constraint::matrixToEulerZXY(const btMatrix3x3& mat,btV { xyz[0] = SIMD_HALF_PI; xyz[1] = btScalar(0.0); - xyz[2] = btAtan2(btGetMatrixElem(mat,2),btGetMatrixElem(mat,0)); + xyz[2] = btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 0)); } return false; } -bool btGeneric6DofSpring2Constraint::matrixToEulerZYX(const btMatrix3x3& mat,btVector3& xyz) +bool btGeneric6DofSpring2Constraint::matrixToEulerZYX(const btMatrix3x3& mat, btVector3& xyz) { // rot = cz*cy cz*sy*sx-cx*sz sz*sx+cz*cx*sy // cy*sz cz*cx+sz*sy*sx cx*sz*sy-cz*sx // -sy cy*sx cy*cx - btScalar fi = btGetMatrixElem(mat,6); + btScalar fi = btGetMatrixElem(mat, 6); if (fi < btScalar(1.0f)) { if (fi > btScalar(-1.0f)) { - xyz[0] = btAtan2(btGetMatrixElem(mat,7), btGetMatrixElem(mat,8)); - xyz[1] = btAsin(-btGetMatrixElem(mat,6)); - xyz[2] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,0)); + xyz[0] = btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 8)); + xyz[1] = btAsin(-btGetMatrixElem(mat, 6)); + xyz[2] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 0)); return true; } else { xyz[0] = btScalar(0.0); xyz[1] = SIMD_HALF_PI; - xyz[2] = -btAtan2(btGetMatrixElem(mat,1),btGetMatrixElem(mat,2)); + xyz[2] = -btAtan2(btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 2)); return false; } } @@ -273,23 +260,36 @@ bool btGeneric6DofSpring2Constraint::matrixToEulerZYX(const btMatrix3x3& mat,btV { xyz[0] = btScalar(0.0); xyz[1] = -SIMD_HALF_PI; - xyz[2] = btAtan2(-btGetMatrixElem(mat,1),-btGetMatrixElem(mat,2)); + xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), -btGetMatrixElem(mat, 2)); } return false; } void btGeneric6DofSpring2Constraint::calculateAngleInfo() { - btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis(); + btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse() * m_calculatedTransformB.getBasis(); switch (m_rotateOrder) { - case RO_XYZ : matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff); break; - case RO_XZY : matrixToEulerXZY(relative_frame,m_calculatedAxisAngleDiff); break; - case RO_YXZ : matrixToEulerYXZ(relative_frame,m_calculatedAxisAngleDiff); break; - case RO_YZX : matrixToEulerYZX(relative_frame,m_calculatedAxisAngleDiff); break; - case RO_ZXY : matrixToEulerZXY(relative_frame,m_calculatedAxisAngleDiff); break; - case RO_ZYX : matrixToEulerZYX(relative_frame,m_calculatedAxisAngleDiff); break; - default : btAssert(false); + case RO_XYZ: + matrixToEulerXYZ(relative_frame, m_calculatedAxisAngleDiff); + break; + case RO_XZY: + matrixToEulerXZY(relative_frame, m_calculatedAxisAngleDiff); + break; + case RO_YXZ: + matrixToEulerYXZ(relative_frame, m_calculatedAxisAngleDiff); + break; + case RO_YZX: + matrixToEulerYZX(relative_frame, m_calculatedAxisAngleDiff); + break; + case RO_ZXY: + matrixToEulerZXY(relative_frame, m_calculatedAxisAngleDiff); + break; + case RO_ZYX: + matrixToEulerZYX(relative_frame, m_calculatedAxisAngleDiff); + break; + default: + btAssert(false); } // in euler angle mode we do not actually constrain the angular velocity // along the axes axis[0] and axis[2] (although we do use axis[1]) : @@ -307,14 +307,14 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo() // to the components of w and set that to 0. switch (m_rotateOrder) { - case RO_XYZ : + case RO_XYZ: { //Is this the "line of nodes" calculation choosing planes YZ (B coordinate system) and xy (A coordinate system)? (http://en.wikipedia.org/wiki/Euler_angles) //The two planes are non-homologous, so this is a Tait–Bryan angle formalism and not a proper Euler //Extrinsic rotations are equal to the reversed order intrinsic rotations so the above xyz extrinsic rotations (axes are fixed) are the same as the zy'x" intrinsic rotations (axes are refreshed after each rotation) //that is why xy and YZ planes are chosen (this will describe a zy'x" intrinsic rotation) (see the figure on the left at http://en.wikipedia.org/wiki/Euler_angles under Tait–Bryan angles) // x' = Nperp = N.cross(axis2) - // y' = N = axis2.cross(axis0) + // y' = N = axis2.cross(axis0) // z' = z // // x" = X @@ -324,7 +324,7 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo() //first rotate around z //second rotate around y'= z.cross(X) //third rotate around x" = X - //Original XYZ extrinsic rotation order. + //Original XYZ extrinsic rotation order. //Planes: xy and YZ normals: z, X. Plane intersection (N) is z.cross(X) btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0); btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2); @@ -333,7 +333,7 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo() m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]); break; } - case RO_XZY : + case RO_XZY: { //planes: xz,ZY normals: y, X //first rotate around y @@ -346,7 +346,7 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo() m_calculatedAxis[1] = m_calculatedAxis[2].cross(axis0); break; } - case RO_YXZ : + case RO_YXZ: { //planes: yx,XZ normals: z, Y //first rotate around z @@ -359,7 +359,7 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo() m_calculatedAxis[2] = m_calculatedAxis[0].cross(axis1); break; } - case RO_YZX : + case RO_YZX: { //planes: yz,ZX normals: x, Y //first rotate around x @@ -372,7 +372,7 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo() m_calculatedAxis[1] = m_calculatedAxis[2].cross(axis0); break; } - case RO_ZXY : + case RO_ZXY: { //planes: zx,XY normals: y, Z //first rotate around y @@ -385,7 +385,7 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo() m_calculatedAxis[2] = m_calculatedAxis[0].cross(axis1); break; } - case RO_ZYX : + case RO_ZYX: { //planes: zy,YX normals: x, Z //first rotate around x @@ -398,22 +398,21 @@ void btGeneric6DofSpring2Constraint::calculateAngleInfo() m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]); break; } - default: - btAssert(false); + default: + btAssert(false); } m_calculatedAxis[0].normalize(); m_calculatedAxis[1].normalize(); m_calculatedAxis[2].normalize(); - } void btGeneric6DofSpring2Constraint::calculateTransforms() { - calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform()); } -void btGeneric6DofSpring2Constraint::calculateTransforms(const btTransform& transA,const btTransform& transB) +void btGeneric6DofSpring2Constraint::calculateTransforms(const btTransform& transA, const btTransform& transB) { m_calculatedTransformA = transA * m_frameInA; m_calculatedTransformB = transB * m_frameInB; @@ -424,18 +423,17 @@ void btGeneric6DofSpring2Constraint::calculateTransforms(const btTransform& tran btScalar miB = getRigidBodyB().getInvMass(); m_hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON); btScalar miS = miA + miB; - if(miS > btScalar(0.f)) + if (miS > btScalar(0.f)) { m_factA = miB / miS; } - else + else { m_factA = btScalar(0.5f); } m_factB = btScalar(1.0f) - m_factA; } - void btGeneric6DofSpring2Constraint::testAngularLimitMotor(int axis_index) { btScalar angle = m_calculatedAxisAngleDiff[axis_index]; @@ -444,35 +442,37 @@ void btGeneric6DofSpring2Constraint::testAngularLimitMotor(int axis_index) m_angularLimits[axis_index].testLimitValue(angle); } - -void btGeneric6DofSpring2Constraint::getInfo1 (btConstraintInfo1* info) +void btGeneric6DofSpring2Constraint::getInfo1(btConstraintInfo1* info) { //prepare constraint - calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform()); info->m_numConstraintRows = 0; info->nub = 0; int i; //test linear limits - for(i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { - if (m_linearLimits.m_currentLimit[i]==4) info->m_numConstraintRows += 2; - else if (m_linearLimits.m_currentLimit[i]!=0) info->m_numConstraintRows += 1; - if (m_linearLimits.m_enableMotor[i] ) info->m_numConstraintRows += 1; + if (m_linearLimits.m_currentLimit[i] == 4) + info->m_numConstraintRows += 2; + else if (m_linearLimits.m_currentLimit[i] != 0) + info->m_numConstraintRows += 1; + if (m_linearLimits.m_enableMotor[i]) info->m_numConstraintRows += 1; if (m_linearLimits.m_enableSpring[i]) info->m_numConstraintRows += 1; } //test angular limits - for (i=0;i<3 ;i++ ) + for (i = 0; i < 3; i++) { testAngularLimitMotor(i); - if (m_angularLimits[i].m_currentLimit==4) info->m_numConstraintRows += 2; - else if (m_angularLimits[i].m_currentLimit!=0) info->m_numConstraintRows += 1; - if (m_angularLimits[i].m_enableMotor ) info->m_numConstraintRows += 1; + if (m_angularLimits[i].m_currentLimit == 4) + info->m_numConstraintRows += 2; + else if (m_angularLimits[i].m_currentLimit != 0) + info->m_numConstraintRows += 1; + if (m_angularLimits[i].m_enableMotor) info->m_numConstraintRows += 1; if (m_angularLimits[i].m_enableSpring) info->m_numConstraintRows += 1; } } - -void btGeneric6DofSpring2Constraint::getInfo2 (btConstraintInfo2* info) +void btGeneric6DofSpring2Constraint::getInfo2(btConstraintInfo2* info) { const btTransform& transA = m_rbA.getCenterOfMassTransform(); const btTransform& transB = m_rbB.getCenterOfMassTransform(); @@ -482,118 +482,138 @@ void btGeneric6DofSpring2Constraint::getInfo2 (btConstraintInfo2* info) const btVector3& angVelB = m_rbB.getAngularVelocity(); // for stability better to solve angular limits first - int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB); - setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB); + int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB); + setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB); } - -int btGeneric6DofSpring2Constraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB) +int btGeneric6DofSpring2Constraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB) { //solve linear limits btRotationalLimitMotor2 limot; - for (int i=0;i<3 ;i++ ) + for (int i = 0; i < 3; i++) { - if(m_linearLimits.m_currentLimit[i] || m_linearLimits.m_enableMotor[i] || m_linearLimits.m_enableSpring[i]) - { // re-use rotational motor code - limot.m_bounce = m_linearLimits.m_bounce[i]; - limot.m_currentLimit = m_linearLimits.m_currentLimit[i]; - limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i]; - limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i]; - limot.m_currentLimitErrorHi = m_linearLimits.m_currentLimitErrorHi[i]; - limot.m_enableMotor = m_linearLimits.m_enableMotor[i]; - limot.m_servoMotor = m_linearLimits.m_servoMotor[i]; - limot.m_servoTarget = m_linearLimits.m_servoTarget[i]; - limot.m_enableSpring = m_linearLimits.m_enableSpring[i]; - limot.m_springStiffness = m_linearLimits.m_springStiffness[i]; + if (m_linearLimits.m_currentLimit[i] || m_linearLimits.m_enableMotor[i] || m_linearLimits.m_enableSpring[i]) + { // re-use rotational motor code + limot.m_bounce = m_linearLimits.m_bounce[i]; + limot.m_currentLimit = m_linearLimits.m_currentLimit[i]; + limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i]; + limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i]; + limot.m_currentLimitErrorHi = m_linearLimits.m_currentLimitErrorHi[i]; + limot.m_enableMotor = m_linearLimits.m_enableMotor[i]; + limot.m_servoMotor = m_linearLimits.m_servoMotor[i]; + limot.m_servoTarget = m_linearLimits.m_servoTarget[i]; + limot.m_enableSpring = m_linearLimits.m_enableSpring[i]; + limot.m_springStiffness = m_linearLimits.m_springStiffness[i]; limot.m_springStiffnessLimited = m_linearLimits.m_springStiffnessLimited[i]; - limot.m_springDamping = m_linearLimits.m_springDamping[i]; - limot.m_springDampingLimited = m_linearLimits.m_springDampingLimited[i]; - limot.m_equilibriumPoint = m_linearLimits.m_equilibriumPoint[i]; - limot.m_hiLimit = m_linearLimits.m_upperLimit[i]; - limot.m_loLimit = m_linearLimits.m_lowerLimit[i]; - limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i]; - limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i]; + limot.m_springDamping = m_linearLimits.m_springDamping[i]; + limot.m_springDampingLimited = m_linearLimits.m_springDampingLimited[i]; + limot.m_equilibriumPoint = m_linearLimits.m_equilibriumPoint[i]; + limot.m_hiLimit = m_linearLimits.m_upperLimit[i]; + limot.m_loLimit = m_linearLimits.m_lowerLimit[i]; + limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i]; + limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i]; btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i); int flags = m_flags >> (i * BT_6DOF_FLAGS_AXIS_SHIFT2); - limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP2) ? m_linearLimits.m_stopCFM[i] : info->cfm[0]; - limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP2) ? m_linearLimits.m_stopERP[i] : info->erp; + limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP2) ? m_linearLimits.m_stopCFM[i] : info->cfm[0]; + limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP2) ? m_linearLimits.m_stopERP[i] : info->erp; limot.m_motorCFM = (flags & BT_6DOF_FLAGS_CFM_MOTO2) ? m_linearLimits.m_motorCFM[i] : info->cfm[0]; limot.m_motorERP = (flags & BT_6DOF_FLAGS_ERP_MOTO2) ? m_linearLimits.m_motorERP[i] : info->erp; //rotAllowed is a bit of a magic from the original 6dof. The calculation of it here is something that imitates the original behavior as much as possible. int indx1 = (i + 1) % 3; int indx2 = (i + 2) % 3; - int rotAllowed = 1; // rotations around orthos to current axis (it is used only when one of the body is static) - #define D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION 1.0e-3 + int rotAllowed = 1; // rotations around orthos to current axis (it is used only when one of the body is static) +#define D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION 1.0e-3 bool indx1Violated = m_angularLimits[indx1].m_currentLimit == 1 || - m_angularLimits[indx1].m_currentLimit == 2 || - ( m_angularLimits[indx1].m_currentLimit == 3 && ( m_angularLimits[indx1].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx1].m_currentLimitError > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION ) ) || - ( m_angularLimits[indx1].m_currentLimit == 4 && ( m_angularLimits[indx1].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx1].m_currentLimitErrorHi > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION ) ); + m_angularLimits[indx1].m_currentLimit == 2 || + (m_angularLimits[indx1].m_currentLimit == 3 && (m_angularLimits[indx1].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx1].m_currentLimitError > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION)) || + (m_angularLimits[indx1].m_currentLimit == 4 && (m_angularLimits[indx1].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx1].m_currentLimitErrorHi > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION)); bool indx2Violated = m_angularLimits[indx2].m_currentLimit == 1 || - m_angularLimits[indx2].m_currentLimit == 2 || - ( m_angularLimits[indx2].m_currentLimit == 3 && ( m_angularLimits[indx2].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx2].m_currentLimitError > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION ) ) || - ( m_angularLimits[indx2].m_currentLimit == 4 && ( m_angularLimits[indx2].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx2].m_currentLimitErrorHi > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION ) ); - if( indx1Violated && indx2Violated ) + m_angularLimits[indx2].m_currentLimit == 2 || + (m_angularLimits[indx2].m_currentLimit == 3 && (m_angularLimits[indx2].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx2].m_currentLimitError > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION)) || + (m_angularLimits[indx2].m_currentLimit == 4 && (m_angularLimits[indx2].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx2].m_currentLimitErrorHi > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION)); + if (indx1Violated && indx2Violated) { rotAllowed = 0; } - row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0, rotAllowed); - + row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0, rotAllowed); } } return row; } - - -int btGeneric6DofSpring2Constraint::setAngularLimits(btConstraintInfo2 *info, int row_offset, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB) +int btGeneric6DofSpring2Constraint::setAngularLimits(btConstraintInfo2* info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB) { int row = row_offset; //order of rotational constraint rows int cIdx[] = {0, 1, 2}; - switch(m_rotateOrder) + switch (m_rotateOrder) { - case RO_XYZ : cIdx[0] = 0; cIdx[1] = 1; cIdx[2] = 2; break; - case RO_XZY : cIdx[0] = 0; cIdx[1] = 2; cIdx[2] = 1; break; - case RO_YXZ : cIdx[0] = 1; cIdx[1] = 0; cIdx[2] = 2; break; - case RO_YZX : cIdx[0] = 1; cIdx[1] = 2; cIdx[2] = 0; break; - case RO_ZXY : cIdx[0] = 2; cIdx[1] = 0; cIdx[2] = 1; break; - case RO_ZYX : cIdx[0] = 2; cIdx[1] = 1; cIdx[2] = 0; break; - default : btAssert(false); + case RO_XYZ: + cIdx[0] = 0; + cIdx[1] = 1; + cIdx[2] = 2; + break; + case RO_XZY: + cIdx[0] = 0; + cIdx[1] = 2; + cIdx[2] = 1; + break; + case RO_YXZ: + cIdx[0] = 1; + cIdx[1] = 0; + cIdx[2] = 2; + break; + case RO_YZX: + cIdx[0] = 1; + cIdx[1] = 2; + cIdx[2] = 0; + break; + case RO_ZXY: + cIdx[0] = 2; + cIdx[1] = 0; + cIdx[2] = 1; + break; + case RO_ZYX: + cIdx[0] = 2; + cIdx[1] = 1; + cIdx[2] = 0; + break; + default: + btAssert(false); } - for (int ii = 0; ii < 3 ; ii++ ) + for (int ii = 0; ii < 3; ii++) { int i = cIdx[ii]; - if(m_angularLimits[i].m_currentLimit || m_angularLimits[i].m_enableMotor || m_angularLimits[i].m_enableSpring) + if (m_angularLimits[i].m_currentLimit || m_angularLimits[i].m_enableMotor || m_angularLimits[i].m_enableSpring) { btVector3 axis = getAxis(i); int flags = m_flags >> ((i + 3) * BT_6DOF_FLAGS_AXIS_SHIFT2); - if(!(flags & BT_6DOF_FLAGS_CFM_STOP2)) + if (!(flags & BT_6DOF_FLAGS_CFM_STOP2)) { m_angularLimits[i].m_stopCFM = info->cfm[0]; } - if(!(flags & BT_6DOF_FLAGS_ERP_STOP2)) + if (!(flags & BT_6DOF_FLAGS_ERP_STOP2)) { m_angularLimits[i].m_stopERP = info->erp; } - if(!(flags & BT_6DOF_FLAGS_CFM_MOTO2)) + if (!(flags & BT_6DOF_FLAGS_CFM_MOTO2)) { m_angularLimits[i].m_motorCFM = info->cfm[0]; } - if(!(flags & BT_6DOF_FLAGS_ERP_MOTO2)) + if (!(flags & BT_6DOF_FLAGS_ERP_MOTO2)) { m_angularLimits[i].m_motorERP = info->erp; } - row += get_limit_motor_info2(&m_angularLimits[i],transA,transB,linVelA,linVelB,angVelA,angVelB, info,row,axis,1); + row += get_limit_motor_info2(&m_angularLimits[i], transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 1); } } return row; } - void btGeneric6DofSpring2Constraint::setFrames(const btTransform& frameA, const btTransform& frameB) { m_frameInA = frameA; @@ -602,32 +622,31 @@ void btGeneric6DofSpring2Constraint::setFrames(const btTransform& frameA, const calculateTransforms(); } - void btGeneric6DofSpring2Constraint::calculateLinearInfo() { m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin(); m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff; - for(int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i]; m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]); } } -void btGeneric6DofSpring2Constraint::calculateJacobi(btRotationalLimitMotor2 * limot, const btTransform& transA,const btTransform& transB, btConstraintInfo2 *info, int srow, btVector3& ax1, int rotational, int rotAllowed) +void btGeneric6DofSpring2Constraint::calculateJacobi(btRotationalLimitMotor2* limot, const btTransform& transA, const btTransform& transB, btConstraintInfo2* info, int srow, btVector3& ax1, int rotational, int rotAllowed) { - btScalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis; - btScalar *J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis; + btScalar* J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis; + btScalar* J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis; - J1[srow+0] = ax1[0]; - J1[srow+1] = ax1[1]; - J1[srow+2] = ax1[2]; + J1[srow + 0] = ax1[0]; + J1[srow + 1] = ax1[1]; + J1[srow + 2] = ax1[2]; - J2[srow+0] = -ax1[0]; - J2[srow+1] = -ax1[1]; - J2[srow+2] = -ax1[2]; + J2[srow + 0] = -ax1[0]; + J2[srow + 1] = -ax1[1]; + J2[srow + 2] = -ax1[2]; - if(!rotational) + if (!rotational) { btVector3 tmpA, tmpB, relA, relB; // get vector from bodyB to frameB in WCS @@ -636,40 +655,44 @@ void btGeneric6DofSpring2Constraint::calculateJacobi(btRotationalLimitMotor2 * l relA = m_calculatedTransformA.getOrigin() - transA.getOrigin(); tmpA = relA.cross(ax1); tmpB = relB.cross(ax1); - if(m_hasStaticBody && (!rotAllowed)) + if (m_hasStaticBody && (!rotAllowed)) { tmpA *= m_factA; tmpB *= m_factB; } int i; - for (i=0; i<3; i++) info->m_J1angularAxis[srow+i] = tmpA[i]; - for (i=0; i<3; i++) info->m_J2angularAxis[srow+i] = -tmpB[i]; + for (i = 0; i < 3; i++) info->m_J1angularAxis[srow + i] = tmpA[i]; + for (i = 0; i < 3; i++) info->m_J2angularAxis[srow + i] = -tmpB[i]; } } - int btGeneric6DofSpring2Constraint::get_limit_motor_info2( - btRotationalLimitMotor2 * limot, - const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB, - btConstraintInfo2 *info, int row, btVector3& ax1, int rotational,int rotAllowed) + btRotationalLimitMotor2* limot, + const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB, + btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed) { int count = 0; int srow = row * info->rowskip; - if (limot->m_currentLimit==4) + if (limot->m_currentLimit == 4) { btScalar vel = rotational ? angVelA.dot(ax1) - angVelB.dot(ax1) : linVelA.dot(ax1) - linVelB.dot(ax1); - calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed); + calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed); info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitError * (rotational ? -1 : 1); - if (rotational) { - if (info->m_constraintError[srow]-vel*limot->m_stopERP > 0) { - btScalar bounceerror = -limot->m_bounce* vel; + if (rotational) + { + if (info->m_constraintError[srow] - vel * limot->m_stopERP > 0) + { + btScalar bounceerror = -limot->m_bounce * vel; if (bounceerror > info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror; } - } else { - if (info->m_constraintError[srow]-vel*limot->m_stopERP < 0) { - btScalar bounceerror = -limot->m_bounce* vel; + } + else + { + if (info->m_constraintError[srow] - vel * limot->m_stopERP < 0) + { + btScalar bounceerror = -limot->m_bounce * vel; if (bounceerror < info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror; } } @@ -679,16 +702,21 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2( srow += info->rowskip; ++count; - calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed); + calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed); info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitErrorHi * (rotational ? -1 : 1); - if (rotational) { - if (info->m_constraintError[srow]-vel*limot->m_stopERP < 0) { - btScalar bounceerror = -limot->m_bounce* vel; + if (rotational) + { + if (info->m_constraintError[srow] - vel * limot->m_stopERP < 0) + { + btScalar bounceerror = -limot->m_bounce * vel; if (bounceerror < info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror; } - } else { - if (info->m_constraintError[srow]-vel*limot->m_stopERP > 0) { - btScalar bounceerror = -limot->m_bounce* vel; + } + else + { + if (info->m_constraintError[srow] - vel * limot->m_stopERP > 0) + { + btScalar bounceerror = -limot->m_bounce * vel; if (bounceerror > info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror; } } @@ -697,10 +725,10 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2( info->cfm[srow] = limot->m_stopCFM; srow += info->rowskip; ++count; - } else - if (limot->m_currentLimit==3) + } + else if (limot->m_currentLimit == 3) { - calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed); + calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed); info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitError * (rotational ? -1 : 1); info->m_lowerLimit[srow] = -SIMD_INFINITY; info->m_upperLimit[srow] = SIMD_INFINITY; @@ -711,13 +739,13 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2( if (limot->m_enableMotor && !limot->m_servoMotor) { - calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed); + calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed); btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity; - btScalar mot_fact = getMotorFactor(limot->m_currentPosition, - limot->m_loLimit, - limot->m_hiLimit, - tag_vel, - info->fps * limot->m_motorERP); + btScalar mot_fact = getMotorFactor(limot->m_currentPosition, + limot->m_loLimit, + limot->m_hiLimit, + tag_vel, + info->fps * limot->m_motorERP); info->m_constraintError[srow] = mot_fact * limot->m_targetVelocity; info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps; info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps; @@ -735,36 +763,36 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2( if (error > SIMD_PI) { error -= SIMD_2_PI; - curServoTarget +=SIMD_2_PI; + curServoTarget += SIMD_2_PI; } if (error < -SIMD_PI) { error += SIMD_2_PI; - curServoTarget -=SIMD_2_PI; + curServoTarget -= SIMD_2_PI; } } - calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed); - btScalar targetvelocity = error<0 ? -limot->m_targetVelocity : limot->m_targetVelocity; + calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed); + btScalar targetvelocity = error < 0 ? -limot->m_targetVelocity : limot->m_targetVelocity; btScalar tag_vel = -targetvelocity; btScalar mot_fact; - if(error != 0) + if (error != 0) { btScalar lowLimit; btScalar hiLimit; - if(limot->m_loLimit > limot->m_hiLimit) + if (limot->m_loLimit > limot->m_hiLimit) { lowLimit = error > 0 ? curServoTarget : -SIMD_INFINITY; - hiLimit = error < 0 ? curServoTarget : SIMD_INFINITY; + hiLimit = error < 0 ? curServoTarget : SIMD_INFINITY; } else { - lowLimit = error > 0 && curServoTarget>limot->m_loLimit ? curServoTarget : limot->m_loLimit; - hiLimit = error < 0 && curServoTarget<limot->m_hiLimit ? curServoTarget : limot->m_hiLimit; + lowLimit = error > 0 && curServoTarget > limot->m_loLimit ? curServoTarget : limot->m_loLimit; + hiLimit = error < 0 && curServoTarget < limot->m_hiLimit ? curServoTarget : limot->m_hiLimit; } mot_fact = getMotorFactor(limot->m_currentPosition, lowLimit, hiLimit, tag_vel, info->fps * limot->m_motorERP); - } - else + } + else { mot_fact = 0; } @@ -779,7 +807,7 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2( if (limot->m_enableSpring) { btScalar error = limot->m_currentPosition - limot->m_equilibriumPoint; - calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed); + calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed); //btScalar cfm = 1.0 / ((1.0/info->fps)*limot->m_springStiffness+ limot->m_springDamping); //if(cfm > 0.99999) @@ -792,34 +820,46 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2( btScalar dt = BT_ONE / info->fps; btScalar kd = limot->m_springDamping; btScalar ks = limot->m_springStiffness; - btScalar vel = rotational ? angVelA.dot(ax1) - angVelB.dot(ax1) : linVelA.dot(ax1) - linVelB.dot(ax1); -// btScalar erp = 0.1; + btScalar vel; + if (rotational) + { + vel = angVelA.dot(ax1) - angVelB.dot(ax1); + } + else + { + btVector3 tanVelA = angVelA.cross(m_calculatedTransformA.getOrigin() - transA.getOrigin()); + btVector3 tanVelB = angVelB.cross(m_calculatedTransformB.getOrigin() - transB.getOrigin()); + vel = (linVelA + tanVelA).dot(ax1) - (linVelB + tanVelB).dot(ax1); + } btScalar cfm = BT_ZERO; btScalar mA = BT_ONE / m_rbA.getInvMass(); btScalar mB = BT_ONE / m_rbB.getInvMass(); - if (rotational) { + if (rotational) + { btScalar rrA = (m_calculatedTransformA.getOrigin() - transA.getOrigin()).length2(); btScalar rrB = (m_calculatedTransformB.getOrigin() - transB.getOrigin()).length2(); if (m_rbA.getInvMass()) mA = mA * rrA + 1 / (m_rbA.getInvInertiaTensorWorld() * ax1).length(); if (m_rbB.getInvMass()) mB = mB * rrB + 1 / (m_rbB.getInvInertiaTensorWorld() * ax1).length(); } - btScalar m = mA > mB ? mB : mA; + btScalar m; + if (m_rbA.getInvMass() == 0) m = mB; else + if (m_rbB.getInvMass() == 0) m = mA; else + m = mA*mB / (mA + mB); btScalar angularfreq = sqrt(ks / m); - //limit stiffness (the spring should not be sampled faster that the quarter of its angular frequency) - if(limot->m_springStiffnessLimited && 0.25 < angularfreq * dt) + if (limot->m_springStiffnessLimited && 0.25 < angularfreq * dt) { ks = BT_ONE / dt / dt / btScalar(16.0) * m; } //avoid damping that would blow up the spring - if(limot->m_springDampingLimited && kd * dt > m) + if (limot->m_springDampingLimited && kd * dt > m) { kd = m / dt; } btScalar fs = ks * error * dt; btScalar fd = -kd * (vel) * (rotational ? -1 : 1) * dt; - btScalar f = (fs+fd); + btScalar f = (fs + fd); // after the spring force affecting the body(es) the new velocity will be // vel + f / m * (rotational ? -1 : 1) @@ -828,15 +868,18 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2( // however in practice any value is fine as long as it is greater then the "proper" velocity, // because the m_lowerLimit and the m_upperLimit will determinate the strength of the final pulling force // so it is much simpler (and more robust) just to simply use inf (with the proper sign) + // (Even with our best intent the "new" velocity is only an estimation. If we underestimate + // the "proper" velocity that will weaken the spring, however if we overestimate it, it doesn't + // matter, because the solver will limit it according the force limit) // you may also wonder what if the current velocity (vel) so high that the pulling force will not change its direction (in this iteration) // will we not request a velocity with the wrong direction ? - // and the answare is not, because in practice during the solving the current velocity is subtracted from the m_constraintError + // and the answer is not, because in practice during the solving the current velocity is subtracted from the m_constraintError // so the sign of the force that is really matters info->m_constraintError[srow] = (rotational ? -1 : 1) * (f < 0 ? -SIMD_INFINITY : SIMD_INFINITY); btScalar minf = f < fd ? f : fd; btScalar maxf = f < fd ? fd : f; - if(!rotational) + if (!rotational) { info->m_lowerLimit[srow] = minf > 0 ? 0 : minf; info->m_upperLimit[srow] = maxf < 0 ? 0 : maxf; @@ -855,56 +898,55 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2( return count; } - -//override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). +//override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). //If no axis is provided, it uses the default axis for this constraint. void btGeneric6DofSpring2Constraint::setParam(int num, btScalar value, int axis) { - if((axis >= 0) && (axis < 3)) + if ((axis >= 0) && (axis < 3)) { - switch(num) + switch (num) { - case BT_CONSTRAINT_STOP_ERP : + case BT_CONSTRAINT_STOP_ERP: m_linearLimits.m_stopERP[axis] = value; m_flags |= BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2); break; - case BT_CONSTRAINT_STOP_CFM : + case BT_CONSTRAINT_STOP_CFM: m_linearLimits.m_stopCFM[axis] = value; m_flags |= BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2); break; - case BT_CONSTRAINT_ERP : + case BT_CONSTRAINT_ERP: m_linearLimits.m_motorERP[axis] = value; m_flags |= BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2); break; - case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_CFM: m_linearLimits.m_motorCFM[axis] = value; m_flags |= BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2); break; - default : + default: btAssertConstrParams(0); } } - else if((axis >=3) && (axis < 6)) + else if ((axis >= 3) && (axis < 6)) { - switch(num) + switch (num) { - case BT_CONSTRAINT_STOP_ERP : + case BT_CONSTRAINT_STOP_ERP: m_angularLimits[axis - 3].m_stopERP = value; m_flags |= BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2); break; - case BT_CONSTRAINT_STOP_CFM : + case BT_CONSTRAINT_STOP_CFM: m_angularLimits[axis - 3].m_stopCFM = value; m_flags |= BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2); break; - case BT_CONSTRAINT_ERP : + case BT_CONSTRAINT_ERP: m_angularLimits[axis - 3].m_motorERP = value; m_flags |= BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2); break; - case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_CFM: m_angularLimits[axis - 3].m_motorCFM = value; m_flags |= BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2); break; - default : + default: btAssertConstrParams(0); } } @@ -915,54 +957,54 @@ void btGeneric6DofSpring2Constraint::setParam(int num, btScalar value, int axis) } //return the local value of parameter -btScalar btGeneric6DofSpring2Constraint::getParam(int num, int axis) const +btScalar btGeneric6DofSpring2Constraint::getParam(int num, int axis) const { btScalar retVal = 0; - if((axis >= 0) && (axis < 3)) + if ((axis >= 0) && (axis < 3)) { - switch(num) + switch (num) { - case BT_CONSTRAINT_STOP_ERP : + case BT_CONSTRAINT_STOP_ERP: btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2))); retVal = m_linearLimits.m_stopERP[axis]; break; - case BT_CONSTRAINT_STOP_CFM : + case BT_CONSTRAINT_STOP_CFM: btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2))); retVal = m_linearLimits.m_stopCFM[axis]; break; - case BT_CONSTRAINT_ERP : + case BT_CONSTRAINT_ERP: btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2))); retVal = m_linearLimits.m_motorERP[axis]; break; - case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_CFM: btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2))); retVal = m_linearLimits.m_motorCFM[axis]; break; - default : + default: btAssertConstrParams(0); } } - else if((axis >=3) && (axis < 6)) + else if ((axis >= 3) && (axis < 6)) { - switch(num) + switch (num) { - case BT_CONSTRAINT_STOP_ERP : + case BT_CONSTRAINT_STOP_ERP: btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2))); retVal = m_angularLimits[axis - 3].m_stopERP; break; - case BT_CONSTRAINT_STOP_CFM : + case BT_CONSTRAINT_STOP_CFM: btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2))); retVal = m_angularLimits[axis - 3].m_stopCFM; break; - case BT_CONSTRAINT_ERP : + case BT_CONSTRAINT_ERP: btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2))); retVal = m_angularLimits[axis - 3].m_motorERP; break; - case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_CFM: btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2))); retVal = m_angularLimits[axis - 3].m_motorCFM; break; - default : + default: btAssertConstrParams(0); } } @@ -973,31 +1015,29 @@ btScalar btGeneric6DofSpring2Constraint::getParam(int num, int axis) const return retVal; } - - -void btGeneric6DofSpring2Constraint::setAxis(const btVector3& axis1,const btVector3& axis2) +void btGeneric6DofSpring2Constraint::setAxis(const btVector3& axis1, const btVector3& axis2) { btVector3 zAxis = axis1.normalized(); btVector3 yAxis = axis2.normalized(); - btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system - + btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system + btTransform frameInW; frameInW.setIdentity(); - frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], - xAxis[1], yAxis[1], zAxis[1], - xAxis[2], yAxis[2], zAxis[2]); - + frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); + // now get constraint frame in local coordinate systems m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW; m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW; - + calculateTransforms(); } void btGeneric6DofSpring2Constraint::setBounce(int index, btScalar bounce) { btAssert((index >= 0) && (index < 6)); - if (index<3) + if (index < 3) m_linearLimits.m_bounce[index] = bounce; else m_angularLimits[index - 3].m_bounce = bounce; @@ -1006,7 +1046,7 @@ void btGeneric6DofSpring2Constraint::setBounce(int index, btScalar bounce) void btGeneric6DofSpring2Constraint::enableMotor(int index, bool onOff) { btAssert((index >= 0) && (index < 6)); - if (index<3) + if (index < 3) m_linearLimits.m_enableMotor[index] = onOff; else m_angularLimits[index - 3].m_enableMotor = onOff; @@ -1015,7 +1055,7 @@ void btGeneric6DofSpring2Constraint::enableMotor(int index, bool onOff) void btGeneric6DofSpring2Constraint::setServo(int index, bool onOff) { btAssert((index >= 0) && (index < 6)); - if (index<3) + if (index < 3) m_linearLimits.m_servoMotor[index] = onOff; else m_angularLimits[index - 3].m_servoMotor = onOff; @@ -1024,18 +1064,16 @@ void btGeneric6DofSpring2Constraint::setServo(int index, bool onOff) void btGeneric6DofSpring2Constraint::setTargetVelocity(int index, btScalar velocity) { btAssert((index >= 0) && (index < 6)); - if (index<3) + if (index < 3) m_linearLimits.m_targetVelocity[index] = velocity; else m_angularLimits[index - 3].m_targetVelocity = velocity; } - - void btGeneric6DofSpring2Constraint::setServoTarget(int index, btScalar targetOrg) { btAssert((index >= 0) && (index < 6)); - if (index<3) + if (index < 3) { m_linearLimits.m_servoTarget[index] = targetOrg; } @@ -1044,23 +1082,24 @@ void btGeneric6DofSpring2Constraint::setServoTarget(int index, btScalar targetOr //wrap between -PI and PI, see also //https://stackoverflow.com/questions/4633177/c-how-to-wrap-a-float-to-the-interval-pi-pi - btScalar target = targetOrg+SIMD_PI; + btScalar target = targetOrg + SIMD_PI; if (1) { - btScalar m = target - SIMD_2_PI * floor(target/SIMD_2_PI); + btScalar m = target - SIMD_2_PI * floor(target / SIMD_2_PI); // handle boundary cases resulted from floating-point cut off: { - if (m>=SIMD_2_PI) + if (m >= SIMD_2_PI) { target = 0; - } else + } + else { - if (m<0 ) + if (m < 0) { - if (SIMD_2_PI+m == SIMD_2_PI) + if (SIMD_2_PI + m == SIMD_2_PI) target = 0; else - target = SIMD_2_PI+m; + target = SIMD_2_PI + m; } else { @@ -1070,7 +1109,7 @@ void btGeneric6DofSpring2Constraint::setServoTarget(int index, btScalar targetOr } target -= SIMD_PI; } - + m_angularLimits[index - 3].m_servoTarget = target; } } @@ -1078,7 +1117,7 @@ void btGeneric6DofSpring2Constraint::setServoTarget(int index, btScalar targetOr void btGeneric6DofSpring2Constraint::setMaxMotorForce(int index, btScalar force) { btAssert((index >= 0) && (index < 6)); - if (index<3) + if (index < 3) m_linearLimits.m_maxMotorForce[index] = force; else m_angularLimits[index - 3].m_maxMotorForce = force; @@ -1087,19 +1126,22 @@ void btGeneric6DofSpring2Constraint::setMaxMotorForce(int index, btScalar force) void btGeneric6DofSpring2Constraint::enableSpring(int index, bool onOff) { btAssert((index >= 0) && (index < 6)); - if (index<3) + if (index < 3) m_linearLimits.m_enableSpring[index] = onOff; else - m_angularLimits[index - 3] .m_enableSpring = onOff; + m_angularLimits[index - 3].m_enableSpring = onOff; } void btGeneric6DofSpring2Constraint::setStiffness(int index, btScalar stiffness, bool limitIfNeeded) { btAssert((index >= 0) && (index < 6)); - if (index<3) { + if (index < 3) + { m_linearLimits.m_springStiffness[index] = stiffness; m_linearLimits.m_springStiffnessLimited[index] = limitIfNeeded; - } else { + } + else + { m_angularLimits[index - 3].m_springStiffness = stiffness; m_angularLimits[index - 3].m_springStiffnessLimited = limitIfNeeded; } @@ -1108,10 +1150,13 @@ void btGeneric6DofSpring2Constraint::setStiffness(int index, btScalar stiffness, void btGeneric6DofSpring2Constraint::setDamping(int index, btScalar damping, bool limitIfNeeded) { btAssert((index >= 0) && (index < 6)); - if (index<3) { + if (index < 3) + { m_linearLimits.m_springDamping[index] = damping; m_linearLimits.m_springDampingLimited[index] = limitIfNeeded; - } else { + } + else + { m_angularLimits[index - 3].m_springDamping = damping; m_angularLimits[index - 3].m_springDampingLimited = limitIfNeeded; } @@ -1121,9 +1166,9 @@ void btGeneric6DofSpring2Constraint::setEquilibriumPoint() { calculateTransforms(); int i; - for( i = 0; i < 3; i++) + for (i = 0; i < 3; i++) m_linearLimits.m_equilibriumPoint[i] = m_calculatedLinearDiff[i]; - for(i = 0; i < 3; i++) + for (i = 0; i < 3; i++) m_angularLimits[i].m_equilibriumPoint = m_calculatedAxisAngleDiff[i]; } @@ -1131,35 +1176,38 @@ void btGeneric6DofSpring2Constraint::setEquilibriumPoint(int index) { btAssert((index >= 0) && (index < 6)); calculateTransforms(); - if (index<3) + if (index < 3) m_linearLimits.m_equilibriumPoint[index] = m_calculatedLinearDiff[index]; else - m_angularLimits[index - 3] .m_equilibriumPoint = m_calculatedAxisAngleDiff[index - 3]; + m_angularLimits[index - 3].m_equilibriumPoint = m_calculatedAxisAngleDiff[index - 3]; } void btGeneric6DofSpring2Constraint::setEquilibriumPoint(int index, btScalar val) { btAssert((index >= 0) && (index < 6)); - if (index<3) + if (index < 3) m_linearLimits.m_equilibriumPoint[index] = val; else - m_angularLimits[index - 3] .m_equilibriumPoint = val; + m_angularLimits[index - 3].m_equilibriumPoint = val; } - //////////////////////////// btRotationalLimitMotor2 //////////////////////////////////// void btRotationalLimitMotor2::testLimitValue(btScalar test_value) { //we can't normalize the angles here because we would lost the sign that we use later, but it doesn't seem to be a problem - if(m_loLimit > m_hiLimit) { + if (m_loLimit > m_hiLimit) + { m_currentLimit = 0; m_currentLimitError = btScalar(0.f); } - else if(m_loLimit == m_hiLimit) { + else if (m_loLimit == m_hiLimit) + { m_currentLimitError = test_value - m_loLimit; m_currentLimit = 3; - } else { + } + else + { m_currentLimitError = test_value - m_loLimit; m_currentLimitErrorHi = test_value - m_hiLimit; m_currentLimit = 4; @@ -1172,18 +1220,20 @@ void btTranslationalLimitMotor2::testLimitValue(int limitIndex, btScalar test_va { btScalar loLimit = m_lowerLimit[limitIndex]; btScalar hiLimit = m_upperLimit[limitIndex]; - if(loLimit > hiLimit) { + if (loLimit > hiLimit) + { m_currentLimitError[limitIndex] = 0; m_currentLimit[limitIndex] = 0; } - else if(loLimit == hiLimit) { + else if (loLimit == hiLimit) + { m_currentLimitError[limitIndex] = test_value - loLimit; m_currentLimit[limitIndex] = 3; - } else { + } + else + { m_currentLimitError[limitIndex] = test_value - loLimit; m_currentLimitErrorHi[limitIndex] = test_value - hiLimit; m_currentLimit[limitIndex] = 4; } } - - diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h index 1b8d0eace9..bc3ee6d210 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h @@ -37,7 +37,6 @@ email: projectileman@yahoo.com http://gimpact.sf.net */ - #ifndef BT_GENERIC_6DOF_CONSTRAINT2_H #define BT_GENERIC_6DOF_CONSTRAINT2_H @@ -47,18 +46,17 @@ http://gimpact.sf.net class btRigidBody; - #ifdef BT_USE_DOUBLE_PRECISION -#define btGeneric6DofSpring2ConstraintData2 btGeneric6DofSpring2ConstraintDoubleData2 -#define btGeneric6DofSpring2ConstraintDataName "btGeneric6DofSpring2ConstraintDoubleData2" +#define btGeneric6DofSpring2ConstraintData2 btGeneric6DofSpring2ConstraintDoubleData2 +#define btGeneric6DofSpring2ConstraintDataName "btGeneric6DofSpring2ConstraintDoubleData2" #else -#define btGeneric6DofSpring2ConstraintData2 btGeneric6DofSpring2ConstraintData -#define btGeneric6DofSpring2ConstraintDataName "btGeneric6DofSpring2ConstraintData" -#endif //BT_USE_DOUBLE_PRECISION +#define btGeneric6DofSpring2ConstraintData2 btGeneric6DofSpring2ConstraintData +#define btGeneric6DofSpring2ConstraintDataName "btGeneric6DofSpring2ConstraintData" +#endif //BT_USE_DOUBLE_PRECISION enum RotateOrder { - RO_XYZ=0, + RO_XYZ = 0, RO_XZY, RO_YXZ, RO_YZX, @@ -69,9 +67,9 @@ enum RotateOrder class btRotationalLimitMotor2 { public: -// upper < lower means free -// upper == lower means locked -// upper > lower means limited + // upper < lower means free + // upper == lower means locked + // upper > lower means limited btScalar m_loLimit; btScalar m_hiLimit; btScalar m_bounce; @@ -79,95 +77,92 @@ public: btScalar m_stopCFM; btScalar m_motorERP; btScalar m_motorCFM; - bool m_enableMotor; + bool m_enableMotor; btScalar m_targetVelocity; btScalar m_maxMotorForce; - bool m_servoMotor; + bool m_servoMotor; btScalar m_servoTarget; - bool m_enableSpring; + bool m_enableSpring; btScalar m_springStiffness; - bool m_springStiffnessLimited; + bool m_springStiffnessLimited; btScalar m_springDamping; - bool m_springDampingLimited; + bool m_springDampingLimited; btScalar m_equilibriumPoint; btScalar m_currentLimitError; btScalar m_currentLimitErrorHi; btScalar m_currentPosition; - int m_currentLimit; + int m_currentLimit; btRotationalLimitMotor2() { - m_loLimit = 1.0f; - m_hiLimit = -1.0f; - m_bounce = 0.0f; - m_stopERP = 0.2f; - m_stopCFM = 0.f; - m_motorERP = 0.9f; - m_motorCFM = 0.f; - m_enableMotor = false; - m_targetVelocity = 0; - m_maxMotorForce = 6.0f; - m_servoMotor = false; - m_servoTarget = 0; - m_enableSpring = false; - m_springStiffness = 0; + m_loLimit = 1.0f; + m_hiLimit = -1.0f; + m_bounce = 0.0f; + m_stopERP = 0.2f; + m_stopCFM = 0.f; + m_motorERP = 0.9f; + m_motorCFM = 0.f; + m_enableMotor = false; + m_targetVelocity = 0; + m_maxMotorForce = 6.0f; + m_servoMotor = false; + m_servoTarget = 0; + m_enableSpring = false; + m_springStiffness = 0; m_springStiffnessLimited = false; - m_springDamping = 0; - m_springDampingLimited = false; - m_equilibriumPoint = 0; + m_springDamping = 0; + m_springDampingLimited = false; + m_equilibriumPoint = 0; - m_currentLimitError = 0; + m_currentLimitError = 0; m_currentLimitErrorHi = 0; - m_currentPosition = 0; - m_currentLimit = 0; + m_currentPosition = 0; + m_currentLimit = 0; } - btRotationalLimitMotor2(const btRotationalLimitMotor2 & limot) + btRotationalLimitMotor2(const btRotationalLimitMotor2& limot) { - m_loLimit = limot.m_loLimit; - m_hiLimit = limot.m_hiLimit; - m_bounce = limot.m_bounce; - m_stopERP = limot.m_stopERP; - m_stopCFM = limot.m_stopCFM; - m_motorERP = limot.m_motorERP; - m_motorCFM = limot.m_motorCFM; - m_enableMotor = limot.m_enableMotor; - m_targetVelocity = limot.m_targetVelocity; - m_maxMotorForce = limot.m_maxMotorForce; - m_servoMotor = limot.m_servoMotor; - m_servoTarget = limot.m_servoTarget; - m_enableSpring = limot.m_enableSpring; - m_springStiffness = limot.m_springStiffness; + m_loLimit = limot.m_loLimit; + m_hiLimit = limot.m_hiLimit; + m_bounce = limot.m_bounce; + m_stopERP = limot.m_stopERP; + m_stopCFM = limot.m_stopCFM; + m_motorERP = limot.m_motorERP; + m_motorCFM = limot.m_motorCFM; + m_enableMotor = limot.m_enableMotor; + m_targetVelocity = limot.m_targetVelocity; + m_maxMotorForce = limot.m_maxMotorForce; + m_servoMotor = limot.m_servoMotor; + m_servoTarget = limot.m_servoTarget; + m_enableSpring = limot.m_enableSpring; + m_springStiffness = limot.m_springStiffness; m_springStiffnessLimited = limot.m_springStiffnessLimited; - m_springDamping = limot.m_springDamping; - m_springDampingLimited = limot.m_springDampingLimited; - m_equilibriumPoint = limot.m_equilibriumPoint; + m_springDamping = limot.m_springDamping; + m_springDampingLimited = limot.m_springDampingLimited; + m_equilibriumPoint = limot.m_equilibriumPoint; - m_currentLimitError = limot.m_currentLimitError; + m_currentLimitError = limot.m_currentLimitError; m_currentLimitErrorHi = limot.m_currentLimitErrorHi; - m_currentPosition = limot.m_currentPosition; - m_currentLimit = limot.m_currentLimit; + m_currentPosition = limot.m_currentPosition; + m_currentLimit = limot.m_currentLimit; } - bool isLimited() { - if(m_loLimit > m_hiLimit) return false; + if (m_loLimit > m_hiLimit) return false; return true; } void testLimitValue(btScalar test_value); }; - - class btTranslationalLimitMotor2 { public: -// upper < lower means free -// upper == lower means locked -// upper > lower means limited + // upper < lower means free + // upper == lower means locked + // upper > lower means limited btVector3 m_lowerLimit; btVector3 m_upperLimit; btVector3 m_bounce; @@ -175,14 +170,14 @@ public: btVector3 m_stopCFM; btVector3 m_motorERP; btVector3 m_motorCFM; - bool m_enableMotor[3]; - bool m_servoMotor[3]; - bool m_enableSpring[3]; + bool m_enableMotor[3]; + bool m_servoMotor[3]; + bool m_enableSpring[3]; btVector3 m_servoTarget; btVector3 m_springStiffness; - bool m_springStiffnessLimited[3]; + bool m_springStiffnessLimited[3]; btVector3 m_springDamping; - bool m_springDampingLimited[3]; + bool m_springDampingLimited[3]; btVector3 m_equilibriumPoint; btVector3 m_targetVelocity; btVector3 m_maxMotorForce; @@ -190,69 +185,69 @@ public: btVector3 m_currentLimitError; btVector3 m_currentLimitErrorHi; btVector3 m_currentLinearDiff; - int m_currentLimit[3]; + int m_currentLimit[3]; btTranslationalLimitMotor2() { - m_lowerLimit .setValue(0.f , 0.f , 0.f ); - m_upperLimit .setValue(0.f , 0.f , 0.f ); - m_bounce .setValue(0.f , 0.f , 0.f ); - m_stopERP .setValue(0.2f, 0.2f, 0.2f); - m_stopCFM .setValue(0.f , 0.f , 0.f ); - m_motorERP .setValue(0.9f, 0.9f, 0.9f); - m_motorCFM .setValue(0.f , 0.f , 0.f ); - - m_currentLimitError .setValue(0.f , 0.f , 0.f ); - m_currentLimitErrorHi.setValue(0.f , 0.f , 0.f ); - m_currentLinearDiff .setValue(0.f , 0.f , 0.f ); - - for(int i=0; i < 3; i++) + m_lowerLimit.setValue(0.f, 0.f, 0.f); + m_upperLimit.setValue(0.f, 0.f, 0.f); + m_bounce.setValue(0.f, 0.f, 0.f); + m_stopERP.setValue(0.2f, 0.2f, 0.2f); + m_stopCFM.setValue(0.f, 0.f, 0.f); + m_motorERP.setValue(0.9f, 0.9f, 0.9f); + m_motorCFM.setValue(0.f, 0.f, 0.f); + + m_currentLimitError.setValue(0.f, 0.f, 0.f); + m_currentLimitErrorHi.setValue(0.f, 0.f, 0.f); + m_currentLinearDiff.setValue(0.f, 0.f, 0.f); + + for (int i = 0; i < 3; i++) { - m_enableMotor[i] = false; - m_servoMotor[i] = false; - m_enableSpring[i] = false; - m_servoTarget[i] = btScalar(0.f); - m_springStiffness[i] = btScalar(0.f); + m_enableMotor[i] = false; + m_servoMotor[i] = false; + m_enableSpring[i] = false; + m_servoTarget[i] = btScalar(0.f); + m_springStiffness[i] = btScalar(0.f); m_springStiffnessLimited[i] = false; - m_springDamping[i] = btScalar(0.f); - m_springDampingLimited[i] = false; - m_equilibriumPoint[i] = btScalar(0.f); - m_targetVelocity[i] = btScalar(0.f); - m_maxMotorForce[i] = btScalar(0.f); - - m_currentLimit[i] = 0; + m_springDamping[i] = btScalar(0.f); + m_springDampingLimited[i] = false; + m_equilibriumPoint[i] = btScalar(0.f); + m_targetVelocity[i] = btScalar(0.f); + m_maxMotorForce[i] = btScalar(0.f); + + m_currentLimit[i] = 0; } } - btTranslationalLimitMotor2(const btTranslationalLimitMotor2 & other ) + btTranslationalLimitMotor2(const btTranslationalLimitMotor2& other) { - m_lowerLimit = other.m_lowerLimit; - m_upperLimit = other.m_upperLimit; - m_bounce = other.m_bounce; - m_stopERP = other.m_stopERP; - m_stopCFM = other.m_stopCFM; - m_motorERP = other.m_motorERP; - m_motorCFM = other.m_motorCFM; - - m_currentLimitError = other.m_currentLimitError; + m_lowerLimit = other.m_lowerLimit; + m_upperLimit = other.m_upperLimit; + m_bounce = other.m_bounce; + m_stopERP = other.m_stopERP; + m_stopCFM = other.m_stopCFM; + m_motorERP = other.m_motorERP; + m_motorCFM = other.m_motorCFM; + + m_currentLimitError = other.m_currentLimitError; m_currentLimitErrorHi = other.m_currentLimitErrorHi; - m_currentLinearDiff = other.m_currentLinearDiff; + m_currentLinearDiff = other.m_currentLinearDiff; - for(int i=0; i < 3; i++) + for (int i = 0; i < 3; i++) { - m_enableMotor[i] = other.m_enableMotor[i]; - m_servoMotor[i] = other.m_servoMotor[i]; - m_enableSpring[i] = other.m_enableSpring[i]; - m_servoTarget[i] = other.m_servoTarget[i]; - m_springStiffness[i] = other.m_springStiffness[i]; + m_enableMotor[i] = other.m_enableMotor[i]; + m_servoMotor[i] = other.m_servoMotor[i]; + m_enableSpring[i] = other.m_enableSpring[i]; + m_servoTarget[i] = other.m_servoTarget[i]; + m_springStiffness[i] = other.m_springStiffness[i]; m_springStiffnessLimited[i] = other.m_springStiffnessLimited[i]; - m_springDamping[i] = other.m_springDamping[i]; - m_springDampingLimited[i] = other.m_springDampingLimited[i]; - m_equilibriumPoint[i] = other.m_equilibriumPoint[i]; - m_targetVelocity[i] = other.m_targetVelocity[i]; - m_maxMotorForce[i] = other.m_maxMotorForce[i]; + m_springDamping[i] = other.m_springDamping[i]; + m_springDampingLimited[i] = other.m_springDampingLimited[i]; + m_equilibriumPoint[i] = other.m_equilibriumPoint[i]; + m_targetVelocity[i] = other.m_targetVelocity[i]; + m_maxMotorForce[i] = other.m_maxMotorForce[i]; - m_currentLimit[i] = other.m_currentLimit[i]; + m_currentLimit[i] = other.m_currentLimit[i]; } } @@ -269,15 +264,14 @@ enum bt6DofFlags2 BT_6DOF_FLAGS_CFM_STOP2 = 1, BT_6DOF_FLAGS_ERP_STOP2 = 2, BT_6DOF_FLAGS_CFM_MOTO2 = 4, - BT_6DOF_FLAGS_ERP_MOTO2 = 8 + BT_6DOF_FLAGS_ERP_MOTO2 = 8, }; -#define BT_6DOF_FLAGS_AXIS_SHIFT2 4 // bits per axis +#define BT_6DOF_FLAGS_AXIS_SHIFT2 4 // bits per axis - -ATTRIBUTE_ALIGNED16(class) btGeneric6DofSpring2Constraint : public btTypedConstraint +ATTRIBUTE_ALIGNED16(class) +btGeneric6DofSpring2Constraint : public btTypedConstraint { protected: - btTransform m_frameInA; btTransform m_frameInB; @@ -290,45 +284,43 @@ protected: RotateOrder m_rotateOrder; protected: - - btTransform m_calculatedTransformA; - btTransform m_calculatedTransformB; - btVector3 m_calculatedAxisAngleDiff; - btVector3 m_calculatedAxis[3]; - btVector3 m_calculatedLinearDiff; - btScalar m_factA; - btScalar m_factB; - bool m_hasStaticBody; - int m_flags; - - btGeneric6DofSpring2Constraint& operator=(btGeneric6DofSpring2Constraint&) + btTransform m_calculatedTransformA; + btTransform m_calculatedTransformB; + btVector3 m_calculatedAxisAngleDiff; + btVector3 m_calculatedAxis[3]; + btVector3 m_calculatedLinearDiff; + btScalar m_factA; + btScalar m_factB; + bool m_hasStaticBody; + int m_flags; + + btGeneric6DofSpring2Constraint& operator=(btGeneric6DofSpring2Constraint&) { btAssert(0); return *this; } - int setAngularLimits(btConstraintInfo2 *info, int row_offset,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB); - int setLinearLimits(btConstraintInfo2 *info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB); + int setAngularLimits(btConstraintInfo2 * info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB); + int setLinearLimits(btConstraintInfo2 * info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB); void calculateLinearInfo(); void calculateAngleInfo(); void testAngularLimitMotor(int axis_index); - void calculateJacobi(btRotationalLimitMotor2* limot, const btTransform& transA,const btTransform& transB, btConstraintInfo2* info, int srow, btVector3& ax1, int rotational, int rotAllowed); - int get_limit_motor_info2(btRotationalLimitMotor2* limot, - const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB, - btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed = false); + void calculateJacobi(btRotationalLimitMotor2 * limot, const btTransform& transA, const btTransform& transB, btConstraintInfo2* info, int srow, btVector3& ax1, int rotational, int rotAllowed); + int get_limit_motor_info2(btRotationalLimitMotor2 * limot, + const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB, + btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed = false); public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - btGeneric6DofSpring2Constraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ); - btGeneric6DofSpring2Constraint(btRigidBody& rbB, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ); + btGeneric6DofSpring2Constraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ); + btGeneric6DofSpring2Constraint(btRigidBody & rbB, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ); virtual void buildJacobian() {} - virtual void getInfo1 (btConstraintInfo1* info); - virtual void getInfo2 (btConstraintInfo2* info); + virtual void getInfo1(btConstraintInfo1 * info); + virtual void getInfo2(btConstraintInfo2 * info); virtual int calculateSerializeBufferSize() const; virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; @@ -336,19 +328,19 @@ public: btTranslationalLimitMotor2* getTranslationalLimitMotor() { return &m_linearLimits; } // Calculates the global transform for the joint offset for body A an B, and also calculates the angle differences between the bodies. - void calculateTransforms(const btTransform& transA,const btTransform& transB); + void calculateTransforms(const btTransform& transA, const btTransform& transB); void calculateTransforms(); // Gets the global transform of the offset for body A - const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; } + const btTransform& getCalculatedTransformA() const { return m_calculatedTransformA; } // Gets the global transform of the offset for body B - const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; } + const btTransform& getCalculatedTransformB() const { return m_calculatedTransformB; } - const btTransform & getFrameOffsetA() const { return m_frameInA; } - const btTransform & getFrameOffsetB() const { return m_frameInB; } + const btTransform& getFrameOffsetA() const { return m_frameInA; } + const btTransform& getFrameOffsetB() const { return m_frameInB; } - btTransform & getFrameOffsetA() { return m_frameInA; } - btTransform & getFrameOffsetB() { return m_frameInB; } + btTransform& getFrameOffsetA() { return m_frameInA; } + btTransform& getFrameOffsetB() { return m_frameInB; } // Get the rotation axis in global coordinates ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously ) btVector3 getAxis(int axis_index) const { return m_calculatedAxis[axis_index]; } @@ -359,58 +351,58 @@ public: // Get the relative position of the constraint pivot ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously ) btScalar getRelativePivotPosition(int axis_index) const { return m_calculatedLinearDiff[axis_index]; } - void setFrames(const btTransform & frameA, const btTransform & frameB); + void setFrames(const btTransform& frameA, const btTransform& frameB); void setLinearLowerLimit(const btVector3& linearLower) { m_linearLimits.m_lowerLimit = linearLower; } - void getLinearLowerLimit(btVector3& linearLower) { linearLower = m_linearLimits.m_lowerLimit; } + void getLinearLowerLimit(btVector3 & linearLower) { linearLower = m_linearLimits.m_lowerLimit; } void setLinearUpperLimit(const btVector3& linearUpper) { m_linearLimits.m_upperLimit = linearUpper; } - void getLinearUpperLimit(btVector3& linearUpper) { linearUpper = m_linearLimits.m_upperLimit; } + void getLinearUpperLimit(btVector3 & linearUpper) { linearUpper = m_linearLimits.m_upperLimit; } void setAngularLowerLimit(const btVector3& angularLower) { - for(int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]); } void setAngularLowerLimitReversed(const btVector3& angularLower) { - for(int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) m_angularLimits[i].m_hiLimit = btNormalizeAngle(-angularLower[i]); } - void getAngularLowerLimit(btVector3& angularLower) + void getAngularLowerLimit(btVector3 & angularLower) { - for(int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) angularLower[i] = m_angularLimits[i].m_loLimit; } - void getAngularLowerLimitReversed(btVector3& angularLower) + void getAngularLowerLimitReversed(btVector3 & angularLower) { - for(int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) angularLower[i] = -m_angularLimits[i].m_hiLimit; } void setAngularUpperLimit(const btVector3& angularUpper) { - for(int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]); } void setAngularUpperLimitReversed(const btVector3& angularUpper) { - for(int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) m_angularLimits[i].m_loLimit = btNormalizeAngle(-angularUpper[i]); } - void getAngularUpperLimit(btVector3& angularUpper) + void getAngularUpperLimit(btVector3 & angularUpper) { - for(int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) angularUpper[i] = m_angularLimits[i].m_hiLimit; } - void getAngularUpperLimitReversed(btVector3& angularUpper) + void getAngularUpperLimitReversed(btVector3 & angularUpper) { - for(int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) angularUpper[i] = -m_angularLimits[i].m_loLimit; } @@ -418,7 +410,7 @@ public: void setLimit(int axis, btScalar lo, btScalar hi) { - if(axis<3) + if (axis < 3) { m_linearLimits.m_lowerLimit[axis] = lo; m_linearLimits.m_upperLimit[axis] = hi; @@ -427,14 +419,14 @@ public: { lo = btNormalizeAngle(lo); hi = btNormalizeAngle(hi); - m_angularLimits[axis-3].m_loLimit = lo; - m_angularLimits[axis-3].m_hiLimit = hi; + m_angularLimits[axis - 3].m_loLimit = lo; + m_angularLimits[axis - 3].m_hiLimit = hi; } } void setLimitReversed(int axis, btScalar lo, btScalar hi) { - if(axis<3) + if (axis < 3) { m_linearLimits.m_lowerLimit[axis] = lo; m_linearLimits.m_upperLimit[axis] = hi; @@ -443,54 +435,53 @@ public: { lo = btNormalizeAngle(lo); hi = btNormalizeAngle(hi); - m_angularLimits[axis-3].m_hiLimit = -lo; - m_angularLimits[axis-3].m_loLimit = -hi; + m_angularLimits[axis - 3].m_hiLimit = -lo; + m_angularLimits[axis - 3].m_loLimit = -hi; } } bool isLimited(int limitIndex) { - if(limitIndex<3) + if (limitIndex < 3) { return m_linearLimits.isLimited(limitIndex); } - return m_angularLimits[limitIndex-3].isLimited(); + return m_angularLimits[limitIndex - 3].isLimited(); } void setRotationOrder(RotateOrder order) { m_rotateOrder = order; } RotateOrder getRotationOrder() { return m_rotateOrder; } - void setAxis( const btVector3& axis1, const btVector3& axis2); + void setAxis(const btVector3& axis1, const btVector3& axis2); void setBounce(int index, btScalar bounce); void enableMotor(int index, bool onOff); - void setServo(int index, bool onOff); // set the type of the motor (servo or not) (the motor has to be turned on for servo also) + void setServo(int index, bool onOff); // set the type of the motor (servo or not) (the motor has to be turned on for servo also) void setTargetVelocity(int index, btScalar velocity); void setServoTarget(int index, btScalar target); void setMaxMotorForce(int index, btScalar force); void enableSpring(int index, bool onOff); - void setStiffness(int index, btScalar stiffness, bool limitIfNeeded = true); // if limitIfNeeded is true the system will automatically limit the stiffness in necessary situations where otherwise the spring would move unrealistically too widely - void setDamping(int index, btScalar damping, bool limitIfNeeded = true); // if limitIfNeeded is true the system will automatically limit the damping in necessary situations where otherwise the spring would blow up - void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF - void setEquilibriumPoint(int index); // set the current constraint position/orientation as an equilibrium point for given DOF + void setStiffness(int index, btScalar stiffness, bool limitIfNeeded = true); // if limitIfNeeded is true the system will automatically limit the stiffness in necessary situations where otherwise the spring would move unrealistically too widely + void setDamping(int index, btScalar damping, bool limitIfNeeded = true); // if limitIfNeeded is true the system will automatically limit the damping in necessary situations where otherwise the spring would blow up + void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF + void setEquilibriumPoint(int index); // set the current constraint position/orientation as an equilibrium point for given DOF void setEquilibriumPoint(int index, btScalar val); - //override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + //override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). //If no axis is provided, it uses the default axis for this constraint. virtual void setParam(int num, btScalar value, int axis = -1); virtual btScalar getParam(int num, int axis = -1) const; - - static btScalar btGetMatrixElem(const btMatrix3x3& mat, int index); - static bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz); - static bool matrixToEulerXZY(const btMatrix3x3& mat,btVector3& xyz); - static bool matrixToEulerYXZ(const btMatrix3x3& mat,btVector3& xyz); - static bool matrixToEulerYZX(const btMatrix3x3& mat,btVector3& xyz); - static bool matrixToEulerZXY(const btMatrix3x3& mat,btVector3& xyz); - static bool matrixToEulerZYX(const btMatrix3x3& mat,btVector3& xyz); -}; + static btScalar btGetMatrixElem(const btMatrix3x3& mat, int index); + static bool matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz); + static bool matrixToEulerXZY(const btMatrix3x3& mat, btVector3& xyz); + static bool matrixToEulerYXZ(const btMatrix3x3& mat, btVector3& xyz); + static bool matrixToEulerYZX(const btMatrix3x3& mat, btVector3& xyz); + static bool matrixToEulerZXY(const btMatrix3x3& mat, btVector3& xyz); + static bool matrixToEulerZYX(const btMatrix3x3& mat, btVector3& xyz); +}; struct btGeneric6DofSpring2ConstraintData { @@ -511,12 +502,12 @@ struct btGeneric6DofSpring2ConstraintData btVector3FloatData m_linearSpringStiffness; btVector3FloatData m_linearSpringDamping; btVector3FloatData m_linearEquilibriumPoint; - char m_linearEnableMotor[4]; - char m_linearServoMotor[4]; - char m_linearEnableSpring[4]; - char m_linearSpringStiffnessLimited[4]; - char m_linearSpringDampingLimited[4]; - char m_padding1[4]; + char m_linearEnableMotor[4]; + char m_linearServoMotor[4]; + char m_linearEnableSpring[4]; + char m_linearSpringStiffnessLimited[4]; + char m_linearSpringDampingLimited[4]; + char m_padding1[4]; btVector3FloatData m_angularUpperLimit; btVector3FloatData m_angularLowerLimit; @@ -531,13 +522,13 @@ struct btGeneric6DofSpring2ConstraintData btVector3FloatData m_angularSpringStiffness; btVector3FloatData m_angularSpringDamping; btVector3FloatData m_angularEquilibriumPoint; - char m_angularEnableMotor[4]; - char m_angularServoMotor[4]; - char m_angularEnableSpring[4]; - char m_angularSpringStiffnessLimited[4]; - char m_angularSpringDampingLimited[4]; + char m_angularEnableMotor[4]; + char m_angularServoMotor[4]; + char m_angularEnableSpring[4]; + char m_angularSpringStiffnessLimited[4]; + char m_angularSpringDampingLimited[4]; - int m_rotateOrder; + int m_rotateOrder; }; struct btGeneric6DofSpring2ConstraintDoubleData2 @@ -559,12 +550,12 @@ struct btGeneric6DofSpring2ConstraintDoubleData2 btVector3DoubleData m_linearSpringStiffness; btVector3DoubleData m_linearSpringDamping; btVector3DoubleData m_linearEquilibriumPoint; - char m_linearEnableMotor[4]; - char m_linearServoMotor[4]; - char m_linearEnableSpring[4]; - char m_linearSpringStiffnessLimited[4]; - char m_linearSpringDampingLimited[4]; - char m_padding1[4]; + char m_linearEnableMotor[4]; + char m_linearServoMotor[4]; + char m_linearEnableSpring[4]; + char m_linearSpringStiffnessLimited[4]; + char m_linearSpringDampingLimited[4]; + char m_padding1[4]; btVector3DoubleData m_angularUpperLimit; btVector3DoubleData m_angularLowerLimit; @@ -579,13 +570,13 @@ struct btGeneric6DofSpring2ConstraintDoubleData2 btVector3DoubleData m_angularSpringStiffness; btVector3DoubleData m_angularSpringDamping; btVector3DoubleData m_angularEquilibriumPoint; - char m_angularEnableMotor[4]; - char m_angularServoMotor[4]; - char m_angularEnableSpring[4]; - char m_angularSpringStiffnessLimited[4]; - char m_angularSpringDampingLimited[4]; + char m_angularEnableMotor[4]; + char m_angularServoMotor[4]; + char m_angularEnableSpring[4]; + char m_angularSpringStiffnessLimited[4]; + char m_angularSpringDampingLimited[4]; - int m_rotateOrder; + int m_rotateOrder; }; SIMD_FORCE_INLINE int btGeneric6DofSpring2Constraint::calculateSerializeBufferSize() const @@ -596,70 +587,70 @@ SIMD_FORCE_INLINE int btGeneric6DofSpring2Constraint::calculateSerializeBufferSi SIMD_FORCE_INLINE const char* btGeneric6DofSpring2Constraint::serialize(void* dataBuffer, btSerializer* serializer) const { btGeneric6DofSpring2ConstraintData2* dof = (btGeneric6DofSpring2ConstraintData2*)dataBuffer; - btTypedConstraint::serialize(&dof->m_typeConstraintData,serializer); + btTypedConstraint::serialize(&dof->m_typeConstraintData, serializer); m_frameInA.serialize(dof->m_rbAFrame); m_frameInB.serialize(dof->m_rbBFrame); int i; - for (i=0;i<3;i++) + for (i = 0; i < 3; i++) { - dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit; - dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit; - dof->m_angularBounce.m_floats[i] = m_angularLimits[i].m_bounce; - dof->m_angularStopERP.m_floats[i] = m_angularLimits[i].m_stopERP; - dof->m_angularStopCFM.m_floats[i] = m_angularLimits[i].m_stopCFM; - dof->m_angularMotorERP.m_floats[i] = m_angularLimits[i].m_motorERP; - dof->m_angularMotorCFM.m_floats[i] = m_angularLimits[i].m_motorCFM; - dof->m_angularTargetVelocity.m_floats[i] = m_angularLimits[i].m_targetVelocity; - dof->m_angularMaxMotorForce.m_floats[i] = m_angularLimits[i].m_maxMotorForce; - dof->m_angularServoTarget.m_floats[i] = m_angularLimits[i].m_servoTarget; - dof->m_angularSpringStiffness.m_floats[i] = m_angularLimits[i].m_springStiffness; - dof->m_angularSpringDamping.m_floats[i] = m_angularLimits[i].m_springDamping; + dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit; + dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit; + dof->m_angularBounce.m_floats[i] = m_angularLimits[i].m_bounce; + dof->m_angularStopERP.m_floats[i] = m_angularLimits[i].m_stopERP; + dof->m_angularStopCFM.m_floats[i] = m_angularLimits[i].m_stopCFM; + dof->m_angularMotorERP.m_floats[i] = m_angularLimits[i].m_motorERP; + dof->m_angularMotorCFM.m_floats[i] = m_angularLimits[i].m_motorCFM; + dof->m_angularTargetVelocity.m_floats[i] = m_angularLimits[i].m_targetVelocity; + dof->m_angularMaxMotorForce.m_floats[i] = m_angularLimits[i].m_maxMotorForce; + dof->m_angularServoTarget.m_floats[i] = m_angularLimits[i].m_servoTarget; + dof->m_angularSpringStiffness.m_floats[i] = m_angularLimits[i].m_springStiffness; + dof->m_angularSpringDamping.m_floats[i] = m_angularLimits[i].m_springDamping; dof->m_angularEquilibriumPoint.m_floats[i] = m_angularLimits[i].m_equilibriumPoint; } - dof->m_angularLowerLimit.m_floats[3] = 0; - dof->m_angularUpperLimit.m_floats[3] = 0; - dof->m_angularBounce.m_floats[3] = 0; - dof->m_angularStopERP.m_floats[3] = 0; - dof->m_angularStopCFM.m_floats[3] = 0; - dof->m_angularMotorERP.m_floats[3] = 0; - dof->m_angularMotorCFM.m_floats[3] = 0; - dof->m_angularTargetVelocity.m_floats[3] = 0; - dof->m_angularMaxMotorForce.m_floats[3] = 0; - dof->m_angularServoTarget.m_floats[3] = 0; - dof->m_angularSpringStiffness.m_floats[3] = 0; - dof->m_angularSpringDamping.m_floats[3] = 0; + dof->m_angularLowerLimit.m_floats[3] = 0; + dof->m_angularUpperLimit.m_floats[3] = 0; + dof->m_angularBounce.m_floats[3] = 0; + dof->m_angularStopERP.m_floats[3] = 0; + dof->m_angularStopCFM.m_floats[3] = 0; + dof->m_angularMotorERP.m_floats[3] = 0; + dof->m_angularMotorCFM.m_floats[3] = 0; + dof->m_angularTargetVelocity.m_floats[3] = 0; + dof->m_angularMaxMotorForce.m_floats[3] = 0; + dof->m_angularServoTarget.m_floats[3] = 0; + dof->m_angularSpringStiffness.m_floats[3] = 0; + dof->m_angularSpringDamping.m_floats[3] = 0; dof->m_angularEquilibriumPoint.m_floats[3] = 0; - for (i=0;i<4;i++) + for (i = 0; i < 4; i++) { - dof->m_angularEnableMotor[i] = i < 3 ? ( m_angularLimits[i].m_enableMotor ? 1 : 0 ) : 0; - dof->m_angularServoMotor[i] = i < 3 ? ( m_angularLimits[i].m_servoMotor ? 1 : 0 ) : 0; - dof->m_angularEnableSpring[i] = i < 3 ? ( m_angularLimits[i].m_enableSpring ? 1 : 0 ) : 0; - dof->m_angularSpringStiffnessLimited[i] = i < 3 ? ( m_angularLimits[i].m_springStiffnessLimited ? 1 : 0 ) : 0; - dof->m_angularSpringDampingLimited[i] = i < 3 ? ( m_angularLimits[i].m_springDampingLimited ? 1 : 0 ) : 0; + dof->m_angularEnableMotor[i] = i < 3 ? (m_angularLimits[i].m_enableMotor ? 1 : 0) : 0; + dof->m_angularServoMotor[i] = i < 3 ? (m_angularLimits[i].m_servoMotor ? 1 : 0) : 0; + dof->m_angularEnableSpring[i] = i < 3 ? (m_angularLimits[i].m_enableSpring ? 1 : 0) : 0; + dof->m_angularSpringStiffnessLimited[i] = i < 3 ? (m_angularLimits[i].m_springStiffnessLimited ? 1 : 0) : 0; + dof->m_angularSpringDampingLimited[i] = i < 3 ? (m_angularLimits[i].m_springDampingLimited ? 1 : 0) : 0; } - m_linearLimits.m_lowerLimit.serialize( dof->m_linearLowerLimit ); - m_linearLimits.m_upperLimit.serialize( dof->m_linearUpperLimit ); - m_linearLimits.m_bounce.serialize( dof->m_linearBounce ); - m_linearLimits.m_stopERP.serialize( dof->m_linearStopERP ); - m_linearLimits.m_stopCFM.serialize( dof->m_linearStopCFM ); - m_linearLimits.m_motorERP.serialize( dof->m_linearMotorERP ); - m_linearLimits.m_motorCFM.serialize( dof->m_linearMotorCFM ); - m_linearLimits.m_targetVelocity.serialize( dof->m_linearTargetVelocity ); - m_linearLimits.m_maxMotorForce.serialize( dof->m_linearMaxMotorForce ); - m_linearLimits.m_servoTarget.serialize( dof->m_linearServoTarget ); - m_linearLimits.m_springStiffness.serialize( dof->m_linearSpringStiffness ); - m_linearLimits.m_springDamping.serialize( dof->m_linearSpringDamping ); - m_linearLimits.m_equilibriumPoint.serialize( dof->m_linearEquilibriumPoint ); - for (i=0;i<4;i++) + m_linearLimits.m_lowerLimit.serialize(dof->m_linearLowerLimit); + m_linearLimits.m_upperLimit.serialize(dof->m_linearUpperLimit); + m_linearLimits.m_bounce.serialize(dof->m_linearBounce); + m_linearLimits.m_stopERP.serialize(dof->m_linearStopERP); + m_linearLimits.m_stopCFM.serialize(dof->m_linearStopCFM); + m_linearLimits.m_motorERP.serialize(dof->m_linearMotorERP); + m_linearLimits.m_motorCFM.serialize(dof->m_linearMotorCFM); + m_linearLimits.m_targetVelocity.serialize(dof->m_linearTargetVelocity); + m_linearLimits.m_maxMotorForce.serialize(dof->m_linearMaxMotorForce); + m_linearLimits.m_servoTarget.serialize(dof->m_linearServoTarget); + m_linearLimits.m_springStiffness.serialize(dof->m_linearSpringStiffness); + m_linearLimits.m_springDamping.serialize(dof->m_linearSpringDamping); + m_linearLimits.m_equilibriumPoint.serialize(dof->m_linearEquilibriumPoint); + for (i = 0; i < 4; i++) { - dof->m_linearEnableMotor[i] = i < 3 ? ( m_linearLimits.m_enableMotor[i] ? 1 : 0 ) : 0; - dof->m_linearServoMotor[i] = i < 3 ? ( m_linearLimits.m_servoMotor[i] ? 1 : 0 ) : 0; - dof->m_linearEnableSpring[i] = i < 3 ? ( m_linearLimits.m_enableSpring[i] ? 1 : 0 ) : 0; - dof->m_linearSpringStiffnessLimited[i] = i < 3 ? ( m_linearLimits.m_springStiffnessLimited[i] ? 1 : 0 ) : 0; - dof->m_linearSpringDampingLimited[i] = i < 3 ? ( m_linearLimits.m_springDampingLimited[i] ? 1 : 0 ) : 0; + dof->m_linearEnableMotor[i] = i < 3 ? (m_linearLimits.m_enableMotor[i] ? 1 : 0) : 0; + dof->m_linearServoMotor[i] = i < 3 ? (m_linearLimits.m_servoMotor[i] ? 1 : 0) : 0; + dof->m_linearEnableSpring[i] = i < 3 ? (m_linearLimits.m_enableSpring[i] ? 1 : 0) : 0; + dof->m_linearSpringStiffnessLimited[i] = i < 3 ? (m_linearLimits.m_springStiffnessLimited[i] ? 1 : 0) : 0; + dof->m_linearSpringDampingLimited[i] = i < 3 ? (m_linearLimits.m_springDampingLimited[i] ? 1 : 0) : 0; } dof->m_rotateOrder = m_rotateOrder; @@ -672,8 +663,4 @@ SIMD_FORCE_INLINE const char* btGeneric6DofSpring2Constraint::serialize(void* da return btGeneric6DofSpring2ConstraintDataName; } - - - - -#endif //BT_GENERIC_6DOF_CONSTRAINT_H +#endif //BT_GENERIC_6DOF_CONSTRAINT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp index 3f875989ea..8baf52bcd1 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp @@ -17,26 +17,23 @@ subject to the following restrictions: #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" - -btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA) +btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) : btGeneric6DofConstraint(rbA, rbB, frameInA, frameInB, useLinearReferenceFrameA) { - init(); + init(); } - btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB) - : btGeneric6DofConstraint(rbB, frameInB, useLinearReferenceFrameB) + : btGeneric6DofConstraint(rbB, frameInB, useLinearReferenceFrameB) { - init(); + init(); } - void btGeneric6DofSpringConstraint::init() { m_objectType = D6_SPRING_CONSTRAINT_TYPE; - for(int i = 0; i < 6; i++) + for (int i = 0; i < 6; i++) { m_springEnabled[i] = false; m_equilibriumPoint[i] = btScalar(0.f); @@ -45,12 +42,11 @@ void btGeneric6DofSpringConstraint::init() } } - void btGeneric6DofSpringConstraint::enableSpring(int index, bool onOff) { btAssert((index >= 0) && (index < 6)); m_springEnabled[index] = onOff; - if(index < 3) + if (index < 3) { m_linearLimits.m_enableMotor[index] = onOff; } @@ -60,44 +56,38 @@ void btGeneric6DofSpringConstraint::enableSpring(int index, bool onOff) } } - - void btGeneric6DofSpringConstraint::setStiffness(int index, btScalar stiffness) { btAssert((index >= 0) && (index < 6)); m_springStiffness[index] = stiffness; } - void btGeneric6DofSpringConstraint::setDamping(int index, btScalar damping) { btAssert((index >= 0) && (index < 6)); m_springDamping[index] = damping; } - void btGeneric6DofSpringConstraint::setEquilibriumPoint() { calculateTransforms(); int i; - for( i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { m_equilibriumPoint[i] = m_calculatedLinearDiff[i]; } - for(i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { m_equilibriumPoint[i + 3] = m_calculatedAxisAngleDiff[i]; } } - - void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index) { btAssert((index >= 0) && (index < 6)); calculateTransforms(); - if(index < 3) + if (index < 3) { m_equilibriumPoint[index] = m_calculatedLinearDiff[index]; } @@ -113,15 +103,14 @@ void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index, btScalar val) m_equilibriumPoint[index] = val; } - void btGeneric6DofSpringConstraint::internalUpdateSprings(btConstraintInfo2* info) { // it is assumed that calculateTransforms() have been called before this call int i; //btVector3 relVel = m_rbB.getLinearVelocity() - m_rbA.getLinearVelocity(); - for(i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { - if(m_springEnabled[i]) + if (m_springEnabled[i]) { // get current position of constraint btScalar currPos = m_calculatedLinearDiff[i]; @@ -130,28 +119,27 @@ void btGeneric6DofSpringConstraint::internalUpdateSprings(btConstraintInfo2* inf // spring force is (delta * m_stiffness) according to Hooke's Law btScalar force = delta * m_springStiffness[i]; btScalar velFactor = info->fps * m_springDamping[i] / btScalar(info->m_numIterations); - m_linearLimits.m_targetVelocity[i] = velFactor * force; - m_linearLimits.m_maxMotorForce[i] = btFabs(force); + m_linearLimits.m_targetVelocity[i] = velFactor * force; + m_linearLimits.m_maxMotorForce[i] = btFabs(force); } } - for(i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { - if(m_springEnabled[i + 3]) + if (m_springEnabled[i + 3]) { // get current position of constraint btScalar currPos = m_calculatedAxisAngleDiff[i]; // calculate difference - btScalar delta = currPos - m_equilibriumPoint[i+3]; + btScalar delta = currPos - m_equilibriumPoint[i + 3]; // spring force is (-delta * m_stiffness) according to Hooke's Law - btScalar force = -delta * m_springStiffness[i+3]; - btScalar velFactor = info->fps * m_springDamping[i+3] / btScalar(info->m_numIterations); + btScalar force = -delta * m_springStiffness[i + 3]; + btScalar velFactor = info->fps * m_springDamping[i + 3] / btScalar(info->m_numIterations); m_angularLimits[i].m_targetVelocity = velFactor * force; m_angularLimits[i].m_maxMotorForce = btFabs(force); } } } - void btGeneric6DofSpringConstraint::getInfo2(btConstraintInfo2* info) { // this will be called by constraint solver at the constraint setup stage @@ -161,25 +149,21 @@ void btGeneric6DofSpringConstraint::getInfo2(btConstraintInfo2* info) btGeneric6DofConstraint::getInfo2(info); } - -void btGeneric6DofSpringConstraint::setAxis(const btVector3& axis1,const btVector3& axis2) +void btGeneric6DofSpringConstraint::setAxis(const btVector3& axis1, const btVector3& axis2) { btVector3 zAxis = axis1.normalized(); btVector3 yAxis = axis2.normalized(); - btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system + btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system btTransform frameInW; frameInW.setIdentity(); - frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], - xAxis[1], yAxis[1], zAxis[1], - xAxis[2], yAxis[2], zAxis[2]); + frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); // now get constraint frame in local coordinate systems m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW; m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW; - calculateTransforms(); + calculateTransforms(); } - - - diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h index dac59c6889..02b9d4d05d 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h @@ -16,20 +16,17 @@ subject to the following restrictions: #ifndef BT_GENERIC_6DOF_SPRING_CONSTRAINT_H #define BT_GENERIC_6DOF_SPRING_CONSTRAINT_H - #include "LinearMath/btVector3.h" #include "btTypedConstraint.h" #include "btGeneric6DofConstraint.h" #ifdef BT_USE_DOUBLE_PRECISION -#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintDoubleData2 -#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintDoubleData2" +#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintDoubleData2 +#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintDoubleData2" #else -#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintData -#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintData" -#endif //BT_USE_DOUBLE_PRECISION - - +#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintData +#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintData" +#endif //BT_USE_DOUBLE_PRECISION /// Generic 6 DOF constraint that allows to set spring motors to any translational and rotational DOF @@ -41,101 +38,98 @@ subject to the following restrictions: /// 4 : rotation Y (2nd Euler rotational around new position of Y axis, range [-PI/2+epsilon, PI/2-epsilon] ) /// 5 : rotation Z (1st Euler rotational around Z axis, range [-PI+epsilon, PI-epsilon] ) -ATTRIBUTE_ALIGNED16(class) btGeneric6DofSpringConstraint : public btGeneric6DofConstraint +ATTRIBUTE_ALIGNED16(class) +btGeneric6DofSpringConstraint : public btGeneric6DofConstraint { protected: - bool m_springEnabled[6]; - btScalar m_equilibriumPoint[6]; - btScalar m_springStiffness[6]; - btScalar m_springDamping[6]; // between 0 and 1 (1 == no damping) + bool m_springEnabled[6]; + btScalar m_equilibriumPoint[6]; + btScalar m_springStiffness[6]; + btScalar m_springDamping[6]; // between 0 and 1 (1 == no damping) void init(); - void internalUpdateSprings(btConstraintInfo2* info); -public: - + void internalUpdateSprings(btConstraintInfo2 * info); + +public: BT_DECLARE_ALIGNED_ALLOCATOR(); - - btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); - btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB); + + btGeneric6DofSpringConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA); + btGeneric6DofSpringConstraint(btRigidBody & rbB, const btTransform& frameInB, bool useLinearReferenceFrameB); void enableSpring(int index, bool onOff); void setStiffness(int index, btScalar stiffness); void setDamping(int index, btScalar damping); - void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF + void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF void setEquilibriumPoint(int index); // set the current constraint position/orientation as an equilibrium point for given DOF void setEquilibriumPoint(int index, btScalar val); bool isSpringEnabled(int index) const { - return m_springEnabled[index]; + return m_springEnabled[index]; } btScalar getStiffness(int index) const { - return m_springStiffness[index]; + return m_springStiffness[index]; } btScalar getDamping(int index) const { - return m_springDamping[index]; + return m_springDamping[index]; } btScalar getEquilibriumPoint(int index) const { - return m_equilibriumPoint[index]; + return m_equilibriumPoint[index]; } - virtual void setAxis( const btVector3& axis1, const btVector3& axis2); + virtual void setAxis(const btVector3& axis1, const btVector3& axis2); - virtual void getInfo2 (btConstraintInfo2* info); + virtual void getInfo2(btConstraintInfo2 * info); - virtual int calculateSerializeBufferSize() const; + virtual int calculateSerializeBufferSize() const; ///fills the dataBuffer and returns the struct name (and 0 on failure) - virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; - + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; }; - struct btGeneric6DofSpringConstraintData { - btGeneric6DofConstraintData m_6dofData; - - int m_springEnabled[6]; - float m_equilibriumPoint[6]; - float m_springStiffness[6]; - float m_springDamping[6]; + btGeneric6DofConstraintData m_6dofData; + + int m_springEnabled[6]; + float m_equilibriumPoint[6]; + float m_springStiffness[6]; + float m_springDamping[6]; }; struct btGeneric6DofSpringConstraintDoubleData2 { - btGeneric6DofConstraintDoubleData2 m_6dofData; - - int m_springEnabled[6]; - double m_equilibriumPoint[6]; - double m_springStiffness[6]; - double m_springDamping[6]; -}; + btGeneric6DofConstraintDoubleData2 m_6dofData; + int m_springEnabled[6]; + double m_equilibriumPoint[6]; + double m_springStiffness[6]; + double m_springDamping[6]; +}; -SIMD_FORCE_INLINE int btGeneric6DofSpringConstraint::calculateSerializeBufferSize() const +SIMD_FORCE_INLINE int btGeneric6DofSpringConstraint::calculateSerializeBufferSize() const { return sizeof(btGeneric6DofSpringConstraintData2); } - ///fills the dataBuffer and returns the struct name (and 0 on failure) -SIMD_FORCE_INLINE const char* btGeneric6DofSpringConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btGeneric6DofSpringConstraint::serialize(void* dataBuffer, btSerializer* serializer) const { btGeneric6DofSpringConstraintData2* dof = (btGeneric6DofSpringConstraintData2*)dataBuffer; - btGeneric6DofConstraint::serialize(&dof->m_6dofData,serializer); + btGeneric6DofConstraint::serialize(&dof->m_6dofData, serializer); int i; - for (i=0;i<6;i++) + for (i = 0; i < 6; i++) { dof->m_equilibriumPoint[i] = m_equilibriumPoint[i]; dof->m_springDamping[i] = m_springDamping[i]; - dof->m_springEnabled[i] = m_springEnabled[i]? 1 : 0; + dof->m_springEnabled[i] = m_springEnabled[i] ? 1 : 0; dof->m_springStiffness[i] = m_springStiffness[i]; } return btGeneric6DofSpringConstraintDataName; } -#endif // BT_GENERIC_6DOF_SPRING_CONSTRAINT_H - +#endif // BT_GENERIC_6DOF_SPRING_CONSTRAINT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp index 4be2aabe4d..6507e1a0a7 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp @@ -13,54 +13,49 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ - - #include "btHinge2Constraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" - - // constructor // anchor, axis1 and axis2 are in world coordinate system // axis1 must be orthogonal to axis2 btHinge2Constraint::btHinge2Constraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2) -: btGeneric6DofSpring2Constraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(),RO_XYZ), - m_anchor(anchor), - m_axis1(axis1), - m_axis2(axis2) + : btGeneric6DofSpring2Constraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), RO_XYZ), + m_anchor(anchor), + m_axis1(axis1), + m_axis2(axis2) { // build frame basis // 6DOF constraint uses Euler angles and to define limits // it is assumed that rotational order is : // Z - first, allowed limits are (-PI,PI); - // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number + // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number // used to prevent constraint from instability on poles; // new position of X, allowed limits are (-PI,PI); // So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs // Build the frame in world coordinate system first btVector3 zAxis = axis1.normalize(); btVector3 xAxis = axis2.normalize(); - btVector3 yAxis = zAxis.cross(xAxis); // we want right coordinate system + btVector3 yAxis = zAxis.cross(xAxis); // we want right coordinate system btTransform frameInW; frameInW.setIdentity(); - frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], - xAxis[1], yAxis[1], zAxis[1], - xAxis[2], yAxis[2], zAxis[2]); + frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); frameInW.setOrigin(anchor); // now get constraint frame in local coordinate systems m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW; m_frameInB = rbB.getCenterOfMassTransform().inverse() * frameInW; // sei limits setLinearLowerLimit(btVector3(0.f, 0.f, -1.f)); - setLinearUpperLimit(btVector3(0.f, 0.f, 1.f)); + setLinearUpperLimit(btVector3(0.f, 0.f, 1.f)); // like front wheels of a car - setAngularLowerLimit(btVector3(1.f, 0.f, -SIMD_HALF_PI * 0.5f)); - setAngularUpperLimit(btVector3(-1.f, 0.f, SIMD_HALF_PI * 0.5f)); + setAngularLowerLimit(btVector3(1.f, 0.f, -SIMD_HALF_PI * 0.5f)); + setAngularUpperLimit(btVector3(-1.f, 0.f, SIMD_HALF_PI * 0.5f)); // enable suspension enableSpring(2, true); setStiffness(2, SIMD_PI * SIMD_PI * 4.f); setDamping(2, 0.01f); setEquilibriumPoint(); } - diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h index 06a8e3ecd1..95f604a890 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h @@ -16,32 +16,30 @@ subject to the following restrictions: #ifndef BT_HINGE2_CONSTRAINT_H #define BT_HINGE2_CONSTRAINT_H - - #include "LinearMath/btVector3.h" #include "btTypedConstraint.h" #include "btGeneric6DofSpring2Constraint.h" - - // Constraint similar to ODE Hinge2 Joint // has 3 degrees of frredom: // 2 rotational degrees of freedom, similar to Euler rotations around Z (axis 1) and X (axis 2) // 1 translational (along axis Z) with suspension spring -ATTRIBUTE_ALIGNED16(class) btHinge2Constraint : public btGeneric6DofSpring2Constraint +ATTRIBUTE_ALIGNED16(class) +btHinge2Constraint : public btGeneric6DofSpring2Constraint { protected: - btVector3 m_anchor; - btVector3 m_axis1; - btVector3 m_axis2; + btVector3 m_anchor; + btVector3 m_axis1; + btVector3 m_axis2; + public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - + BT_DECLARE_ALIGNED_ALLOCATOR(); + // constructor // anchor, axis1 and axis2 are in world coordinate system // axis1 must be orthogonal to axis2 - btHinge2Constraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2); + btHinge2Constraint(btRigidBody & rbA, btRigidBody & rbB, btVector3 & anchor, btVector3 & axis1, btVector3 & axis2); // access const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); } const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); } @@ -51,10 +49,7 @@ public: btScalar getAngle2() { return getAngle(0); } // limits void setUpperLimit(btScalar ang1max) { setAngularUpperLimit(btVector3(-1.f, 0.f, ang1max)); } - void setLowerLimit(btScalar ang1min) { setAngularLowerLimit(btVector3( 1.f, 0.f, ang1min)); } + void setLowerLimit(btScalar ang1min) { setAngularLowerLimit(btVector3(1.f, 0.f, ang1min)); } }; - - -#endif // BT_HINGE2_CONSTRAINT_H - +#endif // BT_HINGE2_CONSTRAINT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp index 7e5e6f9e54..aa6f69000d 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp @@ -13,7 +13,6 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ - #include "btHingeConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" @@ -21,8 +20,6 @@ subject to the following restrictions: #include <new> #include "btSolverBody.h" - - //#define HINGE_USE_OBSOLETE_SOLVER false #define HINGE_USE_OBSOLETE_SOLVER false @@ -30,59 +27,60 @@ subject to the following restrictions: #ifndef __SPU__ - - - - -btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, - const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA) - :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB), +btHingeConstraint::btHingeConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& pivotInA, const btVector3& pivotInB, + const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA) + : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA, rbB), #ifdef _BT_USE_CENTER_LIMIT_ - m_limit(), + m_limit(), #endif - m_angularOnly(false), - m_enableAngularMotor(false), - m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), - m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), - m_useReferenceFrameA(useReferenceFrameA), - m_flags(0), - m_normalCFM(0), - m_normalERP(0), - m_stopCFM(0), - m_stopERP(0) + m_angularOnly(false), + m_enableAngularMotor(false), + m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), + m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), + m_useReferenceFrameA(useReferenceFrameA), + m_flags(0), + m_normalCFM(0), + m_normalERP(0), + m_stopCFM(0), + m_stopERP(0) { m_rbAFrame.getOrigin() = pivotInA; - + // since no frame is given, assume this to be zero angle and just pick rb transform axis btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0); btVector3 rbAxisA2; btScalar projection = axisInA.dot(rbAxisA1); - if (projection >= 1.0f - SIMD_EPSILON) { + if (projection >= 1.0f - SIMD_EPSILON) + { rbAxisA1 = -rbA.getCenterOfMassTransform().getBasis().getColumn(2); rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); - } else if (projection <= -1.0f + SIMD_EPSILON) { + } + else if (projection <= -1.0f + SIMD_EPSILON) + { rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(2); - rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); - } else { + rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); + } + else + { rbAxisA2 = axisInA.cross(rbAxisA1); rbAxisA1 = rbAxisA2.cross(axisInA); } - m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), - rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), - rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + m_rbAFrame.getBasis().setValue(rbAxisA1.getX(), rbAxisA2.getX(), axisInA.getX(), + rbAxisA1.getY(), rbAxisA2.getY(), axisInA.getY(), + rbAxisA1.getZ(), rbAxisA2.getZ(), axisInA.getZ()); + + btQuaternion rotationArc = shortestArcQuat(axisInA, axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc, rbAxisA1); + btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); - btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); - btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); - btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); - m_rbBFrame.getOrigin() = pivotInB; - m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), - rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), - rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); - -#ifndef _BT_USE_CENTER_LIMIT_ + m_rbBFrame.getBasis().setValue(rbAxisB1.getX(), rbAxisB2.getX(), axisInB.getX(), + rbAxisB1.getY(), rbAxisB2.getY(), axisInB.getY(), + rbAxisB1.getZ(), rbAxisB2.getZ(), axisInB.getZ()); + +#ifndef _BT_USE_CENTER_LIMIT_ //start with free m_lowerLimit = btScalar(1.0f); m_upperLimit = btScalar(-1.0f); @@ -94,47 +92,44 @@ btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const bt m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); } - - -btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA) -:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), +btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA) + : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), #ifdef _BT_USE_CENTER_LIMIT_ -m_limit(), + m_limit(), #endif -m_angularOnly(false), m_enableAngularMotor(false), -m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), -m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), -m_useReferenceFrameA(useReferenceFrameA), -m_flags(0), -m_normalCFM(0), -m_normalERP(0), -m_stopCFM(0), -m_stopERP(0) + m_angularOnly(false), + m_enableAngularMotor(false), + m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), + m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), + m_useReferenceFrameA(useReferenceFrameA), + m_flags(0), + m_normalCFM(0), + m_normalERP(0), + m_stopCFM(0), + m_stopERP(0) { - // since no frame is given, assume this to be zero angle and just pick rb transform axis // fixed axis in worldspace btVector3 rbAxisA1, rbAxisA2; btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2); m_rbAFrame.getOrigin() = pivotInA; - m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), - rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), - rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + m_rbAFrame.getBasis().setValue(rbAxisA1.getX(), rbAxisA2.getX(), axisInA.getX(), + rbAxisA1.getY(), rbAxisA2.getY(), axisInA.getY(), + rbAxisA1.getZ(), rbAxisA2.getZ(), axisInA.getZ()); btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * axisInA; - btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); - btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); + btQuaternion rotationArc = shortestArcQuat(axisInA, axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc, rbAxisA1); btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); - m_rbBFrame.getOrigin() = rbA.getCenterOfMassTransform()(pivotInA); - m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), - rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), - rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); - -#ifndef _BT_USE_CENTER_LIMIT_ + m_rbBFrame.getBasis().setValue(rbAxisB1.getX(), rbAxisB2.getX(), axisInB.getX(), + rbAxisB1.getY(), rbAxisB2.getY(), axisInB.getY(), + rbAxisB1.getZ(), rbAxisB2.getZ(), axisInB.getZ()); + +#ifndef _BT_USE_CENTER_LIMIT_ //start with free m_lowerLimit = btScalar(1.0f); m_upperLimit = btScalar(-1.0f); @@ -146,26 +141,24 @@ m_stopERP(0) m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); } - - -btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, - const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA) -:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), +btHingeConstraint::btHingeConstraint(btRigidBody& rbA, btRigidBody& rbB, + const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA) + : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA, rbB), m_rbAFrame(rbAFrame), m_rbBFrame(rbBFrame), #ifdef _BT_USE_CENTER_LIMIT_ -m_limit(), + m_limit(), #endif -m_angularOnly(false), -m_enableAngularMotor(false), -m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), -m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), -m_useReferenceFrameA(useReferenceFrameA), -m_flags(0), -m_normalCFM(0), -m_normalERP(0), -m_stopCFM(0), -m_stopERP(0) + m_angularOnly(false), + m_enableAngularMotor(false), + m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), + m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), + m_useReferenceFrameA(useReferenceFrameA), + m_flags(0), + m_normalCFM(0), + m_normalERP(0), + m_stopCFM(0), + m_stopERP(0) { -#ifndef _BT_USE_CENTER_LIMIT_ +#ifndef _BT_USE_CENTER_LIMIT_ //start with free m_lowerLimit = btScalar(1.0f); m_upperLimit = btScalar(-1.0f); @@ -175,30 +168,28 @@ m_stopERP(0) m_solveLimit = false; #endif m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); -} - - +} btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA) -:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame), + : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_rbAFrame(rbAFrame), m_rbBFrame(rbAFrame), #ifdef _BT_USE_CENTER_LIMIT_ -m_limit(), + m_limit(), #endif -m_angularOnly(false), -m_enableAngularMotor(false), -m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), -m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), -m_useReferenceFrameA(useReferenceFrameA), -m_flags(0), -m_normalCFM(0), -m_normalERP(0), -m_stopCFM(0), -m_stopERP(0) + m_angularOnly(false), + m_enableAngularMotor(false), + m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER), + m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET), + m_useReferenceFrameA(useReferenceFrameA), + m_flags(0), + m_normalCFM(0), + m_normalERP(0), + m_stopCFM(0), + m_stopERP(0) { ///not providing rigidbody B means implicitly using worldspace for body B m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin()); -#ifndef _BT_USE_CENTER_LIMIT_ +#ifndef _BT_USE_CENTER_LIMIT_ //start with free m_lowerLimit = btScalar(1.0f); m_upperLimit = btScalar(-1.0f); @@ -210,9 +201,7 @@ m_stopERP(0) m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f); } - - -void btHingeConstraint::buildJacobian() +void btHingeConstraint::buildJacobian() { if (m_useSolveConstraintObsolete) { @@ -221,8 +210,8 @@ void btHingeConstraint::buildJacobian() if (!m_angularOnly) { - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_rbBFrame.getOrigin(); btVector3 relPos = pivotBInW - pivotAInW; btVector3 normal[3]; @@ -232,23 +221,23 @@ void btHingeConstraint::buildJacobian() } else { - normal[0].setValue(btScalar(1.0),0,0); + normal[0].setValue(btScalar(1.0), 0, 0); } btPlaneSpace1(normal[0], normal[1], normal[2]); - for (int i=0;i<3;i++) + for (int i = 0; i < 3; i++) { new (&m_jac[i]) btJacobianEntry( - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - pivotAInW - m_rbA.getCenterOfMassPosition(), - pivotBInW - m_rbB.getCenterOfMassPosition(), - normal[i], - m_rbA.getInvInertiaDiagLocal(), - m_rbA.getInvMass(), - m_rbB.getInvInertiaDiagLocal(), - m_rbB.getInvMass()); + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normal[i], + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); } } @@ -258,60 +247,55 @@ void btHingeConstraint::buildJacobian() //this is unused for now, it's a todo btVector3 jointAxis0local; btVector3 jointAxis1local; - - btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local); + + btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2), jointAxis0local, jointAxis1local); btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local; btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local; btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); - - new (&m_jacAng[0]) btJacobianEntry(jointAxis0, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); - - new (&m_jacAng[1]) btJacobianEntry(jointAxis1, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); - - new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); - - // clear accumulator - m_accLimitImpulse = btScalar(0.); - - // test angular limit - testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); - //Compute K = J*W*J' for hinge axis - btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); - m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) + - getRigidBodyB().computeAngularImpulseDenominator(axisA)); + new (&m_jacAng[0]) btJacobianEntry(jointAxis0, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); - } -} + new (&m_jacAng[1]) btJacobianEntry(jointAxis1, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); -#endif //__SPU__ + // clear accumulator + m_accLimitImpulse = btScalar(0.); + // test angular limit + testLimit(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform()); -static inline btScalar btNormalizeAnglePositive(btScalar angle) -{ - return btFmod(btFmod(angle, btScalar(2.0*SIMD_PI)) + btScalar(2.0*SIMD_PI), btScalar(2.0*SIMD_PI)); + //Compute K = J*W*J' for hinge axis + btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) + + getRigidBodyB().computeAngularImpulseDenominator(axisA)); + } } +#endif //__SPU__ +static inline btScalar btNormalizeAnglePositive(btScalar angle) +{ + return btFmod(btFmod(angle, btScalar(2.0 * SIMD_PI)) + btScalar(2.0 * SIMD_PI), btScalar(2.0 * SIMD_PI)); +} static btScalar btShortestAngularDistance(btScalar accAngle, btScalar curAngle) { btScalar result = btNormalizeAngle(btNormalizeAnglePositive(btNormalizeAnglePositive(curAngle) - - btNormalizeAnglePositive(accAngle))); + btNormalizeAnglePositive(accAngle))); return result; } @@ -320,41 +304,36 @@ static btScalar btShortestAngleUpdate(btScalar accAngle, btScalar curAngle) btScalar tol(0.3); btScalar result = btShortestAngularDistance(accAngle, curAngle); - if (btFabs(result) > tol) + if (btFabs(result) > tol) return curAngle; - else + else return accAngle + result; return curAngle; } - btScalar btHingeAccumulatedAngleConstraint::getAccumulatedHingeAngle() { btScalar hingeAngle = getHingeAngle(); - m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle,hingeAngle); + m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle, hingeAngle); return m_accumulatedAngle; } -void btHingeAccumulatedAngleConstraint::setAccumulatedHingeAngle(btScalar accAngle) +void btHingeAccumulatedAngleConstraint::setAccumulatedHingeAngle(btScalar accAngle) { - m_accumulatedAngle = accAngle; + m_accumulatedAngle = accAngle; } void btHingeAccumulatedAngleConstraint::getInfo1(btConstraintInfo1* info) { //update m_accumulatedAngle btScalar curHingeAngle = getHingeAngle(); - m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle,curHingeAngle); + m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle, curHingeAngle); btHingeConstraint::getInfo1(info); - } - void btHingeConstraint::getInfo1(btConstraintInfo1* info) { - - if (m_useSolveConstraintObsolete) { info->m_numConstraintRows = 0; @@ -362,17 +341,16 @@ void btHingeConstraint::getInfo1(btConstraintInfo1* info) } else { - info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular - info->nub = 1; + info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular + info->nub = 1; //always add the row, to avoid computation (data is not available yet) //prepare constraint - testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); - if(getSolveLimit() || getEnableAngularMotor()) + testLimit(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform()); + if (getSolveLimit() || getEnableAngularMotor()) { - info->m_numConstraintRows++; // limit 3rd anguar as well - info->nub--; + info->m_numConstraintRows++; // limit 3rd anguar as well + info->nub--; } - } } @@ -386,41 +364,38 @@ void btHingeConstraint::getInfo1NonVirtual(btConstraintInfo1* info) else { //always add the 'limit' row, to avoid computation (data is not available yet) - info->m_numConstraintRows = 6; // Fixed 3 linear + 2 angular - info->nub = 0; + info->m_numConstraintRows = 6; // Fixed 3 linear + 2 angular + info->nub = 0; } } -void btHingeConstraint::getInfo2 (btConstraintInfo2* info) +void btHingeConstraint::getInfo2(btConstraintInfo2* info) { - if(m_useOffsetForConstraintFrame) + if (m_useOffsetForConstraintFrame) { - getInfo2InternalUsingFrameOffset(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity()); + getInfo2InternalUsingFrameOffset(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getAngularVelocity(), m_rbB.getAngularVelocity()); } else { - getInfo2Internal(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity()); + getInfo2Internal(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getAngularVelocity(), m_rbB.getAngularVelocity()); } } - -void btHingeConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB) +void btHingeConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB) { ///the regular (virtual) implementation getInfo2 already performs 'testLimit' during getInfo1, so we need to do it now - testLimit(transA,transB); + testLimit(transA, transB); - getInfo2Internal(info,transA,transB,angVelA,angVelB); + getInfo2Internal(info, transA, transB, angVelA, angVelB); } - -void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB) +void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB) { - btAssert(!m_useSolveConstraintObsolete); int i, skip = info->rowskip; // transforms in world space - btTransform trA = transA*m_rbAFrame; - btTransform trB = transB*m_rbBFrame; + btTransform trA = transA * m_rbAFrame; + btTransform trB = transB * m_rbBFrame; // pivot point btVector3 pivotAInW = trA.getOrigin(); btVector3 pivotBInW = trB.getOrigin(); @@ -448,7 +423,7 @@ void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransf info->m_constraintError[i*skip]=0.f; } } -#endif //#if 0 +#endif //#if 0 // linear (all fixed) if (!m_angularOnly) @@ -460,10 +435,7 @@ void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransf info->m_J2linearAxis[0] = -1; info->m_J2linearAxis[skip + 1] = -1; info->m_J2linearAxis[2 * skip + 2] = -1; - } - - - + } btVector3 a1 = pivotAInW - transA.getOrigin(); { @@ -471,22 +443,22 @@ void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransf btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + skip); btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * skip); btVector3 a1neg = -a1; - a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); + a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2); } btVector3 a2 = pivotBInW - transB.getOrigin(); { btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + skip); btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * skip); - a2.getSkewSymmetricMatrix(angular0,angular1,angular2); + a2.getSkewSymmetricMatrix(angular0, angular1, angular2); } // linear RHS btScalar normalErp = (m_flags & BT_HINGE_FLAGS_ERP_NORM) ? m_normalERP : info->erp; - btScalar k = info->fps * normalErp; + btScalar k = info->fps * normalErp; if (!m_angularOnly) { - for(i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { info->m_constraintError[i * skip] = k * (pivotBInW[i] - pivotAInW[i]); } @@ -504,9 +476,9 @@ void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransf // get 2 orthos to hinge axis (X, Y) btVector3 p = trA.getBasis().getColumn(0); btVector3 q = trA.getBasis().getColumn(1); - // set the two hinge angular rows - int s3 = 3 * info->rowskip; - int s4 = 4 * info->rowskip; + // set the two hinge angular rows + int s3 = 3 * info->rowskip; + int s4 = 4 * info->rowskip; info->m_J1angularAxis[s3 + 0] = p[0]; info->m_J1angularAxis[s3 + 1] = p[1]; @@ -521,181 +493,172 @@ void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransf info->m_J2angularAxis[s4 + 0] = -q[0]; info->m_J2angularAxis[s4 + 1] = -q[1]; info->m_J2angularAxis[s4 + 2] = -q[2]; - // compute the right hand side of the constraint equation. set relative - // body velocities along p and q to bring the hinge back into alignment. - // if ax1,ax2 are the unit length hinge axes as computed from body1 and - // body2, we need to rotate both bodies along the axis u = (ax1 x ax2). - // if `theta' is the angle between ax1 and ax2, we need an angular velocity - // along u to cover angle erp*theta in one step : - // |angular_velocity| = angle/time = erp*theta / stepsize - // = (erp*fps) * theta - // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| - // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) - // ...as ax1 and ax2 are unit length. if theta is smallish, - // theta ~= sin(theta), so - // angular_velocity = (erp*fps) * (ax1 x ax2) - // ax1 x ax2 is in the plane space of ax1, so we project the angular - // velocity to p and q to find the right hand side. - btVector3 ax2 = trB.getBasis().getColumn(2); + // compute the right hand side of the constraint equation. set relative + // body velocities along p and q to bring the hinge back into alignment. + // if ax1,ax2 are the unit length hinge axes as computed from body1 and + // body2, we need to rotate both bodies along the axis u = (ax1 x ax2). + // if `theta' is the angle between ax1 and ax2, we need an angular velocity + // along u to cover angle erp*theta in one step : + // |angular_velocity| = angle/time = erp*theta / stepsize + // = (erp*fps) * theta + // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| + // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) + // ...as ax1 and ax2 are unit length. if theta is smallish, + // theta ~= sin(theta), so + // angular_velocity = (erp*fps) * (ax1 x ax2) + // ax1 x ax2 is in the plane space of ax1, so we project the angular + // velocity to p and q to find the right hand side. + btVector3 ax2 = trB.getBasis().getColumn(2); btVector3 u = ax1.cross(ax2); info->m_constraintError[s3] = k * u.dot(p); info->m_constraintError[s4] = k * u.dot(q); // check angular limits - int nrow = 4; // last filled row + int nrow = 4; // last filled row int srow; btScalar limit_err = btScalar(0.0); int limit = 0; - if(getSolveLimit()) + if (getSolveLimit()) { -#ifdef _BT_USE_CENTER_LIMIT_ - limit_err = m_limit.getCorrection() * m_referenceSign; +#ifdef _BT_USE_CENTER_LIMIT_ + limit_err = m_limit.getCorrection() * m_referenceSign; #else - limit_err = m_correction * m_referenceSign; + limit_err = m_correction * m_referenceSign; #endif - limit = (limit_err > btScalar(0.0)) ? 1 : 2; - + limit = (limit_err > btScalar(0.0)) ? 1 : 2; } // if the hinge has joint limits or motor, add in the extra row bool powered = getEnableAngularMotor(); - if(limit || powered) + if (limit || powered) { nrow++; srow = nrow * info->rowskip; - info->m_J1angularAxis[srow+0] = ax1[0]; - info->m_J1angularAxis[srow+1] = ax1[1]; - info->m_J1angularAxis[srow+2] = ax1[2]; + info->m_J1angularAxis[srow + 0] = ax1[0]; + info->m_J1angularAxis[srow + 1] = ax1[1]; + info->m_J1angularAxis[srow + 2] = ax1[2]; - info->m_J2angularAxis[srow+0] = -ax1[0]; - info->m_J2angularAxis[srow+1] = -ax1[1]; - info->m_J2angularAxis[srow+2] = -ax1[2]; + info->m_J2angularAxis[srow + 0] = -ax1[0]; + info->m_J2angularAxis[srow + 1] = -ax1[1]; + info->m_J2angularAxis[srow + 2] = -ax1[2]; btScalar lostop = getLowerLimit(); btScalar histop = getUpperLimit(); - if(limit && (lostop == histop)) + if (limit && (lostop == histop)) { // the joint motor is ineffective powered = false; } info->m_constraintError[srow] = btScalar(0.0f); btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : normalErp; - if(powered) + if (powered) { - if(m_flags & BT_HINGE_FLAGS_CFM_NORM) + if (m_flags & BT_HINGE_FLAGS_CFM_NORM) { info->cfm[srow] = m_normalCFM; } btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP); info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign; - info->m_lowerLimit[srow] = - m_maxMotorImpulse; - info->m_upperLimit[srow] = m_maxMotorImpulse; + info->m_lowerLimit[srow] = -m_maxMotorImpulse; + info->m_upperLimit[srow] = m_maxMotorImpulse; } - if(limit) + if (limit) { k = info->fps * currERP; info->m_constraintError[srow] += k * limit_err; - if(m_flags & BT_HINGE_FLAGS_CFM_STOP) + if (m_flags & BT_HINGE_FLAGS_CFM_STOP) { info->cfm[srow] = m_stopCFM; } - if(lostop == histop) + if (lostop == histop) { // limited low and high simultaneously info->m_lowerLimit[srow] = -SIMD_INFINITY; info->m_upperLimit[srow] = SIMD_INFINITY; } - else if(limit == 1) - { // low limit + else if (limit == 1) + { // low limit info->m_lowerLimit[srow] = 0; info->m_upperLimit[srow] = SIMD_INFINITY; } - else - { // high limit + else + { // high limit info->m_lowerLimit[srow] = -SIMD_INFINITY; info->m_upperLimit[srow] = 0; } // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) -#ifdef _BT_USE_CENTER_LIMIT_ +#ifdef _BT_USE_CENTER_LIMIT_ btScalar bounce = m_limit.getRelaxationFactor(); #else btScalar bounce = m_relaxationFactor; #endif - if(bounce > btScalar(0.0)) + if (bounce > btScalar(0.0)) { btScalar vel = angVelA.dot(ax1); vel -= angVelB.dot(ax1); // only apply bounce if the velocity is incoming, and if the // resulting c[] exceeds what we already have. - if(limit == 1) - { // low limit - if(vel < 0) + if (limit == 1) + { // low limit + if (vel < 0) { btScalar newc = -bounce * vel; - if(newc > info->m_constraintError[srow]) + if (newc > info->m_constraintError[srow]) { info->m_constraintError[srow] = newc; } } } else - { // high limit - all those computations are reversed - if(vel > 0) + { // high limit - all those computations are reversed + if (vel > 0) { btScalar newc = -bounce * vel; - if(newc < info->m_constraintError[srow]) + if (newc < info->m_constraintError[srow]) { info->m_constraintError[srow] = newc; } } } } -#ifdef _BT_USE_CENTER_LIMIT_ +#ifdef _BT_USE_CENTER_LIMIT_ info->m_constraintError[srow] *= m_limit.getBiasFactor(); #else info->m_constraintError[srow] *= m_biasFactor; #endif - } // if(limit) - } // if angular limit or powered + } // if(limit) + } // if angular limit or powered } - -void btHingeConstraint::setFrames(const btTransform & frameA, const btTransform & frameB) +void btHingeConstraint::setFrames(const btTransform& frameA, const btTransform& frameB) { m_rbAFrame = frameA; m_rbBFrame = frameB; buildJacobian(); } - -void btHingeConstraint::updateRHS(btScalar timeStep) +void btHingeConstraint::updateRHS(btScalar timeStep) { (void)timeStep; - } - - - btScalar btHingeConstraint::getHingeAngle() { - return getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + return getHingeAngle(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform()); } -btScalar btHingeConstraint::getHingeAngle(const btTransform& transA,const btTransform& transB) +btScalar btHingeConstraint::getHingeAngle(const btTransform& transA, const btTransform& transB) { - const btVector3 refAxis0 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0); - const btVector3 refAxis1 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1); + const btVector3 refAxis0 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0); + const btVector3 refAxis1 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1); const btVector3 swingAxis = transB.getBasis() * m_rbBFrame.getBasis().getColumn(1); -// btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); + // btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); return m_referenceSign * angle; } - - -void btHingeConstraint::testLimit(const btTransform& transA,const btTransform& transB) +void btHingeConstraint::testLimit(const btTransform& transA, const btTransform& transB) { // Compute limit information - m_hingeAngle = getHingeAngle(transA,transB); -#ifdef _BT_USE_CENTER_LIMIT_ + m_hingeAngle = getHingeAngle(transA, transB); +#ifdef _BT_USE_CENTER_LIMIT_ m_limit.test(m_hingeAngle); #else m_correction = btScalar(0.); @@ -709,7 +672,7 @@ void btHingeConstraint::testLimit(const btTransform& transA,const btTransform& t m_correction = (m_lowerLimit - m_hingeAngle); m_limitSign = 1.0f; m_solveLimit = true; - } + } else if (m_hingeAngle >= m_upperLimit) { m_correction = m_upperLimit - m_hingeAngle; @@ -721,7 +684,6 @@ void btHingeConstraint::testLimit(const btTransform& transA,const btTransform& t return; } - static btVector3 vHinge(0, 0, btScalar(1)); void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt) @@ -731,14 +693,15 @@ void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt) qConstraint.normalize(); // extract "pure" hinge component - btVector3 vNoHinge = quatRotate(qConstraint, vHinge); vNoHinge.normalize(); + btVector3 vNoHinge = quatRotate(qConstraint, vHinge); + vNoHinge.normalize(); btQuaternion qNoHinge = shortestArcQuat(vHinge, vNoHinge); btQuaternion qHinge = qNoHinge.inverse() * qConstraint; qHinge.normalize(); // compute angular target, clamped to limits btScalar targetAngle = qHinge.getAngle(); - if (targetAngle > SIMD_PI) // long way around. flip quat and recalculate. + if (targetAngle > SIMD_PI) // long way around. flip quat and recalculate. { qHinge = -(qHinge); targetAngle = qHinge.getAngle(); @@ -751,7 +714,7 @@ void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt) void btHingeConstraint::setMotorTarget(btScalar targetAngle, btScalar dt) { -#ifdef _BT_USE_CENTER_LIMIT_ +#ifdef _BT_USE_CENTER_LIMIT_ m_limit.fit(targetAngle); #else if (m_lowerLimit < m_upperLimit) @@ -763,20 +726,18 @@ void btHingeConstraint::setMotorTarget(btScalar targetAngle, btScalar dt) } #endif // compute angular velocity - btScalar curAngle = getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + btScalar curAngle = getHingeAngle(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform()); btScalar dAngle = targetAngle - curAngle; m_motorTargetVelocity = dAngle / dt; } - - -void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB) +void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB) { btAssert(!m_useSolveConstraintObsolete); int i, s = info->rowskip; // transforms in world space - btTransform trA = transA*m_rbAFrame; - btTransform trB = transB*m_rbBFrame; + btTransform trA = transA * m_rbAFrame; + btTransform trB = transB * m_rbBFrame; // pivot point // btVector3 pivotAInW = trA.getOrigin(); // btVector3 pivotBInW = trB.getOrigin(); @@ -789,11 +750,11 @@ void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON); btScalar miS = miA + miB; btScalar factA, factB; - if(miS > btScalar(0.f)) + if (miS > btScalar(0.f)) { factA = miB / miS; } - else + else { factA = btScalar(0.5f); } @@ -803,15 +764,21 @@ void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info btVector3 ax1A = trA.getBasis().getColumn(2); btVector3 ax1B = trB.getBasis().getColumn(2); btVector3 ax1 = ax1A * factA + ax1B * factB; + if (ax1.length2()<SIMD_EPSILON) + { + factA=0.f; + factB=1.f; + ax1 = ax1A * factA + ax1B * factB; + } ax1.normalize(); - // fill first 3 rows + // fill first 3 rows // we want: velA + wA x relA == velB + wB x relB btTransform bodyA_trans = transA; btTransform bodyB_trans = transB; int s0 = 0; int s1 = s; int s2 = s * 2; - int nrow = 2; // last filled row + int nrow = 2; // last filled row btVector3 tmpA, tmpB, relA, relB, p, q; // get vector from bodyB to frameB in WCS relB = trB.getOrigin() - bodyB_trans.getOrigin(); @@ -830,7 +797,7 @@ void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info // now choose average ortho to hinge axis p = orthoB * factA + orthoA * factB; btScalar len2 = p.length2(); - if(len2 > SIMD_EPSILON) + if (len2 > SIMD_EPSILON) { p /= btSqrt(len2); } @@ -843,44 +810,44 @@ void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info // fill three rows tmpA = relA.cross(p); tmpB = relB.cross(p); - for (i=0; i<3; i++) info->m_J1angularAxis[s0+i] = tmpA[i]; - for (i=0; i<3; i++) info->m_J2angularAxis[s0+i] = -tmpB[i]; + for (i = 0; i < 3; i++) info->m_J1angularAxis[s0 + i] = tmpA[i]; + for (i = 0; i < 3; i++) info->m_J2angularAxis[s0 + i] = -tmpB[i]; tmpA = relA.cross(q); tmpB = relB.cross(q); - if(hasStaticBody && getSolveLimit()) - { // to make constraint between static and dynamic objects more rigid + if (hasStaticBody && getSolveLimit()) + { // to make constraint between static and dynamic objects more rigid // remove wA (or wB) from equation if angular limit is hit tmpB *= factB; tmpA *= factA; } - for (i=0; i<3; i++) info->m_J1angularAxis[s1+i] = tmpA[i]; - for (i=0; i<3; i++) info->m_J2angularAxis[s1+i] = -tmpB[i]; + for (i = 0; i < 3; i++) info->m_J1angularAxis[s1 + i] = tmpA[i]; + for (i = 0; i < 3; i++) info->m_J2angularAxis[s1 + i] = -tmpB[i]; tmpA = relA.cross(ax1); tmpB = relB.cross(ax1); - if(hasStaticBody) - { // to make constraint between static and dynamic objects more rigid + if (hasStaticBody) + { // to make constraint between static and dynamic objects more rigid // remove wA (or wB) from equation tmpB *= factB; tmpA *= factA; } - for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i]; - for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i]; + for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = tmpA[i]; + for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = -tmpB[i]; - btScalar normalErp = (m_flags & BT_HINGE_FLAGS_ERP_NORM)? m_normalERP : info->erp; + btScalar normalErp = (m_flags & BT_HINGE_FLAGS_ERP_NORM) ? m_normalERP : info->erp; btScalar k = info->fps * normalErp; if (!m_angularOnly) { - for (i=0; i<3; i++) info->m_J1linearAxis[s0+i] = p[i]; - for (i=0; i<3; i++) info->m_J1linearAxis[s1+i] = q[i]; - for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = ax1[i]; + for (i = 0; i < 3; i++) info->m_J1linearAxis[s0 + i] = p[i]; + for (i = 0; i < 3; i++) info->m_J1linearAxis[s1 + i] = q[i]; + for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = ax1[i]; + + for (i = 0; i < 3; i++) info->m_J2linearAxis[s0 + i] = -p[i]; + for (i = 0; i < 3; i++) info->m_J2linearAxis[s1 + i] = -q[i]; + for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -ax1[i]; - for (i=0; i<3; i++) info->m_J2linearAxis[s0+i] = -p[i]; - for (i=0; i<3; i++) info->m_J2linearAxis[s1+i] = -q[i]; - for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -ax1[i]; + // compute three elements of right hand side - // compute three elements of right hand side - btScalar rhs = k * p.dot(ofs); info->m_constraintError[s0] = rhs; rhs = k * q.dot(ofs); @@ -925,146 +892,144 @@ void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info // angular_velocity = (erp*fps) * (ax1 x ax2) // ax1 x ax2 is in the plane space of ax1, so we project the angular // velocity to p and q to find the right hand side. - k = info->fps * normalErp;//?? + k = info->fps * normalErp; //?? btVector3 u = ax1A.cross(ax1B); info->m_constraintError[s3] = k * u.dot(p); info->m_constraintError[s4] = k * u.dot(q); #endif // check angular limits - nrow = 4; // last filled row + nrow = 4; // last filled row int srow; btScalar limit_err = btScalar(0.0); int limit = 0; - if(getSolveLimit()) + if (getSolveLimit()) { -#ifdef _BT_USE_CENTER_LIMIT_ - limit_err = m_limit.getCorrection() * m_referenceSign; +#ifdef _BT_USE_CENTER_LIMIT_ + limit_err = m_limit.getCorrection() * m_referenceSign; #else - limit_err = m_correction * m_referenceSign; + limit_err = m_correction * m_referenceSign; #endif - limit = (limit_err > btScalar(0.0)) ? 1 : 2; - + limit = (limit_err > btScalar(0.0)) ? 1 : 2; } // if the hinge has joint limits or motor, add in the extra row bool powered = getEnableAngularMotor(); - if(limit || powered) + if (limit || powered) { nrow++; srow = nrow * info->rowskip; - info->m_J1angularAxis[srow+0] = ax1[0]; - info->m_J1angularAxis[srow+1] = ax1[1]; - info->m_J1angularAxis[srow+2] = ax1[2]; + info->m_J1angularAxis[srow + 0] = ax1[0]; + info->m_J1angularAxis[srow + 1] = ax1[1]; + info->m_J1angularAxis[srow + 2] = ax1[2]; - info->m_J2angularAxis[srow+0] = -ax1[0]; - info->m_J2angularAxis[srow+1] = -ax1[1]; - info->m_J2angularAxis[srow+2] = -ax1[2]; + info->m_J2angularAxis[srow + 0] = -ax1[0]; + info->m_J2angularAxis[srow + 1] = -ax1[1]; + info->m_J2angularAxis[srow + 2] = -ax1[2]; btScalar lostop = getLowerLimit(); btScalar histop = getUpperLimit(); - if(limit && (lostop == histop)) + if (limit && (lostop == histop)) { // the joint motor is ineffective powered = false; } info->m_constraintError[srow] = btScalar(0.0f); btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : normalErp; - if(powered) + if (powered) { - if(m_flags & BT_HINGE_FLAGS_CFM_NORM) + if (m_flags & BT_HINGE_FLAGS_CFM_NORM) { info->cfm[srow] = m_normalCFM; } btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP); info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign; - info->m_lowerLimit[srow] = - m_maxMotorImpulse; - info->m_upperLimit[srow] = m_maxMotorImpulse; + info->m_lowerLimit[srow] = -m_maxMotorImpulse; + info->m_upperLimit[srow] = m_maxMotorImpulse; } - if(limit) + if (limit) { k = info->fps * currERP; info->m_constraintError[srow] += k * limit_err; - if(m_flags & BT_HINGE_FLAGS_CFM_STOP) + if (m_flags & BT_HINGE_FLAGS_CFM_STOP) { info->cfm[srow] = m_stopCFM; } - if(lostop == histop) + if (lostop == histop) { // limited low and high simultaneously info->m_lowerLimit[srow] = -SIMD_INFINITY; info->m_upperLimit[srow] = SIMD_INFINITY; } - else if(limit == 1) - { // low limit + else if (limit == 1) + { // low limit info->m_lowerLimit[srow] = 0; info->m_upperLimit[srow] = SIMD_INFINITY; } - else - { // high limit + else + { // high limit info->m_lowerLimit[srow] = -SIMD_INFINITY; info->m_upperLimit[srow] = 0; } // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) -#ifdef _BT_USE_CENTER_LIMIT_ +#ifdef _BT_USE_CENTER_LIMIT_ btScalar bounce = m_limit.getRelaxationFactor(); #else btScalar bounce = m_relaxationFactor; #endif - if(bounce > btScalar(0.0)) + if (bounce > btScalar(0.0)) { btScalar vel = angVelA.dot(ax1); vel -= angVelB.dot(ax1); // only apply bounce if the velocity is incoming, and if the // resulting c[] exceeds what we already have. - if(limit == 1) - { // low limit - if(vel < 0) + if (limit == 1) + { // low limit + if (vel < 0) { btScalar newc = -bounce * vel; - if(newc > info->m_constraintError[srow]) + if (newc > info->m_constraintError[srow]) { info->m_constraintError[srow] = newc; } } } else - { // high limit - all those computations are reversed - if(vel > 0) + { // high limit - all those computations are reversed + if (vel > 0) { btScalar newc = -bounce * vel; - if(newc < info->m_constraintError[srow]) + if (newc < info->m_constraintError[srow]) { info->m_constraintError[srow] = newc; } } } } -#ifdef _BT_USE_CENTER_LIMIT_ +#ifdef _BT_USE_CENTER_LIMIT_ info->m_constraintError[srow] *= m_limit.getBiasFactor(); #else info->m_constraintError[srow] *= m_biasFactor; #endif - } // if(limit) - } // if angular limit or powered + } // if(limit) + } // if angular limit or powered } - -///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). +///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). ///If no axis is provided, it uses the default axis for this constraint. void btHingeConstraint::setParam(int num, btScalar value, int axis) { - if((axis == -1) || (axis == 5)) + if ((axis == -1) || (axis == 5)) { - switch(num) - { - case BT_CONSTRAINT_STOP_ERP : + switch (num) + { + case BT_CONSTRAINT_STOP_ERP: m_stopERP = value; m_flags |= BT_HINGE_FLAGS_ERP_STOP; break; - case BT_CONSTRAINT_STOP_CFM : + case BT_CONSTRAINT_STOP_CFM: m_stopCFM = value; m_flags |= BT_HINGE_FLAGS_CFM_STOP; break; - case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_CFM: m_normalCFM = value; m_flags |= BT_HINGE_FLAGS_CFM_NORM; break; @@ -1072,7 +1037,7 @@ void btHingeConstraint::setParam(int num, btScalar value, int axis) m_normalERP = value; m_flags |= BT_HINGE_FLAGS_ERP_NORM; break; - default : + default: btAssertConstrParams(0); } } @@ -1083,22 +1048,22 @@ void btHingeConstraint::setParam(int num, btScalar value, int axis) } ///return the local value of parameter -btScalar btHingeConstraint::getParam(int num, int axis) const +btScalar btHingeConstraint::getParam(int num, int axis) const { btScalar retVal = 0; - if((axis == -1) || (axis == 5)) + if ((axis == -1) || (axis == 5)) { - switch(num) - { - case BT_CONSTRAINT_STOP_ERP : + switch (num) + { + case BT_CONSTRAINT_STOP_ERP: btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_STOP); retVal = m_stopERP; break; - case BT_CONSTRAINT_STOP_CFM : + case BT_CONSTRAINT_STOP_CFM: btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_STOP); retVal = m_stopCFM; break; - case BT_CONSTRAINT_CFM : + case BT_CONSTRAINT_CFM: btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_NORM); retVal = m_normalCFM; break; @@ -1106,7 +1071,7 @@ btScalar btHingeConstraint::getParam(int num, int axis) const btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_NORM); retVal = m_normalERP; break; - default : + default: btAssertConstrParams(0); } } @@ -1116,5 +1081,3 @@ btScalar btHingeConstraint::getParam(int num, int axis) const } return retVal; } - - diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h index 3c3df24dba..c7509e30af 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h @@ -20,7 +20,6 @@ subject to the following restrictions: #define _BT_USE_CENTER_LIMIT_ 1 - #include "LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" @@ -28,14 +27,12 @@ subject to the following restrictions: class btRigidBody; #ifdef BT_USE_DOUBLE_PRECISION -#define btHingeConstraintData btHingeConstraintDoubleData2 //rename to 2 for backwards compatibility, so we can still load the 'btHingeConstraintDoubleData' version -#define btHingeConstraintDataName "btHingeConstraintDoubleData2" +#define btHingeConstraintData btHingeConstraintDoubleData2 //rename to 2 for backwards compatibility, so we can still load the 'btHingeConstraintDoubleData' version +#define btHingeConstraintDataName "btHingeConstraintDoubleData2" #else -#define btHingeConstraintData btHingeConstraintFloatData -#define btHingeConstraintDataName "btHingeConstraintFloatData" -#endif //BT_USE_DOUBLE_PRECISION - - +#define btHingeConstraintData btHingeConstraintFloatData +#define btHingeConstraintDataName "btHingeConstraintFloatData" +#endif //BT_USE_DOUBLE_PRECISION enum btHingeFlags { @@ -45,89 +42,83 @@ enum btHingeFlags BT_HINGE_FLAGS_ERP_NORM = 8 }; - /// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space /// axis defines the orientation of the hinge axis -ATTRIBUTE_ALIGNED16(class) btHingeConstraint : public btTypedConstraint +ATTRIBUTE_ALIGNED16(class) +btHingeConstraint : public btTypedConstraint { #ifdef IN_PARALLELL_SOLVER public: #endif - btJacobianEntry m_jac[3]; //3 orthogonal linear constraints - btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor + btJacobianEntry m_jac[3]; //3 orthogonal linear constraints + btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor - btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis. btTransform m_rbBFrame; - btScalar m_motorTargetVelocity; - btScalar m_maxMotorImpulse; - + btScalar m_motorTargetVelocity; + btScalar m_maxMotorImpulse; -#ifdef _BT_USE_CENTER_LIMIT_ - btAngularLimit m_limit; +#ifdef _BT_USE_CENTER_LIMIT_ + btAngularLimit m_limit; #else - btScalar m_lowerLimit; - btScalar m_upperLimit; - btScalar m_limitSign; - btScalar m_correction; + btScalar m_lowerLimit; + btScalar m_upperLimit; + btScalar m_limitSign; + btScalar m_correction; - btScalar m_limitSoftness; - btScalar m_biasFactor; - btScalar m_relaxationFactor; + btScalar m_limitSoftness; + btScalar m_biasFactor; + btScalar m_relaxationFactor; - bool m_solveLimit; + bool m_solveLimit; #endif - btScalar m_kHinge; - + btScalar m_kHinge; - btScalar m_accLimitImpulse; - btScalar m_hingeAngle; - btScalar m_referenceSign; + btScalar m_accLimitImpulse; + btScalar m_hingeAngle; + btScalar m_referenceSign; - bool m_angularOnly; - bool m_enableAngularMotor; - bool m_useSolveConstraintObsolete; - bool m_useOffsetForConstraintFrame; - bool m_useReferenceFrameA; + bool m_angularOnly; + bool m_enableAngularMotor; + bool m_useSolveConstraintObsolete; + bool m_useOffsetForConstraintFrame; + bool m_useReferenceFrameA; - btScalar m_accMotorImpulse; + btScalar m_accMotorImpulse; - int m_flags; - btScalar m_normalCFM; - btScalar m_normalERP; - btScalar m_stopCFM; - btScalar m_stopERP; + int m_flags; + btScalar m_normalCFM; + btScalar m_normalERP; + btScalar m_stopCFM; + btScalar m_stopERP; - public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - - btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA = false); - btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA = false); - - btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false); + btHingeConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& pivotInA, const btVector3& pivotInB, const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA = false); + + btHingeConstraint(btRigidBody & rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA = false); - btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA = false); + btHingeConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false); + btHingeConstraint(btRigidBody & rbA, const btTransform& rbAFrame, bool useReferenceFrameA = false); - virtual void buildJacobian(); + virtual void buildJacobian(); - virtual void getInfo1 (btConstraintInfo1* info); + virtual void getInfo1(btConstraintInfo1 * info); - void getInfo1NonVirtual(btConstraintInfo1* info); + void getInfo1NonVirtual(btConstraintInfo1 * info); - virtual void getInfo2 (btConstraintInfo2* info); + virtual void getInfo2(btConstraintInfo2 * info); - void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB); + void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB); - void getInfo2Internal(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB); - void getInfo2InternalUsingFrameOffset(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB); - + void getInfo2Internal(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB); + void getInfo2InternalUsingFrameOffset(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB); - void updateRHS(btScalar timeStep); + void updateRHS(btScalar timeStep); const btRigidBody& getRigidBodyA() const { @@ -138,19 +129,19 @@ public: return m_rbB; } - btRigidBody& getRigidBodyA() - { - return m_rbA; - } + btRigidBody& getRigidBodyA() + { + return m_rbA; + } - btRigidBody& getRigidBodyB() - { - return m_rbB; + btRigidBody& getRigidBodyB() + { + return m_rbB; } btTransform& getFrameOffsetA() { - return m_rbAFrame; + return m_rbAFrame; } btTransform& getFrameOffsetB() @@ -159,15 +150,15 @@ public: } void setFrames(const btTransform& frameA, const btTransform& frameB); - - void setAngularOnly(bool angularOnly) + + void setAngularOnly(bool angularOnly) { m_angularOnly = angularOnly; } - void enableAngularMotor(bool enableMotor,btScalar targetVelocity,btScalar maxMotorImpulse) + void enableAngularMotor(bool enableMotor, btScalar targetVelocity, btScalar maxMotorImpulse) { - m_enableAngularMotor = enableMotor; + m_enableAngularMotor = enableMotor; m_motorTargetVelocity = targetVelocity; m_maxMotorImpulse = maxMotorImpulse; } @@ -175,29 +166,28 @@ public: // extra motor API, including ability to set a target rotation (as opposed to angular velocity) // note: setMotorTarget sets angular velocity under the hood, so you must call it every tick to // maintain a given angular target. - void enableMotor(bool enableMotor) { m_enableAngularMotor = enableMotor; } + void enableMotor(bool enableMotor) { m_enableAngularMotor = enableMotor; } void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; } void setMotorTargetVelocity(btScalar motorTargetVelocity) { m_motorTargetVelocity = motorTargetVelocity; } - void setMotorTarget(const btQuaternion& qAinB, btScalar dt); // qAinB is rotation of body A wrt body B. + void setMotorTarget(const btQuaternion& qAinB, btScalar dt); // qAinB is rotation of body A wrt body B. void setMotorTarget(btScalar targetAngle, btScalar dt); - - void setLimit(btScalar low,btScalar high,btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) + void setLimit(btScalar low, btScalar high, btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) { -#ifdef _BT_USE_CENTER_LIMIT_ +#ifdef _BT_USE_CENTER_LIMIT_ m_limit.set(low, high, _softness, _biasFactor, _relaxationFactor); #else m_lowerLimit = btNormalizeAngle(low); m_upperLimit = btNormalizeAngle(high); - m_limitSoftness = _softness; + m_limitSoftness = _softness; m_biasFactor = _biasFactor; m_relaxationFactor = _relaxationFactor; #endif } - + btScalar getLimitSoftness() const { -#ifdef _BT_USE_CENTER_LIMIT_ +#ifdef _BT_USE_CENTER_LIMIT_ return m_limit.getSoftness(); #else return m_limitSoftness; @@ -206,7 +196,7 @@ public: btScalar getLimitBiasFactor() const { -#ifdef _BT_USE_CENTER_LIMIT_ +#ifdef _BT_USE_CENTER_LIMIT_ return m_limit.getBiasFactor(); #else return m_biasFactor; @@ -215,112 +205,110 @@ public: btScalar getLimitRelaxationFactor() const { -#ifdef _BT_USE_CENTER_LIMIT_ +#ifdef _BT_USE_CENTER_LIMIT_ return m_limit.getRelaxationFactor(); #else return m_relaxationFactor; #endif } - void setAxis(btVector3& axisInA) + void setAxis(btVector3 & axisInA) { btVector3 rbAxisA1, rbAxisA2; btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2); btVector3 pivotInA = m_rbAFrame.getOrigin(); -// m_rbAFrame.getOrigin() = pivotInA; - m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), - rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), - rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + // m_rbAFrame.getOrigin() = pivotInA; + m_rbAFrame.getBasis().setValue(rbAxisA1.getX(), rbAxisA2.getX(), axisInA.getX(), + rbAxisA1.getY(), rbAxisA2.getY(), axisInA.getY(), + rbAxisA1.getZ(), rbAxisA2.getZ(), axisInA.getZ()); btVector3 axisInB = m_rbA.getCenterOfMassTransform().getBasis() * axisInA; - btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); - btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); + btQuaternion rotationArc = shortestArcQuat(axisInA, axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc, rbAxisA1); btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); m_rbBFrame.getOrigin() = m_rbB.getCenterOfMassTransform().inverse()(m_rbA.getCenterOfMassTransform()(pivotInA)); - m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), - rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), - rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); + m_rbBFrame.getBasis().setValue(rbAxisB1.getX(), rbAxisB2.getX(), axisInB.getX(), + rbAxisB1.getY(), rbAxisB2.getY(), axisInB.getY(), + rbAxisB1.getZ(), rbAxisB2.getZ(), axisInB.getZ()); m_rbBFrame.getBasis() = m_rbB.getCenterOfMassTransform().getBasis().inverse() * m_rbBFrame.getBasis(); - } - bool hasLimit() const { -#ifdef _BT_USE_CENTER_LIMIT_ - return m_limit.getHalfRange() > 0; + bool hasLimit() const + { +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.getHalfRange() > 0; #else - return m_lowerLimit <= m_upperLimit; + return m_lowerLimit <= m_upperLimit; #endif - } + } - btScalar getLowerLimit() const + btScalar getLowerLimit() const { -#ifdef _BT_USE_CENTER_LIMIT_ - return m_limit.getLow(); +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.getLow(); #else - return m_lowerLimit; + return m_lowerLimit; #endif } - btScalar getUpperLimit() const + btScalar getUpperLimit() const { -#ifdef _BT_USE_CENTER_LIMIT_ - return m_limit.getHigh(); -#else - return m_upperLimit; +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.getHigh(); +#else + return m_upperLimit; #endif } - ///The getHingeAngle gives the hinge angle in range [-PI,PI] btScalar getHingeAngle(); - btScalar getHingeAngle(const btTransform& transA,const btTransform& transB); - - void testLimit(const btTransform& transA,const btTransform& transB); + btScalar getHingeAngle(const btTransform& transA, const btTransform& transB); + void testLimit(const btTransform& transA, const btTransform& transB); - const btTransform& getAFrame() const { return m_rbAFrame; }; + const btTransform& getAFrame() const { return m_rbAFrame; }; const btTransform& getBFrame() const { return m_rbBFrame; }; - btTransform& getAFrame() { return m_rbAFrame; }; + btTransform& getAFrame() { return m_rbAFrame; }; btTransform& getBFrame() { return m_rbBFrame; }; inline int getSolveLimit() { -#ifdef _BT_USE_CENTER_LIMIT_ - return m_limit.isLimit(); +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.isLimit(); #else - return m_solveLimit; + return m_solveLimit; #endif } inline btScalar getLimitSign() { -#ifdef _BT_USE_CENTER_LIMIT_ - return m_limit.getSign(); +#ifdef _BT_USE_CENTER_LIMIT_ + return m_limit.getSign(); #else return m_limitSign; #endif } - inline bool getAngularOnly() - { - return m_angularOnly; + inline bool getAngularOnly() + { + return m_angularOnly; } - inline bool getEnableAngularMotor() - { - return m_enableAngularMotor; + inline bool getEnableAngularMotor() + { + return m_enableAngularMotor; } - inline btScalar getMotorTargetVelocity() - { - return m_motorTargetVelocity; + inline btScalar getMotorTargetVelocity() + { + return m_motorTargetVelocity; } - inline btScalar getMaxMotorImpulse() - { - return m_maxMotorImpulse; + inline btScalar getMaxMotorImpulse() + { + return m_maxMotorImpulse; } // access for UseFrameOffset bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; } @@ -329,143 +317,132 @@ public: bool getUseReferenceFrameA() const { return m_useReferenceFrameA; } void setUseReferenceFrameA(bool useReferenceFrameA) { m_useReferenceFrameA = useReferenceFrameA; } - ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). ///If no axis is provided, it uses the default axis for this constraint. - virtual void setParam(int num, btScalar value, int axis = -1); + virtual void setParam(int num, btScalar value, int axis = -1); ///return the local value of parameter - virtual btScalar getParam(int num, int axis = -1) const; - - virtual int getFlags() const + virtual btScalar getParam(int num, int axis = -1) const; + + virtual int getFlags() const { - return m_flags; + return m_flags; } - virtual int calculateSerializeBufferSize() const; + virtual int calculateSerializeBufferSize() const; ///fills the dataBuffer and returns the struct name (and 0 on failure) - virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; - - + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; }; - //only for backward compatibility #ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION ///this structure is not used, except for loading pre-2.82 .bullet files -struct btHingeConstraintDoubleData +struct btHingeConstraintDoubleData { - btTypedConstraintData m_typeConstraintData; - btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTypedConstraintData m_typeConstraintData; + btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. btTransformDoubleData m_rbBFrame; - int m_useReferenceFrameA; - int m_angularOnly; - int m_enableAngularMotor; - float m_motorTargetVelocity; - float m_maxMotorImpulse; - - float m_lowerLimit; - float m_upperLimit; - float m_limitSoftness; - float m_biasFactor; - float m_relaxationFactor; - + int m_useReferenceFrameA; + int m_angularOnly; + int m_enableAngularMotor; + float m_motorTargetVelocity; + float m_maxMotorImpulse; + + float m_lowerLimit; + float m_upperLimit; + float m_limitSoftness; + float m_biasFactor; + float m_relaxationFactor; }; -#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION +#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION ///The getAccumulatedHingeAngle returns the accumulated hinge angle, taking rotation across the -PI/PI boundary into account -ATTRIBUTE_ALIGNED16(class) btHingeAccumulatedAngleConstraint : public btHingeConstraint +ATTRIBUTE_ALIGNED16(class) +btHingeAccumulatedAngleConstraint : public btHingeConstraint { protected: - btScalar m_accumulatedAngle; -public: + btScalar m_accumulatedAngle; +public: BT_DECLARE_ALIGNED_ALLOCATOR(); - - btHingeAccumulatedAngleConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA = false) - :btHingeConstraint(rbA,rbB,pivotInA,pivotInB, axisInA,axisInB, useReferenceFrameA ) + + btHingeAccumulatedAngleConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& pivotInA, const btVector3& pivotInB, const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA = false) + : btHingeConstraint(rbA, rbB, pivotInA, pivotInB, axisInA, axisInB, useReferenceFrameA) { - m_accumulatedAngle=getHingeAngle(); + m_accumulatedAngle = getHingeAngle(); } - btHingeAccumulatedAngleConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA = false) - :btHingeConstraint(rbA,pivotInA,axisInA, useReferenceFrameA) + btHingeAccumulatedAngleConstraint(btRigidBody & rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA = false) + : btHingeConstraint(rbA, pivotInA, axisInA, useReferenceFrameA) { - m_accumulatedAngle=getHingeAngle(); + m_accumulatedAngle = getHingeAngle(); } - - btHingeAccumulatedAngleConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false) - :btHingeConstraint(rbA,rbB, rbAFrame, rbBFrame, useReferenceFrameA ) + + btHingeAccumulatedAngleConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false) + : btHingeConstraint(rbA, rbB, rbAFrame, rbBFrame, useReferenceFrameA) { - m_accumulatedAngle=getHingeAngle(); + m_accumulatedAngle = getHingeAngle(); } - btHingeAccumulatedAngleConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA = false) - :btHingeConstraint(rbA,rbAFrame, useReferenceFrameA ) + btHingeAccumulatedAngleConstraint(btRigidBody & rbA, const btTransform& rbAFrame, bool useReferenceFrameA = false) + : btHingeConstraint(rbA, rbAFrame, useReferenceFrameA) { - m_accumulatedAngle=getHingeAngle(); + m_accumulatedAngle = getHingeAngle(); } btScalar getAccumulatedHingeAngle(); - void setAccumulatedHingeAngle(btScalar accAngle); - virtual void getInfo1 (btConstraintInfo1* info); - + void setAccumulatedHingeAngle(btScalar accAngle); + virtual void getInfo1(btConstraintInfo1 * info); }; -struct btHingeConstraintFloatData +struct btHingeConstraintFloatData { - btTypedConstraintData m_typeConstraintData; - btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis. btTransformFloatData m_rbBFrame; - int m_useReferenceFrameA; - int m_angularOnly; - - int m_enableAngularMotor; - float m_motorTargetVelocity; - float m_maxMotorImpulse; - - float m_lowerLimit; - float m_upperLimit; - float m_limitSoftness; - float m_biasFactor; - float m_relaxationFactor; - + int m_useReferenceFrameA; + int m_angularOnly; + + int m_enableAngularMotor; + float m_motorTargetVelocity; + float m_maxMotorImpulse; + + float m_lowerLimit; + float m_upperLimit; + float m_limitSoftness; + float m_biasFactor; + float m_relaxationFactor; }; - - ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 -struct btHingeConstraintDoubleData2 +struct btHingeConstraintDoubleData2 { - btTypedConstraintDoubleData m_typeConstraintData; - btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTypedConstraintDoubleData m_typeConstraintData; + btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. btTransformDoubleData m_rbBFrame; - int m_useReferenceFrameA; - int m_angularOnly; - int m_enableAngularMotor; - double m_motorTargetVelocity; - double m_maxMotorImpulse; - - double m_lowerLimit; - double m_upperLimit; - double m_limitSoftness; - double m_biasFactor; - double m_relaxationFactor; - char m_padding1[4]; - + int m_useReferenceFrameA; + int m_angularOnly; + int m_enableAngularMotor; + double m_motorTargetVelocity; + double m_maxMotorImpulse; + + double m_lowerLimit; + double m_upperLimit; + double m_limitSoftness; + double m_biasFactor; + double m_relaxationFactor; + char m_padding1[4]; }; - - - -SIMD_FORCE_INLINE int btHingeConstraint::calculateSerializeBufferSize() const +SIMD_FORCE_INLINE int btHingeConstraint::calculateSerializeBufferSize() const { return sizeof(btHingeConstraintData); } - ///fills the dataBuffer and returns the struct name (and 0 on failure) -SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btSerializer* serializer) const { btHingeConstraintData* hingeData = (btHingeConstraintData*)dataBuffer; - btTypedConstraint::serialize(&hingeData->m_typeConstraintData,serializer); + btTypedConstraint::serialize(&hingeData->m_typeConstraintData, serializer); m_rbAFrame.serialize(hingeData->m_rbAFrame); m_rbBFrame.serialize(hingeData->m_rbBFrame); @@ -475,7 +452,7 @@ SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btS hingeData->m_maxMotorImpulse = float(m_maxMotorImpulse); hingeData->m_motorTargetVelocity = float(m_motorTargetVelocity); hingeData->m_useReferenceFrameA = m_useReferenceFrameA; -#ifdef _BT_USE_CENTER_LIMIT_ +#ifdef _BT_USE_CENTER_LIMIT_ hingeData->m_lowerLimit = float(m_limit.getLow()); hingeData->m_upperLimit = float(m_limit.getHigh()); hingeData->m_limitSoftness = float(m_limit.getSoftness()); @@ -500,4 +477,4 @@ SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btS return btHingeConstraintDataName; } -#endif //BT_HINGECONSTRAINT_H +#endif //BT_HINGECONSTRAINT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h index 125580d199..438456fe51 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h @@ -18,7 +18,6 @@ subject to the following restrictions: #include "LinearMath/btMatrix3x3.h" - //notes: // Another memory optimization would be to store m_1MinvJt in the remaining 3 w components // which makes the btJacobianEntry memory layout 16 bytes @@ -27,25 +26,26 @@ subject to the following restrictions: /// Jacobian entry is an abstraction that allows to describe constraints /// it can be used in combination with a constraint solver /// Can be used to relate the effect of an impulse to the constraint error -ATTRIBUTE_ALIGNED16(class) btJacobianEntry +ATTRIBUTE_ALIGNED16(class) +btJacobianEntry { public: - btJacobianEntry() {}; + btJacobianEntry(){}; //constraint between two different rigidbodies btJacobianEntry( const btMatrix3x3& world2A, const btMatrix3x3& world2B, - const btVector3& rel_pos1,const btVector3& rel_pos2, + const btVector3& rel_pos1, const btVector3& rel_pos2, const btVector3& jointAxis, - const btVector3& inertiaInvA, + const btVector3& inertiaInvA, const btScalar massInvA, const btVector3& inertiaInvB, const btScalar massInvB) - :m_linearJointAxis(jointAxis) + : m_linearJointAxis(jointAxis) { - m_aJ = world2A*(rel_pos1.cross(m_linearJointAxis)); - m_bJ = world2B*(rel_pos2.cross(-m_linearJointAxis)); - m_0MinvJt = inertiaInvA * m_aJ; + m_aJ = world2A * (rel_pos1.cross(m_linearJointAxis)); + m_bJ = world2B * (rel_pos2.cross(-m_linearJointAxis)); + m_0MinvJt = inertiaInvA * m_aJ; m_1MinvJt = inertiaInvB * m_bJ; m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ); @@ -54,33 +54,31 @@ public: //angular constraint between two different rigidbodies btJacobianEntry(const btVector3& jointAxis, - const btMatrix3x3& world2A, - const btMatrix3x3& world2B, - const btVector3& inertiaInvA, - const btVector3& inertiaInvB) - :m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.))) + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + const btVector3& inertiaInvA, + const btVector3& inertiaInvB) + : m_linearJointAxis(btVector3(btScalar(0.), btScalar(0.), btScalar(0.))) { - m_aJ= world2A*jointAxis; - m_bJ = world2B*-jointAxis; - m_0MinvJt = inertiaInvA * m_aJ; + m_aJ = world2A * jointAxis; + m_bJ = world2B * -jointAxis; + m_0MinvJt = inertiaInvA * m_aJ; m_1MinvJt = inertiaInvB * m_bJ; - m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); + m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); btAssert(m_Adiag > btScalar(0.0)); } //angular constraint between two different rigidbodies btJacobianEntry(const btVector3& axisInA, - const btVector3& axisInB, - const btVector3& inertiaInvA, - const btVector3& inertiaInvB) - : m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.))) - , m_aJ(axisInA) - , m_bJ(-axisInB) + const btVector3& axisInB, + const btVector3& inertiaInvA, + const btVector3& inertiaInvB) + : m_linearJointAxis(btVector3(btScalar(0.), btScalar(0.), btScalar(0.))), m_aJ(axisInA), m_bJ(-axisInB) { - m_0MinvJt = inertiaInvA * m_aJ; + m_0MinvJt = inertiaInvA * m_aJ; m_1MinvJt = inertiaInvB * m_bJ; - m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); + m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); btAssert(m_Adiag > btScalar(0.0)); } @@ -88,25 +86,25 @@ public: //constraint on one rigidbody btJacobianEntry( const btMatrix3x3& world2A, - const btVector3& rel_pos1,const btVector3& rel_pos2, + const btVector3& rel_pos1, const btVector3& rel_pos2, const btVector3& jointAxis, - const btVector3& inertiaInvA, + const btVector3& inertiaInvA, const btScalar massInvA) - :m_linearJointAxis(jointAxis) + : m_linearJointAxis(jointAxis) { - m_aJ= world2A*(rel_pos1.cross(jointAxis)); - m_bJ = world2A*(rel_pos2.cross(-jointAxis)); - m_0MinvJt = inertiaInvA * m_aJ; - m_1MinvJt = btVector3(btScalar(0.),btScalar(0.),btScalar(0.)); + m_aJ = world2A * (rel_pos1.cross(jointAxis)); + m_bJ = world2A * (rel_pos2.cross(-jointAxis)); + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = btVector3(btScalar(0.), btScalar(0.), btScalar(0.)); m_Adiag = massInvA + m_0MinvJt.dot(m_aJ); btAssert(m_Adiag > btScalar(0.0)); } - btScalar getDiagonal() const { return m_Adiag; } + btScalar getDiagonal() const { return m_Adiag; } // for two constraints on the same rigidbody (for example vehicle friction) - btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA) const + btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA) const { const btJacobianEntry& jacA = *this; btScalar lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis); @@ -114,42 +112,39 @@ public: return lin + ang; } - - // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies) - btScalar getNonDiagonal(const btJacobianEntry& jacB,const btScalar massInvA,const btScalar massInvB) const + btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA, const btScalar massInvB) const { const btJacobianEntry& jacA = *this; btVector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis; btVector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ; btVector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ; - btVector3 lin0 = massInvA * lin ; + btVector3 lin0 = massInvA * lin; btVector3 lin1 = massInvB * lin; - btVector3 sum = ang0+ang1+lin0+lin1; - return sum[0]+sum[1]+sum[2]; + btVector3 sum = ang0 + ang1 + lin0 + lin1; + return sum[0] + sum[1] + sum[2]; } - btScalar getRelativeVelocity(const btVector3& linvelA,const btVector3& angvelA,const btVector3& linvelB,const btVector3& angvelB) + btScalar getRelativeVelocity(const btVector3& linvelA, const btVector3& angvelA, const btVector3& linvelB, const btVector3& angvelB) { btVector3 linrel = linvelA - linvelB; - btVector3 angvela = angvelA * m_aJ; - btVector3 angvelb = angvelB * m_bJ; + btVector3 angvela = angvelA * m_aJ; + btVector3 angvelb = angvelB * m_bJ; linrel *= m_linearJointAxis; angvela += angvelb; angvela += linrel; - btScalar rel_vel2 = angvela[0]+angvela[1]+angvela[2]; + btScalar rel_vel2 = angvela[0] + angvela[1] + angvela[2]; return rel_vel2 + SIMD_EPSILON; } -//private: + //private: - btVector3 m_linearJointAxis; - btVector3 m_aJ; - btVector3 m_bJ; - btVector3 m_0MinvJt; - btVector3 m_1MinvJt; + btVector3 m_linearJointAxis; + btVector3 m_aJ; + btVector3 m_bJ; + btVector3 m_0MinvJt; + btVector3 m_1MinvJt; //Optimization: can be stored in the w/last component of one of the vectors - btScalar m_Adiag; - + btScalar m_Adiag; }; -#endif //BT_JACOBIAN_ENTRY_H +#endif //BT_JACOBIAN_ENTRY_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp index f3979be358..ccf8916049 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp @@ -15,14 +15,9 @@ subject to the following restrictions: #include "btNNCGConstraintSolver.h" - - - - - -btScalar btNNCGConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) +btScalar btNNCGConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) { - btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup( bodies,numBodies,manifoldPtr, numManifolds, constraints,numConstraints,infoGlobal,debugDrawer); + btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer); m_pNC.resizeNoInitialize(m_tmpSolverNonContactConstraintPool.size()); m_pC.resizeNoInitialize(m_tmpSolverContactConstraintPool.size()); @@ -37,38 +32,39 @@ btScalar btNNCGConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject* return val; } -btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */,int /*numBodies*/,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/) +btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/) { - int numNonContactPool = m_tmpSolverNonContactConstraintPool.size(); int numConstraintPool = m_tmpSolverContactConstraintPool.size(); int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size(); if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER) { - if (1) // uncomment this for a bit less random ((iteration & 7) == 0) + if (1) // uncomment this for a bit less random ((iteration & 7) == 0) { - - for (int j=0; j<numNonContactPool; ++j) { + for (int j = 0; j < numNonContactPool; ++j) + { int tmp = m_orderNonContactConstraintPool[j]; - int swapi = btRandInt2(j+1); + int swapi = btRandInt2(j + 1); m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi]; m_orderNonContactConstraintPool[swapi] = tmp; } - //contact/friction constraints are not solved more than - if (iteration< infoGlobal.m_numIterations) + //contact/friction constraints are not solved more than + if (iteration < infoGlobal.m_numIterations) { - for (int j=0; j<numConstraintPool; ++j) { + for (int j = 0; j < numConstraintPool; ++j) + { int tmp = m_orderTmpConstraintPool[j]; - int swapi = btRandInt2(j+1); + int swapi = btRandInt2(j + 1); m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi]; m_orderTmpConstraintPool[swapi] = tmp; } - for (int j=0; j<numFrictionPool; ++j) { + for (int j = 0; j < numFrictionPool; ++j) + { int tmp = m_orderFrictionConstraintPool[j]; - int swapi = btRandInt2(j+1); + int swapi = btRandInt2(j + 1); m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi]; m_orderFrictionConstraintPool[swapi] = tmp; } @@ -76,39 +72,40 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision } } - btScalar deltaflengthsqr = 0; { - for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) + for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) { btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]]; - if (iteration < constraint.m_overrideNumSolverIterations) + if (iteration < constraint.m_overrideNumSolverIterations) { - btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint); + btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint); m_deltafNC[j] = deltaf; deltaflengthsqr += deltaf * deltaf; } } } - - if (m_onlyForNoneContact) + if (m_onlyForNoneContact) { - if (iteration==0) + if (iteration == 0) + { + for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = m_deltafNC[j]; + } + else { - for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) m_pNC[j] = m_deltafNC[j]; - } else { // deltaflengthsqrprev can be 0 only if the solver solved the problem exactly in the previous iteration. In this case we should have quit, but mainly for debug reason with this 'hack' it is now allowed to continue the calculation - btScalar beta = m_deltafLengthSqrPrev>0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2; - if (beta>1) + btScalar beta = m_deltafLengthSqrPrev > 0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2; + if (beta > 1) { - for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) m_pNC[j] = 0; - } else + for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = 0; + } + else { - for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) + for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) { btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]]; - if (iteration < constraint.m_overrideNumSolverIterations) + if (iteration < constraint.m_overrideNumSolverIterations) { btScalar additionaldeltaimpulse = beta * m_pNC[j]; constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse; @@ -116,8 +113,8 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA]; btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB]; const btSolverConstraint& c = constraint; - body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse); - body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse); + body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse); + body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse); } } } @@ -125,21 +122,18 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision m_deltafLengthSqrPrev = deltaflengthsqr; } - - { - - if (iteration< infoGlobal.m_numIterations) + if (iteration < infoGlobal.m_numIterations) { - for (int j=0;j<numConstraints;j++) + for (int j = 0; j < numConstraints; j++) { if (constraints[j]->isEnabled()) { - int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(),infoGlobal.m_timeStep); - int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep); + int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep); + int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep); btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid]; btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid]; - constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep); + constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep); } } @@ -147,203 +141,206 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS) { int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); - int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)? 2 : 1; + int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1; - for (int c=0;c<numPoolConstraints;c++) + for (int c = 0; c < numPoolConstraints; c++) { - btScalar totalImpulse =0; + btScalar totalImpulse = 0; { const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]]; - btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold); m_deltafC[c] = deltaf; - deltaflengthsqr += deltaf*deltaf; + deltaflengthsqr += deltaf * deltaf; totalImpulse = solveManifold.m_appliedImpulse; } bool applyFriction = true; if (applyFriction) { { + btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]]; - btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier]]; - - if (totalImpulse>btScalar(0)) + if (totalImpulse > btScalar(0)) { - solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); - solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; - btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); - m_deltafCF[c*multiplier] = deltaf; - deltaflengthsqr += deltaf*deltaf; - } else { - m_deltafCF[c*multiplier] = 0; + solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse; + btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold); + m_deltafCF[c * multiplier] = deltaf; + deltaflengthsqr += deltaf * deltaf; + } + else + { + m_deltafCF[c * multiplier] = 0; } } if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) { + btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]]; - btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier+1]]; - - if (totalImpulse>btScalar(0)) + if (totalImpulse > btScalar(0)) + { + solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse; + btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold); + m_deltafCF[c * multiplier + 1] = deltaf; + deltaflengthsqr += deltaf * deltaf; + } + else { - solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); - solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; - btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); - m_deltafCF[c*multiplier+1] = deltaf; - deltaflengthsqr += deltaf*deltaf; - } else { - m_deltafCF[c*multiplier+1] = 0; + m_deltafCF[c * multiplier + 1] = 0; } } } } - } - else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS + else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS { //solve the friction constraints after all contact constraints, don't interleave them int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); int j; - for (j=0;j<numPoolConstraints;j++) + for (j = 0; j < numPoolConstraints; j++) { const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]]; - btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold); m_deltafC[j] = deltaf; - deltaflengthsqr += deltaf*deltaf; + deltaflengthsqr += deltaf * deltaf; } - - ///solve all friction constraints int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size(); - for (j=0;j<numFrictionPoolConstraints;j++) + for (j = 0; j < numFrictionPoolConstraints; j++) { btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]]; btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; - if (totalImpulse>btScalar(0)) + if (totalImpulse > btScalar(0)) { - solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); - solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; + solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse; - btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); + btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold); m_deltafCF[j] = deltaf; - deltaflengthsqr += deltaf*deltaf; - } else { + deltaflengthsqr += deltaf * deltaf; + } + else + { m_deltafCF[j] = 0; } } } - { + { int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size(); - for (int j=0;j<numRollingFrictionPoolConstraints;j++) + for (int j = 0; j < numRollingFrictionPoolConstraints; j++) { - btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j]; btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse; - if (totalImpulse>btScalar(0)) + if (totalImpulse > btScalar(0)) { - btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse; - if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction) + btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse; + if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction) rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; - btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint); + btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint); m_deltafCRF[j] = deltaf; - deltaflengthsqr += deltaf*deltaf; - } else { + deltaflengthsqr += deltaf * deltaf; + } + else + { m_deltafCRF[j] = 0; } } - } - + } } - - - } - - - - if (!m_onlyForNoneContact) + if (!m_onlyForNoneContact) { - if (iteration==0) + if (iteration == 0) { - for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) m_pNC[j] = m_deltafNC[j]; - for (int j=0;j<m_tmpSolverContactConstraintPool.size();j++) m_pC[j] = m_deltafC[j]; - for (int j=0;j<m_tmpSolverContactFrictionConstraintPool.size();j++) m_pCF[j] = m_deltafCF[j]; - for (int j=0;j<m_tmpSolverContactRollingFrictionConstraintPool.size();j++) m_pCRF[j] = m_deltafCRF[j]; - } else + for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = m_deltafNC[j]; + for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++) m_pC[j] = m_deltafC[j]; + for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++) m_pCF[j] = m_deltafCF[j]; + for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++) m_pCRF[j] = m_deltafCRF[j]; + } + else { // deltaflengthsqrprev can be 0 only if the solver solved the problem exactly in the previous iteration. In this case we should have quit, but mainly for debug reason with this 'hack' it is now allowed to continue the calculation - btScalar beta = m_deltafLengthSqrPrev>0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2; - if (beta>1) { - for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) m_pNC[j] = 0; - for (int j=0;j<m_tmpSolverContactConstraintPool.size();j++) m_pC[j] = 0; - for (int j=0;j<m_tmpSolverContactFrictionConstraintPool.size();j++) m_pCF[j] = 0; - for (int j=0;j<m_tmpSolverContactRollingFrictionConstraintPool.size();j++) m_pCRF[j] = 0; - } else { - for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) + btScalar beta = m_deltafLengthSqrPrev > 0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2; + if (beta > 1) + { + for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = 0; + for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++) m_pC[j] = 0; + for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++) m_pCF[j] = 0; + for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++) m_pCRF[j] = 0; + } + else + { + for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) { btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]]; - if (iteration < constraint.m_overrideNumSolverIterations) { + if (iteration < constraint.m_overrideNumSolverIterations) + { btScalar additionaldeltaimpulse = beta * m_pNC[j]; constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse; m_pNC[j] = beta * m_pNC[j] + m_deltafNC[j]; btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA]; btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB]; const btSolverConstraint& c = constraint; - body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse); - body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse); + body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse); + body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse); } } - for (int j=0;j<m_tmpSolverContactConstraintPool.size();j++) + for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++) { btSolverConstraint& constraint = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]]; - if (iteration< infoGlobal.m_numIterations) { + if (iteration < infoGlobal.m_numIterations) + { btScalar additionaldeltaimpulse = beta * m_pC[j]; constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse; m_pC[j] = beta * m_pC[j] + m_deltafC[j]; btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA]; btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB]; const btSolverConstraint& c = constraint; - body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse); - body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse); + body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse); + body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse); } } - for (int j=0;j<m_tmpSolverContactFrictionConstraintPool.size();j++) + for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++) { btSolverConstraint& constraint = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]]; - if (iteration< infoGlobal.m_numIterations) { + if (iteration < infoGlobal.m_numIterations) + { btScalar additionaldeltaimpulse = beta * m_pCF[j]; constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse; m_pCF[j] = beta * m_pCF[j] + m_deltafCF[j]; btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA]; btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB]; const btSolverConstraint& c = constraint; - body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse); - body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse); + body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse); + body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse); } } { - for (int j=0;j<m_tmpSolverContactRollingFrictionConstraintPool.size();j++) + for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++) { btSolverConstraint& constraint = m_tmpSolverContactRollingFrictionConstraintPool[j]; - if (iteration< infoGlobal.m_numIterations) { + if (iteration < infoGlobal.m_numIterations) + { btScalar additionaldeltaimpulse = beta * m_pCRF[j]; constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse; m_pCRF[j] = beta * m_pCRF[j] + m_deltafCRF[j]; btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA]; btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB]; const btSolverConstraint& c = constraint; - body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,additionaldeltaimpulse); - body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse); + body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse); + body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse); } } } @@ -355,7 +352,7 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision return deltaflengthsqr; } -btScalar btNNCGConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal) +btScalar btNNCGConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal) { m_pNC.resizeNoInitialize(0); m_pC.resizeNoInitialize(0); @@ -369,6 +366,3 @@ btScalar btNNCGConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal); } - - - diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h index a300929cd5..c84f274a99 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h @@ -18,33 +18,30 @@ subject to the following restrictions: #include "btSequentialImpulseConstraintSolver.h" -ATTRIBUTE_ALIGNED16(class) btNNCGConstraintSolver : public btSequentialImpulseConstraintSolver +ATTRIBUTE_ALIGNED16(class) +btNNCGConstraintSolver : public btSequentialImpulseConstraintSolver { protected: - btScalar m_deltafLengthSqrPrev; - btAlignedObjectArray<btScalar> m_pNC; // p for None Contact constraints - btAlignedObjectArray<btScalar> m_pC; // p for Contact constraints - btAlignedObjectArray<btScalar> m_pCF; // p for ContactFriction constraints - btAlignedObjectArray<btScalar> m_pCRF; // p for ContactRollingFriction constraints + btAlignedObjectArray<btScalar> m_pNC; // p for None Contact constraints + btAlignedObjectArray<btScalar> m_pC; // p for Contact constraints + btAlignedObjectArray<btScalar> m_pCF; // p for ContactFriction constraints + btAlignedObjectArray<btScalar> m_pCRF; // p for ContactRollingFriction constraints //These are recalculated in every iterations. We just keep these to prevent reallocation in each iteration. - btAlignedObjectArray<btScalar> m_deltafNC; // deltaf for NoneContact constraints - btAlignedObjectArray<btScalar> m_deltafC; // deltaf for Contact constraints - btAlignedObjectArray<btScalar> m_deltafCF; // deltaf for ContactFriction constraints - btAlignedObjectArray<btScalar> m_deltafCRF; // deltaf for ContactRollingFriction constraints + btAlignedObjectArray<btScalar> m_deltafNC; // deltaf for NoneContact constraints + btAlignedObjectArray<btScalar> m_deltafC; // deltaf for Contact constraints + btAlignedObjectArray<btScalar> m_deltafCF; // deltaf for ContactFriction constraints + btAlignedObjectArray<btScalar> m_deltafCRF; // deltaf for ContactRollingFriction constraints - protected: + virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal); + virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer); - virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal); - virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); - - virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); + virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer); public: - BT_DECLARE_ALIGNED_ALLOCATOR(); btNNCGConstraintSolver() : btSequentialImpulseConstraintSolver(), m_onlyForNoneContact(false) {} @@ -57,8 +54,4 @@ public: bool m_onlyForNoneContact; }; - - - -#endif //BT_NNCG_CONSTRAINT_SOLVER_H - +#endif //BT_NNCG_CONSTRAINT_SOLVER_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp index 3c0430b903..ad399dc57f 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp @@ -13,217 +13,193 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ - #include "btPoint2PointConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include <new> - - - - -btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB) -:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB), -m_flags(0), -m_useSolveConstraintObsolete(false) +btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& pivotInA, const btVector3& pivotInB) + : btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE, rbA, rbB), m_pivotInA(pivotInA), m_pivotInB(pivotInB), m_flags(0), m_useSolveConstraintObsolete(false) { - } - -btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA) -:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)), -m_flags(0), -m_useSolveConstraintObsolete(false) +btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA, const btVector3& pivotInA) + : btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE, rbA), m_pivotInA(pivotInA), m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)), m_flags(0), m_useSolveConstraintObsolete(false) { - } -void btPoint2PointConstraint::buildJacobian() +void btPoint2PointConstraint::buildJacobian() { - ///we need it for both methods { m_appliedImpulse = btScalar(0.); - btVector3 normal(0,0,0); + btVector3 normal(0, 0, 0); - for (int i=0;i<3;i++) + for (int i = 0; i < 3; i++) { normal[i] = 1; new (&m_jac[i]) btJacobianEntry( - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(), - m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(), - normal, - m_rbA.getInvInertiaDiagLocal(), - m_rbA.getInvMass(), - m_rbB.getInvInertiaDiagLocal(), - m_rbB.getInvMass()); - normal[i] = 0; + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getCenterOfMassTransform() * m_pivotInA - m_rbA.getCenterOfMassPosition(), + m_rbB.getCenterOfMassTransform() * m_pivotInB - m_rbB.getCenterOfMassPosition(), + normal, + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + normal[i] = 0; } } - - } -void btPoint2PointConstraint::getInfo1 (btConstraintInfo1* info) +void btPoint2PointConstraint::getInfo1(btConstraintInfo1* info) { getInfo1NonVirtual(info); } -void btPoint2PointConstraint::getInfo1NonVirtual (btConstraintInfo1* info) +void btPoint2PointConstraint::getInfo1NonVirtual(btConstraintInfo1* info) { if (m_useSolveConstraintObsolete) { info->m_numConstraintRows = 0; info->nub = 0; - } else + } + else { info->m_numConstraintRows = 3; info->nub = 3; } } - - - -void btPoint2PointConstraint::getInfo2 (btConstraintInfo2* info) +void btPoint2PointConstraint::getInfo2(btConstraintInfo2* info) { - getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform()); } -void btPoint2PointConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans) +void btPoint2PointConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans) { btAssert(!m_useSolveConstraintObsolete); - //retrieve matrices + //retrieve matrices // anchor points in global coordinates with respect to body PORs. - - // set jacobian - info->m_J1linearAxis[0] = 1; - info->m_J1linearAxis[info->rowskip+1] = 1; - info->m_J1linearAxis[2*info->rowskip+2] = 1; - btVector3 a1 = body0_trans.getBasis()*getPivotInA(); + // set jacobian + info->m_J1linearAxis[0] = 1; + info->m_J1linearAxis[info->rowskip + 1] = 1; + info->m_J1linearAxis[2 * info->rowskip + 2] = 1; + + btVector3 a1 = body0_trans.getBasis() * getPivotInA(); { btVector3* angular0 = (btVector3*)(info->m_J1angularAxis); - btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip); - btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip); + btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * info->rowskip); btVector3 a1neg = -a1; - a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2); + a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2); } - + info->m_J2linearAxis[0] = -1; - info->m_J2linearAxis[info->rowskip+1] = -1; - info->m_J2linearAxis[2*info->rowskip+2] = -1; - - btVector3 a2 = body1_trans.getBasis()*getPivotInB(); - + info->m_J2linearAxis[info->rowskip + 1] = -1; + info->m_J2linearAxis[2 * info->rowskip + 2] = -1; + + btVector3 a2 = body1_trans.getBasis() * getPivotInB(); + { - // btVector3 a2n = -a2; + // btVector3 a2n = -a2; btVector3* angular0 = (btVector3*)(info->m_J2angularAxis); - btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip); - btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip); - a2.getSkewSymmetricMatrix(angular0,angular1,angular2); + btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + info->rowskip); + btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * info->rowskip); + a2.getSkewSymmetricMatrix(angular0, angular1, angular2); } - - - // set right hand side + // set right hand side btScalar currERP = (m_flags & BT_P2P_FLAGS_ERP) ? m_erp : info->erp; - btScalar k = info->fps * currERP; - int j; - for (j=0; j<3; j++) - { - info->m_constraintError[j*info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]); + btScalar k = info->fps * currERP; + int j; + for (j = 0; j < 3; j++) + { + info->m_constraintError[j * info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]); //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]); - } - if(m_flags & BT_P2P_FLAGS_CFM) + } + if (m_flags & BT_P2P_FLAGS_CFM) { - for (j=0; j<3; j++) + for (j = 0; j < 3; j++) { - info->cfm[j*info->rowskip] = m_cfm; + info->cfm[j * info->rowskip] = m_cfm; } } - btScalar impulseClamp = m_setting.m_impulseClamp;// - for (j=0; j<3; j++) - { + btScalar impulseClamp = m_setting.m_impulseClamp; // + for (j = 0; j < 3; j++) + { if (m_setting.m_impulseClamp > 0) { - info->m_lowerLimit[j*info->rowskip] = -impulseClamp; - info->m_upperLimit[j*info->rowskip] = impulseClamp; + info->m_lowerLimit[j * info->rowskip] = -impulseClamp; + info->m_upperLimit[j * info->rowskip] = impulseClamp; } } info->m_damping = m_setting.m_damping; - } - - -void btPoint2PointConstraint::updateRHS(btScalar timeStep) +void btPoint2PointConstraint::updateRHS(btScalar timeStep) { (void)timeStep; - } -///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). +///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). ///If no axis is provided, it uses the default axis for this constraint. void btPoint2PointConstraint::setParam(int num, btScalar value, int axis) { - if(axis != -1) + if (axis != -1) { btAssertConstrParams(0); } else { - switch(num) + switch (num) { - case BT_CONSTRAINT_ERP : - case BT_CONSTRAINT_STOP_ERP : - m_erp = value; + case BT_CONSTRAINT_ERP: + case BT_CONSTRAINT_STOP_ERP: + m_erp = value; m_flags |= BT_P2P_FLAGS_ERP; break; - case BT_CONSTRAINT_CFM : - case BT_CONSTRAINT_STOP_CFM : - m_cfm = value; + case BT_CONSTRAINT_CFM: + case BT_CONSTRAINT_STOP_CFM: + m_cfm = value; m_flags |= BT_P2P_FLAGS_CFM; break; - default: + default: btAssertConstrParams(0); } } } ///return the local value of parameter -btScalar btPoint2PointConstraint::getParam(int num, int axis) const +btScalar btPoint2PointConstraint::getParam(int num, int axis) const { btScalar retVal(SIMD_INFINITY); - if(axis != -1) + if (axis != -1) { btAssertConstrParams(0); } else { - switch(num) + switch (num) { - case BT_CONSTRAINT_ERP : - case BT_CONSTRAINT_STOP_ERP : + case BT_CONSTRAINT_ERP: + case BT_CONSTRAINT_STOP_ERP: btAssertConstrParams(m_flags & BT_P2P_FLAGS_ERP); - retVal = m_erp; + retVal = m_erp; break; - case BT_CONSTRAINT_CFM : - case BT_CONSTRAINT_STOP_CFM : + case BT_CONSTRAINT_CFM: + case BT_CONSTRAINT_STOP_CFM: btAssertConstrParams(m_flags & BT_P2P_FLAGS_CFM); - retVal = m_cfm; + retVal = m_cfm; break; - default: + default: btAssertConstrParams(0); } } return retVal; } - diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h index 8fa03d719d..4717e19800 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h @@ -22,26 +22,24 @@ subject to the following restrictions: class btRigidBody; - #ifdef BT_USE_DOUBLE_PRECISION -#define btPoint2PointConstraintData2 btPoint2PointConstraintDoubleData2 -#define btPoint2PointConstraintDataName "btPoint2PointConstraintDoubleData2" +#define btPoint2PointConstraintData2 btPoint2PointConstraintDoubleData2 +#define btPoint2PointConstraintDataName "btPoint2PointConstraintDoubleData2" #else -#define btPoint2PointConstraintData2 btPoint2PointConstraintFloatData -#define btPoint2PointConstraintDataName "btPoint2PointConstraintFloatData" -#endif //BT_USE_DOUBLE_PRECISION +#define btPoint2PointConstraintData2 btPoint2PointConstraintFloatData +#define btPoint2PointConstraintDataName "btPoint2PointConstraintFloatData" +#endif //BT_USE_DOUBLE_PRECISION -struct btConstraintSetting +struct btConstraintSetting { - btConstraintSetting() : - m_tau(btScalar(0.3)), - m_damping(btScalar(1.)), - m_impulseClamp(btScalar(0.)) + btConstraintSetting() : m_tau(btScalar(0.3)), + m_damping(btScalar(1.)), + m_impulseClamp(btScalar(0.)) { } - btScalar m_tau; - btScalar m_damping; - btScalar m_impulseClamp; + btScalar m_tau; + btScalar m_damping; + btScalar m_impulseClamp; }; enum btPoint2PointFlags @@ -51,52 +49,51 @@ enum btPoint2PointFlags }; /// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space -ATTRIBUTE_ALIGNED16(class) btPoint2PointConstraint : public btTypedConstraint +ATTRIBUTE_ALIGNED16(class) +btPoint2PointConstraint : public btTypedConstraint { #ifdef IN_PARALLELL_SOLVER public: #endif - btJacobianEntry m_jac[3]; //3 orthogonal linear constraints - - btVector3 m_pivotInA; - btVector3 m_pivotInB; - - int m_flags; - btScalar m_erp; - btScalar m_cfm; - -public: + btJacobianEntry m_jac[3]; //3 orthogonal linear constraints + + btVector3 m_pivotInA; + btVector3 m_pivotInB; + + int m_flags; + btScalar m_erp; + btScalar m_cfm; +public: BT_DECLARE_ALIGNED_ALLOCATOR(); ///for backwards compatibility during the transition to 'getInfo/getInfo2' - bool m_useSolveConstraintObsolete; - - btConstraintSetting m_setting; + bool m_useSolveConstraintObsolete; - btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB); + btConstraintSetting m_setting; - btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA); + btPoint2PointConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& pivotInA, const btVector3& pivotInB); + btPoint2PointConstraint(btRigidBody & rbA, const btVector3& pivotInA); - virtual void buildJacobian(); + virtual void buildJacobian(); - virtual void getInfo1 (btConstraintInfo1* info); + virtual void getInfo1(btConstraintInfo1 * info); - void getInfo1NonVirtual (btConstraintInfo1* info); + void getInfo1NonVirtual(btConstraintInfo1 * info); - virtual void getInfo2 (btConstraintInfo2* info); + virtual void getInfo2(btConstraintInfo2 * info); - void getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans); + void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& body0_trans, const btTransform& body1_trans); - void updateRHS(btScalar timeStep); + void updateRHS(btScalar timeStep); - void setPivotA(const btVector3& pivotA) + void setPivotA(const btVector3& pivotA) { m_pivotInA = pivotA; } - void setPivotB(const btVector3& pivotB) + void setPivotB(const btVector3& pivotB) { m_pivotInB = pivotB; } @@ -111,70 +108,66 @@ public: return m_pivotInB; } - ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). ///If no axis is provided, it uses the default axis for this constraint. - virtual void setParam(int num, btScalar value, int axis = -1); + virtual void setParam(int num, btScalar value, int axis = -1); ///return the local value of parameter - virtual btScalar getParam(int num, int axis = -1) const; - - virtual int getFlags() const + virtual btScalar getParam(int num, int axis = -1) const; + + virtual int getFlags() const { - return m_flags; - } + return m_flags; + } - virtual int calculateSerializeBufferSize() const; + virtual int calculateSerializeBufferSize() const; ///fills the dataBuffer and returns the struct name (and 0 on failure) - virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; - - + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; }; ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 -struct btPoint2PointConstraintFloatData +struct btPoint2PointConstraintFloatData { - btTypedConstraintData m_typeConstraintData; - btVector3FloatData m_pivotInA; - btVector3FloatData m_pivotInB; + btTypedConstraintData m_typeConstraintData; + btVector3FloatData m_pivotInA; + btVector3FloatData m_pivotInB; }; ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 -struct btPoint2PointConstraintDoubleData2 +struct btPoint2PointConstraintDoubleData2 { - btTypedConstraintDoubleData m_typeConstraintData; - btVector3DoubleData m_pivotInA; - btVector3DoubleData m_pivotInB; + btTypedConstraintDoubleData m_typeConstraintData; + btVector3DoubleData m_pivotInA; + btVector3DoubleData m_pivotInB; }; #ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ///this structure is not used, except for loading pre-2.82 .bullet files ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 -struct btPoint2PointConstraintDoubleData +struct btPoint2PointConstraintDoubleData { - btTypedConstraintData m_typeConstraintData; - btVector3DoubleData m_pivotInA; - btVector3DoubleData m_pivotInB; + btTypedConstraintData m_typeConstraintData; + btVector3DoubleData m_pivotInA; + btVector3DoubleData m_pivotInB; }; -#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION +#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION - -SIMD_FORCE_INLINE int btPoint2PointConstraint::calculateSerializeBufferSize() const +SIMD_FORCE_INLINE int btPoint2PointConstraint::calculateSerializeBufferSize() const { return sizeof(btPoint2PointConstraintData2); - } - ///fills the dataBuffer and returns the struct name (and 0 on failure) -SIMD_FORCE_INLINE const char* btPoint2PointConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btPoint2PointConstraint::serialize(void* dataBuffer, btSerializer* serializer) const { btPoint2PointConstraintData2* p2pData = (btPoint2PointConstraintData2*)dataBuffer; - btTypedConstraint::serialize(&p2pData->m_typeConstraintData,serializer); + btTypedConstraint::serialize(&p2pData->m_typeConstraintData, serializer); m_pivotInA.serialize(p2pData->m_pivotInA); m_pivotInB.serialize(p2pData->m_pivotInB); return btPoint2PointConstraintDataName; } -#endif //BT_POINT2POINTCONSTRAINT_H +#endif //BT_POINT2POINTCONSTRAINT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp index 63174a6ec0..def3227b43 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -21,7 +21,6 @@ subject to the following restrictions: #include "btSequentialImpulseConstraintSolver.h" #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" - #include "LinearMath/btIDebugDraw.h" #include "LinearMath/btCpuFeatureUtility.h" @@ -34,9 +33,9 @@ subject to the following restrictions: //#include "btSolverBody.h" //#include "btSolverConstraint.h" #include "LinearMath/btAlignedObjectArray.h" -#include <string.h> //for memset +#include <string.h> //for memset -int gNumSplitImpulseRecoveries = 0; +int gNumSplitImpulseRecoveries = 0; #include "BulletDynamics/Dynamics/btRigidBody.h" @@ -45,13 +44,13 @@ int gNumSplitImpulseRecoveries = 0; ///Below are optional SSE2 and SSE4/FMA3 versions. We assume most hardware has SSE2. For SSE4/FMA3 we perform a CPU feature check. static btScalar gResolveSingleConstraintRowGeneric_scalar_reference(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c) { - btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm; + btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm; const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetDeltaAngularVelocity()); const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetDeltaAngularVelocity()); // const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn; - deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv; - deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv; + deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv; + deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv; const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse; if (sum < c.m_lowerLimit) @@ -69,21 +68,20 @@ static btScalar gResolveSingleConstraintRowGeneric_scalar_reference(btSolverBody c.m_appliedImpulse = sum; } - bodyA.internalApplyImpulse(c.m_contactNormal1*bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse); - bodyB.internalApplyImpulse(c.m_contactNormal2*bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse); + bodyA.internalApplyImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse); + bodyB.internalApplyImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse); - return deltaImpulse*(1./c.m_jacDiagABInv); + return deltaImpulse * (1. / c.m_jacDiagABInv); } - static btScalar gResolveSingleConstraintRowLowerLimit_scalar_reference(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c) { - btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm; + btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm; const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetDeltaAngularVelocity()); const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetDeltaAngularVelocity()); - deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv; - deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv; + deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv; + deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv; const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse; if (sum < c.m_lowerLimit) { @@ -94,58 +92,55 @@ static btScalar gResolveSingleConstraintRowLowerLimit_scalar_reference(btSolverB { c.m_appliedImpulse = sum; } - bodyA.internalApplyImpulse(c.m_contactNormal1*bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse); - bodyB.internalApplyImpulse(c.m_contactNormal2*bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse); + bodyA.internalApplyImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse); + bodyB.internalApplyImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse); - return deltaImpulse*(1./c.m_jacDiagABInv); + return deltaImpulse * (1. / c.m_jacDiagABInv); } - - #ifdef USE_SIMD #include <emmintrin.h> - -#define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e)) -static inline __m128 btSimdDot3( __m128 vec0, __m128 vec1 ) +#define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e, e, e, e)) +static inline __m128 btSimdDot3(__m128 vec0, __m128 vec1) { - __m128 result = _mm_mul_ps( vec0, vec1); - return _mm_add_ps( btVecSplat( result, 0 ), _mm_add_ps( btVecSplat( result, 1 ), btVecSplat( result, 2 ) ) ); + __m128 result = _mm_mul_ps(vec0, vec1); + return _mm_add_ps(btVecSplat(result, 0), _mm_add_ps(btVecSplat(result, 1), btVecSplat(result, 2))); } -#if defined (BT_ALLOW_SSE4) +#if defined(BT_ALLOW_SSE4) #include <intrin.h> -#define USE_FMA 1 -#define USE_FMA3_INSTEAD_FMA4 1 -#define USE_SSE4_DOT 1 +#define USE_FMA 1 +#define USE_FMA3_INSTEAD_FMA4 1 +#define USE_SSE4_DOT 1 -#define SSE4_DP(a, b) _mm_dp_ps(a, b, 0x7f) -#define SSE4_DP_FP(a, b) _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7f)) +#define SSE4_DP(a, b) _mm_dp_ps(a, b, 0x7f) +#define SSE4_DP_FP(a, b) _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7f)) #if USE_SSE4_DOT -#define DOT_PRODUCT(a, b) SSE4_DP(a, b) +#define DOT_PRODUCT(a, b) SSE4_DP(a, b) #else -#define DOT_PRODUCT(a, b) btSimdDot3(a, b) +#define DOT_PRODUCT(a, b) btSimdDot3(a, b) #endif #if USE_FMA #if USE_FMA3_INSTEAD_FMA4 // a*b + c -#define FMADD(a, b, c) _mm_fmadd_ps(a, b, c) +#define FMADD(a, b, c) _mm_fmadd_ps(a, b, c) // -(a*b) + c -#define FMNADD(a, b, c) _mm_fnmadd_ps(a, b, c) -#else // USE_FMA3 +#define FMNADD(a, b, c) _mm_fnmadd_ps(a, b, c) +#else // USE_FMA3 // a*b + c -#define FMADD(a, b, c) _mm_macc_ps(a, b, c) +#define FMADD(a, b, c) _mm_macc_ps(a, b, c) // -(a*b) + c -#define FMNADD(a, b, c) _mm_nmacc_ps(a, b, c) +#define FMNADD(a, b, c) _mm_nmacc_ps(a, b, c) #endif -#else // USE_FMA +#else // USE_FMA // c + a*b -#define FMADD(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b)) +#define FMADD(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b)) // c - a*b -#define FMNADD(a, b, c) _mm_sub_ps(c, _mm_mul_ps(a, b)) +#define FMNADD(a, b, c) _mm_sub_ps(c, _mm_mul_ps(a, b)) #endif #endif @@ -153,8 +148,8 @@ static inline __m128 btSimdDot3( __m128 vec0, __m128 vec1 ) static btScalar gResolveSingleConstraintRowGeneric_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c) { __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse); - __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); - __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); + __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); + __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); btSimdScalar deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm))); __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128)); __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128)); @@ -170,52 +165,49 @@ static btScalar gResolveSingleConstraintRowGeneric_sse2(btSolverBody& bodyA, btS __m128 upperMinApplied = _mm_sub_ps(upperLimit1, cpAppliedImp); deltaImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied)); c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1)); - __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128); - __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal2).mVec128, bodyB.internalGetInvMass().mVec128); + __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128); + __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal2).mVec128, bodyB.internalGetInvMass().mVec128); __m128 impulseMagnitude = deltaImpulse; bodyA.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude)); bodyA.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude)); bodyB.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude)); bodyB.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude)); - return deltaImpulse.m_floats[0]/c.m_jacDiagABInv; + return deltaImpulse.m_floats[0] / c.m_jacDiagABInv; } - // Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3 static btScalar gResolveSingleConstraintRowGeneric_sse4_1_fma3(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c) { -#if defined (BT_ALLOW_SSE4) - __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv); - __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm); - const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit); - const __m128 upperLimit = _mm_set_ps1(c.m_upperLimit); - const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128)); - const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128)); - deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse); - deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse); - tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse); // sum - const __m128 maskLower = _mm_cmpgt_ps(tmp, lowerLimit); - const __m128 maskUpper = _mm_cmpgt_ps(upperLimit, tmp); - deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), _mm_blendv_ps(_mm_sub_ps(upperLimit, c.m_appliedImpulse), deltaImpulse, maskUpper), maskLower); - c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, _mm_blendv_ps(upperLimit, tmp, maskUpper), maskLower); - bodyA.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128), deltaImpulse, bodyA.internalGetDeltaLinearVelocity().mVec128); +#if defined(BT_ALLOW_SSE4) + __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv); + __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm); + const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit); + const __m128 upperLimit = _mm_set_ps1(c.m_upperLimit); + const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128)); + const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128)); + deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse); + deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse); + tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse); // sum + const __m128 maskLower = _mm_cmpgt_ps(tmp, lowerLimit); + const __m128 maskUpper = _mm_cmpgt_ps(upperLimit, tmp); + deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), _mm_blendv_ps(_mm_sub_ps(upperLimit, c.m_appliedImpulse), deltaImpulse, maskUpper), maskLower); + c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, _mm_blendv_ps(upperLimit, tmp, maskUpper), maskLower); + bodyA.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128), deltaImpulse, bodyA.internalGetDeltaLinearVelocity().mVec128); bodyA.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentA.mVec128, deltaImpulse, bodyA.internalGetDeltaAngularVelocity().mVec128); - bodyB.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128), deltaImpulse, bodyB.internalGetDeltaLinearVelocity().mVec128); + bodyB.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128), deltaImpulse, bodyB.internalGetDeltaLinearVelocity().mVec128); bodyB.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentB.mVec128, deltaImpulse, bodyB.internalGetDeltaAngularVelocity().mVec128); btSimdScalar deltaImp = deltaImpulse; - return deltaImp.m_floats[0]*(1./c.m_jacDiagABInv); + return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv); #else - return gResolveSingleConstraintRowGeneric_sse2(bodyA,bodyB,c); + return gResolveSingleConstraintRowGeneric_sse2(bodyA, bodyB, c); #endif } - - static btScalar gResolveSingleConstraintRowLowerLimit_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c) { __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse); - __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); - __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); + __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); + __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); btSimdScalar deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm))); __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128)); __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128)); @@ -228,104 +220,98 @@ static btScalar gResolveSingleConstraintRowLowerLimit_sse2(btSolverBody& bodyA, __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp); deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse)); c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum)); - __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128); - __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128); + __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128); + __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128); __m128 impulseMagnitude = deltaImpulse; bodyA.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude)); bodyA.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude)); bodyB.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude)); bodyB.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude)); - return deltaImpulse.m_floats[0]/c.m_jacDiagABInv; + return deltaImpulse.m_floats[0] / c.m_jacDiagABInv; } - // Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3 static btScalar gResolveSingleConstraintRowLowerLimit_sse4_1_fma3(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c) { #ifdef BT_ALLOW_SSE4 - __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv); - __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm); - const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit); - const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128)); - const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128)); - deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse); - deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse); - tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse); - const __m128 mask = _mm_cmpgt_ps(tmp, lowerLimit); - deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), deltaImpulse, mask); - c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, tmp, mask); - bodyA.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128), deltaImpulse, bodyA.internalGetDeltaLinearVelocity().mVec128); + __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv); + __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm); + const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit); + const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128)); + const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128)); + deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse); + deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse); + tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse); + const __m128 mask = _mm_cmpgt_ps(tmp, lowerLimit); + deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), deltaImpulse, mask); + c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, tmp, mask); + bodyA.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128), deltaImpulse, bodyA.internalGetDeltaLinearVelocity().mVec128); bodyA.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentA.mVec128, deltaImpulse, bodyA.internalGetDeltaAngularVelocity().mVec128); - bodyB.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128), deltaImpulse, bodyB.internalGetDeltaLinearVelocity().mVec128); + bodyB.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128), deltaImpulse, bodyB.internalGetDeltaLinearVelocity().mVec128); bodyB.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentB.mVec128, deltaImpulse, bodyB.internalGetDeltaAngularVelocity().mVec128); btSimdScalar deltaImp = deltaImpulse; - return deltaImp.m_floats[0]*(1./c.m_jacDiagABInv); + return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv); #else - return gResolveSingleConstraintRowLowerLimit_sse2(bodyA,bodyB,c); -#endif //BT_ALLOW_SSE4 + return gResolveSingleConstraintRowLowerLimit_sse2(bodyA, bodyB, c); +#endif //BT_ALLOW_SSE4 } +#endif //USE_SIMD -#endif //USE_SIMD - - - -btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& c) +btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c) { return m_resolveSingleConstraintRowGeneric(bodyA, bodyB, c); } // Project Gauss Seidel or the equivalent Sequential Impulse -btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& c) +btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c) { return m_resolveSingleConstraintRowGeneric(bodyA, bodyB, c); } -btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& c) +btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c) { return m_resolveSingleConstraintRowLowerLimit(bodyA, bodyB, c); } - -btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& c) +btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c) { return m_resolveSingleConstraintRowLowerLimit(bodyA, bodyB, c); } - static btScalar gResolveSplitPenetrationImpulse_scalar_reference( - btSolverBody& bodyA, - btSolverBody& bodyB, - const btSolverConstraint& c) + btSolverBody& bodyA, + btSolverBody& bodyB, + const btSolverConstraint& c) { btScalar deltaImpulse = 0.f; - if (c.m_rhsPenetration) - { - gNumSplitImpulseRecoveries++; - deltaImpulse = c.m_rhsPenetration-btScalar(c.m_appliedPushImpulse)*c.m_cfm; - const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetTurnVelocity()); - const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetTurnVelocity()); - - deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv; - deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv; - const btScalar sum = btScalar(c.m_appliedPushImpulse) + deltaImpulse; - if (sum < c.m_lowerLimit) - { - deltaImpulse = c.m_lowerLimit-c.m_appliedPushImpulse; - c.m_appliedPushImpulse = c.m_lowerLimit; - } - else - { - c.m_appliedPushImpulse = sum; - } - bodyA.internalApplyPushImpulse(c.m_contactNormal1*bodyA.internalGetInvMass(),c.m_angularComponentA,deltaImpulse); - bodyB.internalApplyPushImpulse(c.m_contactNormal2*bodyB.internalGetInvMass(),c.m_angularComponentB,deltaImpulse); - } - return deltaImpulse*(1./c.m_jacDiagABInv); + if (c.m_rhsPenetration) + { + gNumSplitImpulseRecoveries++; + deltaImpulse = c.m_rhsPenetration - btScalar(c.m_appliedPushImpulse) * c.m_cfm; + const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetTurnVelocity()); + const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetTurnVelocity()); + + deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv; + deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv; + const btScalar sum = btScalar(c.m_appliedPushImpulse) + deltaImpulse; + if (sum < c.m_lowerLimit) + { + deltaImpulse = c.m_lowerLimit - c.m_appliedPushImpulse; + c.m_appliedPushImpulse = c.m_lowerLimit; + } + else + { + c.m_appliedPushImpulse = sum; + } + bodyA.internalApplyPushImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse); + bodyB.internalApplyPushImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse); + } + return deltaImpulse * (1. / c.m_jacDiagABInv); } -static btScalar gResolveSplitPenetrationImpulse_sse2(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& c) +static btScalar gResolveSplitPenetrationImpulse_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c) { #ifdef USE_SIMD if (!c.m_rhsPenetration) @@ -334,113 +320,109 @@ static btScalar gResolveSplitPenetrationImpulse_sse2(btSolverBody& bodyA,btSolve gNumSplitImpulseRecoveries++; __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse); - __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); - __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); - __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse),_mm_set1_ps(c.m_cfm))); - __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128,bodyA.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,bodyA.internalGetTurnVelocity().mVec128)); - __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128,bodyB.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128,bodyB.internalGetTurnVelocity().mVec128)); - deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv))); - deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv))); - btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse); - btSimdScalar resultLowerLess,resultUpperLess; - resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1); - resultUpperLess = _mm_cmplt_ps(sum,upperLimit1); - __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp); - deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) ); - c.m_appliedPushImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) ); - __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128,bodyA.internalGetInvMass().mVec128); - __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128,bodyB.internalGetInvMass().mVec128); + __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit); + __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit); + __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse), _mm_set1_ps(c.m_cfm))); + __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetTurnVelocity().mVec128)); + __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetTurnVelocity().mVec128)); + deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv))); + deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv))); + btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse); + btSimdScalar resultLowerLess, resultUpperLess; + resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1); + resultUpperLess = _mm_cmplt_ps(sum, upperLimit1); + __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp); + deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse)); + c.m_appliedPushImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum)); + __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128); + __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128); __m128 impulseMagnitude = deltaImpulse; - bodyA.internalGetPushVelocity().mVec128 = _mm_add_ps(bodyA.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude)); - bodyA.internalGetTurnVelocity().mVec128 = _mm_add_ps(bodyA.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude)); - bodyB.internalGetPushVelocity().mVec128 = _mm_add_ps(bodyB.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude)); - bodyB.internalGetTurnVelocity().mVec128 = _mm_add_ps(bodyB.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude)); + bodyA.internalGetPushVelocity().mVec128 = _mm_add_ps(bodyA.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude)); + bodyA.internalGetTurnVelocity().mVec128 = _mm_add_ps(bodyA.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude)); + bodyB.internalGetPushVelocity().mVec128 = _mm_add_ps(bodyB.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude)); + bodyB.internalGetTurnVelocity().mVec128 = _mm_add_ps(bodyB.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude)); btSimdScalar deltaImp = deltaImpulse; return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv); #else - return gResolveSplitPenetrationImpulse_scalar_reference(bodyA,bodyB,c); + return gResolveSplitPenetrationImpulse_scalar_reference(bodyA, bodyB, c); #endif } - btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver() { - m_btSeed2 = 0; - m_cachedSolverMode = 0; - setupSolverFunctions( false ); + m_btSeed2 = 0; + m_cachedSolverMode = 0; + setupSolverFunctions(false); } -void btSequentialImpulseConstraintSolver::setupSolverFunctions( bool useSimd ) +void btSequentialImpulseConstraintSolver::setupSolverFunctions(bool useSimd) { - m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_scalar_reference; - m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_scalar_reference; - m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_scalar_reference; + m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_scalar_reference; + m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_scalar_reference; + m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_scalar_reference; - if ( useSimd ) - { + if (useSimd) + { #ifdef USE_SIMD - m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse2; - m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse2; - m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_sse2; + m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse2; + m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse2; + m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_sse2; #ifdef BT_ALLOW_SSE4 - int cpuFeatures = btCpuFeatureUtility::getCpuFeatures(); - if ((cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_FMA3) && (cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_SSE4_1)) - { - m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse4_1_fma3; - m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse4_1_fma3; - } -#endif//BT_ALLOW_SSE4 -#endif //USE_SIMD - } + int cpuFeatures = btCpuFeatureUtility::getCpuFeatures(); + if ((cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_FMA3) && (cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_SSE4_1)) + { + m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse4_1_fma3; + m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse4_1_fma3; + } +#endif //BT_ALLOW_SSE4 +#endif //USE_SIMD + } } - btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver() - { - } - - btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverGeneric() - { - return gResolveSingleConstraintRowGeneric_scalar_reference; - } +btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver() +{ +} - btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverLowerLimit() - { - return gResolveSingleConstraintRowLowerLimit_scalar_reference; - } +btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverGeneric() +{ + return gResolveSingleConstraintRowGeneric_scalar_reference; +} +btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverLowerLimit() +{ + return gResolveSingleConstraintRowLowerLimit_scalar_reference; +} #ifdef USE_SIMD - btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverGeneric() - { - return gResolveSingleConstraintRowGeneric_sse2; - } - btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverLowerLimit() - { - return gResolveSingleConstraintRowLowerLimit_sse2; - } +btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverGeneric() +{ + return gResolveSingleConstraintRowGeneric_sse2; +} +btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverLowerLimit() +{ + return gResolveSingleConstraintRowLowerLimit_sse2; +} #ifdef BT_ALLOW_SSE4 - btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverGeneric() - { - return gResolveSingleConstraintRowGeneric_sse4_1_fma3; - } - btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverLowerLimit() - { - return gResolveSingleConstraintRowLowerLimit_sse4_1_fma3; - } -#endif //BT_ALLOW_SSE4 -#endif //USE_SIMD +btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverGeneric() +{ + return gResolveSingleConstraintRowGeneric_sse4_1_fma3; +} +btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverLowerLimit() +{ + return gResolveSingleConstraintRowLowerLimit_sse4_1_fma3; +} +#endif //BT_ALLOW_SSE4 +#endif //USE_SIMD unsigned long btSequentialImpulseConstraintSolver::btRand2() { - m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff; + m_btSeed2 = (1664525L * m_btSeed2 + 1013904223L) & 0xffffffff; return m_btSeed2; } - - //See ODE: adam's all-int straightforward(?) dRandInt (0..n-1) -int btSequentialImpulseConstraintSolver::btRandInt2 (int n) +int btSequentialImpulseConstraintSolver::btRandInt2(int n) { // seems good; xor-fold and modulus const unsigned long un = static_cast<unsigned long>(n); @@ -448,15 +430,20 @@ int btSequentialImpulseConstraintSolver::btRandInt2 (int n) // note: probably more aggressive than it needs to be -- might be // able to get away without one or two of the innermost branches. - if (un <= 0x00010000UL) { + if (un <= 0x00010000UL) + { r ^= (r >> 16); - if (un <= 0x00000100UL) { + if (un <= 0x00000100UL) + { r ^= (r >> 8); - if (un <= 0x00000010UL) { + if (un <= 0x00000010UL) + { r ^= (r >> 4); - if (un <= 0x00000004UL) { + if (un <= 0x00000004UL) + { r ^= (r >> 2); - if (un <= 0x00000002UL) { + if (un <= 0x00000002UL) + { r ^= (r >> 1); } } @@ -464,70 +451,56 @@ int btSequentialImpulseConstraintSolver::btRandInt2 (int n) } } - return (int) (r % un); + return (int)(r % un); } - - -void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep) +void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep) { + btRigidBody* rb = collisionObject ? btRigidBody::upcast(collisionObject) : 0; - btRigidBody* rb = collisionObject? btRigidBody::upcast(collisionObject) : 0; - - solverBody->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f); - solverBody->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f); - solverBody->internalGetPushVelocity().setValue(0.f,0.f,0.f); - solverBody->internalGetTurnVelocity().setValue(0.f,0.f,0.f); + solverBody->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f); + solverBody->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f); + solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f); + solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f); if (rb) { solverBody->m_worldTransform = rb->getWorldTransform(); - solverBody->internalSetInvMass(btVector3(rb->getInvMass(),rb->getInvMass(),rb->getInvMass())*rb->getLinearFactor()); + solverBody->internalSetInvMass(btVector3(rb->getInvMass(), rb->getInvMass(), rb->getInvMass()) * rb->getLinearFactor()); solverBody->m_originalBody = rb; solverBody->m_angularFactor = rb->getAngularFactor(); solverBody->m_linearFactor = rb->getLinearFactor(); solverBody->m_linearVelocity = rb->getLinearVelocity(); solverBody->m_angularVelocity = rb->getAngularVelocity(); - solverBody->m_externalForceImpulse = rb->getTotalForce()*rb->getInvMass()*timeStep; - solverBody->m_externalTorqueImpulse = rb->getTotalTorque()*rb->getInvInertiaTensorWorld()*timeStep ; - - } else + solverBody->m_externalForceImpulse = rb->getTotalForce() * rb->getInvMass() * timeStep; + solverBody->m_externalTorqueImpulse = rb->getTotalTorque() * rb->getInvInertiaTensorWorld() * timeStep; + } + else { solverBody->m_worldTransform.setIdentity(); - solverBody->internalSetInvMass(btVector3(0,0,0)); + solverBody->internalSetInvMass(btVector3(0, 0, 0)); solverBody->m_originalBody = 0; - solverBody->m_angularFactor.setValue(1,1,1); - solverBody->m_linearFactor.setValue(1,1,1); - solverBody->m_linearVelocity.setValue(0,0,0); - solverBody->m_angularVelocity.setValue(0,0,0); - solverBody->m_externalForceImpulse.setValue(0,0,0); - solverBody->m_externalTorqueImpulse.setValue(0,0,0); + solverBody->m_angularFactor.setValue(1, 1, 1); + solverBody->m_linearFactor.setValue(1, 1, 1); + solverBody->m_linearVelocity.setValue(0, 0, 0); + solverBody->m_angularVelocity.setValue(0, 0, 0); + solverBody->m_externalForceImpulse.setValue(0, 0, 0); + solverBody->m_externalTorqueImpulse.setValue(0, 0, 0); } - - } - - - - - btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold) { //printf("rel_vel =%f\n", rel_vel); - if (btFabs(rel_vel)<velocityThreshold) + if (btFabs(rel_vel) < velocityThreshold) return 0.; btScalar rest = restitution * -rel_vel; return rest; } - - -void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection, int frictionMode) +void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionObject* colObj, btVector3& frictionDirection, int frictionMode) { - - if (colObj && colObj->hasAnisotropicFriction(frictionMode)) { // transform to local coordinates @@ -538,16 +511,10 @@ void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionOb // ... and transform it back to global coordinates frictionDirection = colObj->getWorldTransform().getBasis() * loc_lateral; } - } - - - -void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip) +void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip) { - - btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA]; btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB]; @@ -568,12 +535,13 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr solverConstraint.m_contactNormal1 = normalAxis; btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal1); solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; - solverConstraint.m_angularComponentA = body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor(); - }else + solverConstraint.m_angularComponentA = body0->getInvInertiaTensorWorld() * ftorqueAxis1 * body0->getAngularFactor(); + } + else { solverConstraint.m_contactNormal1.setZero(); solverConstraint.m_relpos1CrossNormal.setZero(); - solverConstraint.m_angularComponentA .setZero(); + solverConstraint.m_angularComponentA.setZero(); } if (bodyA) @@ -581,8 +549,9 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr solverConstraint.m_contactNormal2 = -normalAxis; btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal2); solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; - solverConstraint.m_angularComponentB = bodyA->getInvInertiaTensorWorld()*ftorqueAxis1*bodyA->getAngularFactor(); - } else + solverConstraint.m_angularComponentB = bodyA->getInvInertiaTensorWorld() * ftorqueAxis1 * bodyA->getAngularFactor(); + } + else { solverConstraint.m_contactNormal2.setZero(); solverConstraint.m_relpos2CrossNormal.setZero(); @@ -595,32 +564,28 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr btScalar denom1 = 0.f; if (body0) { - vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + vec = (solverConstraint.m_angularComponentA).cross(rel_pos1); denom0 = body0->getInvMass() + normalAxis.dot(vec); } if (bodyA) { - vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2); + vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2); denom1 = bodyA->getInvMass() + normalAxis.dot(vec); } - btScalar denom = relaxation/(denom0+denom1); + btScalar denom = relaxation / (denom0 + denom1); solverConstraint.m_jacDiagABInv = denom; } { - - btScalar rel_vel; - btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0?solverBodyA.m_linearVelocity+solverBodyA.m_externalForceImpulse:btVector3(0,0,0)) - + solverConstraint.m_relpos1CrossNormal.dot(body0?solverBodyA.m_angularVelocity:btVector3(0,0,0)); - btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyA?solverBodyB.m_linearVelocity+solverBodyB.m_externalForceImpulse:btVector3(0,0,0)) - + solverConstraint.m_relpos2CrossNormal.dot(bodyA?solverBodyB.m_angularVelocity:btVector3(0,0,0)); + btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0 ? solverBodyA.m_linearVelocity + solverBodyA.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : btVector3(0, 0, 0)); + btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyA ? solverBodyB.m_linearVelocity + solverBodyB.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(bodyA ? solverBodyB.m_angularVelocity : btVector3(0, 0, 0)); - rel_vel = vel1Dotn+vel2Dotn; + rel_vel = vel1Dotn + vel2Dotn; -// btScalar positionalError = 0.f; + // btScalar positionalError = 0.f; - btScalar velocityError = desiredVelocity - rel_vel; + btScalar velocityError = desiredVelocity - rel_vel; btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv; btScalar penetrationImpulse = btScalar(0); @@ -628,8 +593,8 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR) { btScalar distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(normalAxis); - btScalar positionalError = -distance * infoGlobal.m_frictionERP/infoGlobal.m_timeStep; - penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; + btScalar positionalError = -distance * infoGlobal.m_frictionERP / infoGlobal.m_timeStep; + penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv; } solverConstraint.m_rhs = penetrationImpulse + velocityImpulse; @@ -637,11 +602,10 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr solverConstraint.m_cfm = cfmSlip; solverConstraint.m_lowerLimit = -solverConstraint.m_friction; solverConstraint.m_upperLimit = solverConstraint.m_friction; - } } -btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip) +btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip) { btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing(); solverConstraint.m_frictionIndex = frictionIndex; @@ -650,15 +614,13 @@ btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(c return solverConstraint; } - -void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis1,int solverBodyIdA,int solverBodyIdB, - btManifoldPoint& cp,btScalar combinedTorsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2, - btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, - btScalar desiredVelocity, btScalar cfmSlip) +void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB, + btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, + btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, + btScalar desiredVelocity, btScalar cfmSlip) { - btVector3 normalAxis(0,0,0); - + btVector3 normalAxis(0, 0, 0); solverConstraint.m_contactNormal1 = normalAxis; solverConstraint.m_contactNormal2 = -normalAxis; @@ -671,8 +633,8 @@ void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint( btSo solverConstraint.m_solverBodyIdA = solverBodyIdA; solverConstraint.m_solverBodyIdB = solverBodyIdB; - solverConstraint.m_friction = combinedTorsionalFriction; - solverConstraint.m_originalContactPoint = 0; + solverConstraint.m_friction = combinedTorsionalFriction; + solverConstraint.m_originalContactPoint = 0; solverConstraint.m_appliedImpulse = 0.f; solverConstraint.m_appliedPushImpulse = 0.f; @@ -680,138 +642,125 @@ void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint( btSo { btVector3 ftorqueAxis1 = -normalAxis1; solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; - solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor() : btVector3(0,0,0); + solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld() * ftorqueAxis1 * body0->getAngularFactor() : btVector3(0, 0, 0); } { btVector3 ftorqueAxis1 = normalAxis1; solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; - solverConstraint.m_angularComponentB = bodyA ? bodyA->getInvInertiaTensorWorld()*ftorqueAxis1*bodyA->getAngularFactor() : btVector3(0,0,0); + solverConstraint.m_angularComponentB = bodyA ? bodyA->getInvInertiaTensorWorld() * ftorqueAxis1 * bodyA->getAngularFactor() : btVector3(0, 0, 0); } - { - btVector3 iMJaA = body0?body0->getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal:btVector3(0,0,0); - btVector3 iMJaB = bodyA?bodyA->getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal:btVector3(0,0,0); + btVector3 iMJaA = body0 ? body0->getInvInertiaTensorWorld() * solverConstraint.m_relpos1CrossNormal : btVector3(0, 0, 0); + btVector3 iMJaB = bodyA ? bodyA->getInvInertiaTensorWorld() * solverConstraint.m_relpos2CrossNormal : btVector3(0, 0, 0); btScalar sum = 0; sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal); sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal); - solverConstraint.m_jacDiagABInv = btScalar(1.)/sum; + solverConstraint.m_jacDiagABInv = btScalar(1.) / sum; } { - - btScalar rel_vel; - btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0?solverBodyA.m_linearVelocity+solverBodyA.m_externalForceImpulse:btVector3(0,0,0)) - + solverConstraint.m_relpos1CrossNormal.dot(body0?solverBodyA.m_angularVelocity:btVector3(0,0,0)); - btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyA?solverBodyB.m_linearVelocity+solverBodyB.m_externalForceImpulse:btVector3(0,0,0)) - + solverConstraint.m_relpos2CrossNormal.dot(bodyA?solverBodyB.m_angularVelocity:btVector3(0,0,0)); + btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0 ? solverBodyA.m_linearVelocity + solverBodyA.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : btVector3(0, 0, 0)); + btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyA ? solverBodyB.m_linearVelocity + solverBodyB.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(bodyA ? solverBodyB.m_angularVelocity : btVector3(0, 0, 0)); - rel_vel = vel1Dotn+vel2Dotn; + rel_vel = vel1Dotn + vel2Dotn; -// btScalar positionalError = 0.f; + // btScalar positionalError = 0.f; - btSimdScalar velocityError = desiredVelocity - rel_vel; - btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv); + btSimdScalar velocityError = desiredVelocity - rel_vel; + btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv); solverConstraint.m_rhs = velocityImpulse; solverConstraint.m_cfm = cfmSlip; solverConstraint.m_lowerLimit = -solverConstraint.m_friction; solverConstraint.m_upperLimit = solverConstraint.m_friction; - } } - - - - - - - -btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,btScalar combinedTorsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip) +btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip) { btSolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing(); solverConstraint.m_frictionIndex = frictionIndex; - setupTorsionalFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, combinedTorsionalFriction,rel_pos1, rel_pos2, - colObj0, colObj1, relaxation, desiredVelocity, cfmSlip); + setupTorsionalFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, combinedTorsionalFriction, rel_pos1, rel_pos2, + colObj0, colObj1, relaxation, desiredVelocity, cfmSlip); return solverConstraint; } - -int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body,btScalar timeStep) +int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body, btScalar timeStep) { #if BT_THREADSAFE - int solverBodyId = -1; - bool isRigidBodyType = btRigidBody::upcast( &body ) != NULL; - if ( isRigidBodyType && !body.isStaticOrKinematicObject() ) - { - // dynamic body - // Dynamic bodies can only be in one island, so it's safe to write to the companionId - solverBodyId = body.getCompanionId(); - if ( solverBodyId < 0 ) - { - solverBodyId = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody( &solverBody, &body, timeStep ); - body.setCompanionId( solverBodyId ); - } - } - else if (isRigidBodyType && body.isKinematicObject()) - { - // - // NOTE: must test for kinematic before static because some kinematic objects also - // identify as "static" - // - // Kinematic bodies can be in multiple islands at once, so it is a - // race condition to write to them, so we use an alternate method - // to record the solverBodyId - int uniqueId = body.getWorldArrayIndex(); - const int INVALID_SOLVER_BODY_ID = -1; - if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size()) - { - m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID); - } - solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ]; - // if no table entry yet, - if ( solverBodyId == INVALID_SOLVER_BODY_ID ) - { - // create a table entry for this body - solverBodyId = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody( &solverBody, &body, timeStep ); - m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ] = solverBodyId; - } - } - else - { - bool isMultiBodyType = (body.getInternalType()&btCollisionObject::CO_FEATHERSTONE_LINK); - // Incorrectly set collision object flags can degrade performance in various ways. + int solverBodyId = -1; + bool isRigidBodyType = btRigidBody::upcast(&body) != NULL; + if (isRigidBodyType && !body.isStaticOrKinematicObject()) + { + // dynamic body + // Dynamic bodies can only be in one island, so it's safe to write to the companionId + solverBodyId = body.getCompanionId(); + if (solverBodyId < 0) + { + solverBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody, &body, timeStep); + body.setCompanionId(solverBodyId); + } + } + else if (isRigidBodyType && body.isKinematicObject()) + { + // + // NOTE: must test for kinematic before static because some kinematic objects also + // identify as "static" + // + // Kinematic bodies can be in multiple islands at once, so it is a + // race condition to write to them, so we use an alternate method + // to record the solverBodyId + int uniqueId = body.getWorldArrayIndex(); + const int INVALID_SOLVER_BODY_ID = -1; + if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size()) + { + m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID); + } + solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId]; + // if no table entry yet, + if (solverBodyId == INVALID_SOLVER_BODY_ID) + { + // create a table entry for this body + solverBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody, &body, timeStep); + m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId; + } + } + else + { + bool isMultiBodyType = (body.getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK); + // Incorrectly set collision object flags can degrade performance in various ways. if (!isMultiBodyType) { - btAssert( body.isStaticOrKinematicObject() ); + btAssert(body.isStaticOrKinematicObject()); } - //it could be a multibody link collider - // all fixed bodies (inf mass) get mapped to a single solver id - if ( m_fixedBodyId < 0 ) - { - m_fixedBodyId = m_tmpSolverBodyPool.size(); - btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); - initSolverBody( &fixedBody, 0, timeStep ); - } - solverBodyId = m_fixedBodyId; - } - btAssert( solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size() ); + //it could be a multibody link collider + // all fixed bodies (inf mass) get mapped to a single solver id + if (m_fixedBodyId < 0) + { + m_fixedBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&fixedBody, 0, timeStep); + } + solverBodyId = m_fixedBodyId; + } + btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size()); return solverBodyId; -#else // BT_THREADSAFE +#else // BT_THREADSAFE - int solverBodyIdA = -1; + int solverBodyIdA = -1; if (body.getCompanionId() >= 0) { //body has already been converted solverBodyIdA = body.getCompanionId(); - btAssert(solverBodyIdA < m_tmpSolverBodyPool.size()); - } else + btAssert(solverBodyIdA < m_tmpSolverBodyPool.size()); + } + else { btRigidBody* rb = btRigidBody::upcast(&body); //convert both active and kinematic objects (for their velocity) @@ -819,233 +768,216 @@ int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& { solverBodyIdA = m_tmpSolverBodyPool.size(); btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,&body,timeStep); + initSolverBody(&solverBody, &body, timeStep); body.setCompanionId(solverBodyIdA); - } else + } + else { - - if (m_fixedBodyId<0) + if (m_fixedBodyId < 0) { m_fixedBodyId = m_tmpSolverBodyPool.size(); btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); - initSolverBody(&fixedBody,0,timeStep); + initSolverBody(&fixedBody, 0, timeStep); } return m_fixedBodyId; -// return 0;//assume first one is a fixed solver body + // return 0;//assume first one is a fixed solver body } } return solverBodyIdA; -#endif // BT_THREADSAFE - +#endif // BT_THREADSAFE } #include <stdio.h> - void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btContactSolverInfo& infoGlobal, btScalar& relaxation, const btVector3& rel_pos1, const btVector3& rel_pos2) { + // const btVector3& pos1 = cp.getPositionWorldOnA(); + // const btVector3& pos2 = cp.getPositionWorldOnB(); - // const btVector3& pos1 = cp.getPositionWorldOnA(); - // const btVector3& pos2 = cp.getPositionWorldOnB(); - - btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA]; - btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB]; - - btRigidBody* rb0 = bodyA->m_originalBody; - btRigidBody* rb1 = bodyB->m_originalBody; - -// btVector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); -// btVector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin(); - //rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin(); - //rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin(); - - relaxation = infoGlobal.m_sor; - btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep; - - //cfm = 1 / ( dt * kp + kd ) - //erp = dt * kp / ( dt * kp + kd ) - - btScalar cfm = infoGlobal.m_globalCfm; - btScalar erp = infoGlobal.m_erp2; - - if ((cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP)) - { - if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM) - cfm = cp.m_contactCFM; - if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP) - erp = cp.m_contactERP; - } else - { - if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING) - { - btScalar denom = ( infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1 ); - if (denom < SIMD_EPSILON) - { - denom = SIMD_EPSILON; - } - cfm = btScalar(1) / denom; - erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom; - } - } - - cfm *= invTimeStep; - - - btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); - solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0); - btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); - solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0); - - { -#ifdef COMPUTE_IMPULSE_DENOM - btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB); - btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB); -#else - btVector3 vec; - btScalar denom0 = 0.f; - btScalar denom1 = 0.f; - if (rb0) - { - vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); - denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec); - } - if (rb1) - { - vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2); - denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec); - } -#endif //COMPUTE_IMPULSE_DENOM - - btScalar denom = relaxation/(denom0+denom1+cfm); - solverConstraint.m_jacDiagABInv = denom; - } - - if (rb0) - { - solverConstraint.m_contactNormal1 = cp.m_normalWorldOnB; - solverConstraint.m_relpos1CrossNormal = torqueAxis0; - } else - { - solverConstraint.m_contactNormal1.setZero(); - solverConstraint.m_relpos1CrossNormal.setZero(); - } - if (rb1) - { - solverConstraint.m_contactNormal2 = -cp.m_normalWorldOnB; - solverConstraint.m_relpos2CrossNormal = -torqueAxis1; - }else - { - solverConstraint.m_contactNormal2.setZero(); - solverConstraint.m_relpos2CrossNormal.setZero(); - } - - btScalar restitution = 0.f; - btScalar penetration = cp.getDistance()+infoGlobal.m_linearSlop; - - { - btVector3 vel1,vel2; + btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA]; + btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB]; - vel1 = rb0? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0); - vel2 = rb1? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); + btRigidBody* rb0 = bodyA->m_originalBody; + btRigidBody* rb1 = bodyB->m_originalBody; - // btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); - btVector3 vel = vel1 - vel2; - btScalar rel_vel = cp.m_normalWorldOnB.dot(vel); + // btVector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); + // btVector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin(); + //rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin(); + //rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin(); + relaxation = infoGlobal.m_sor; + btScalar invTimeStep = btScalar(1) / infoGlobal.m_timeStep; + //cfm = 1 / ( dt * kp + kd ) + //erp = dt * kp / ( dt * kp + kd ) - solverConstraint.m_friction = cp.m_combinedFriction; + btScalar cfm = infoGlobal.m_globalCfm; + btScalar erp = infoGlobal.m_erp2; + if ((cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP)) + { + if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM) + cfm = cp.m_contactCFM; + if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP) + erp = cp.m_contactERP; + } + else + { + if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING) + { + btScalar denom = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1); + if (denom < SIMD_EPSILON) + { + denom = SIMD_EPSILON; + } + cfm = btScalar(1) / denom; + erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom; + } + } - restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold); - if (restitution <= btScalar(0.)) - { - restitution = 0.f; - }; - } + cfm *= invTimeStep; + btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0); + btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * -torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0); - ///warm starting (or zero if disabled) - if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) - { - solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor; - if (rb0) - bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1*bodyA->internalGetInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse); - if (rb1) - bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2*bodyB->internalGetInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse); - } else - { - solverConstraint.m_appliedImpulse = 0.f; - } + { +#ifdef COMPUTE_IMPULSE_DENOM + btScalar denom0 = rb0->computeImpulseDenominator(pos1, cp.m_normalWorldOnB); + btScalar denom1 = rb1->computeImpulseDenominator(pos2, cp.m_normalWorldOnB); +#else + btVector3 vec; + btScalar denom0 = 0.f; + btScalar denom1 = 0.f; + if (rb0) + { + vec = (solverConstraint.m_angularComponentA).cross(rel_pos1); + denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec); + } + if (rb1) + { + vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2); + denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec); + } +#endif //COMPUTE_IMPULSE_DENOM - solverConstraint.m_appliedPushImpulse = 0.f; + btScalar denom = relaxation / (denom0 + denom1 + cfm); + solverConstraint.m_jacDiagABInv = denom; + } - { + if (rb0) + { + solverConstraint.m_contactNormal1 = cp.m_normalWorldOnB; + solverConstraint.m_relpos1CrossNormal = torqueAxis0; + } + else + { + solverConstraint.m_contactNormal1.setZero(); + solverConstraint.m_relpos1CrossNormal.setZero(); + } + if (rb1) + { + solverConstraint.m_contactNormal2 = -cp.m_normalWorldOnB; + solverConstraint.m_relpos2CrossNormal = -torqueAxis1; + } + else + { + solverConstraint.m_contactNormal2.setZero(); + solverConstraint.m_relpos2CrossNormal.setZero(); + } - btVector3 externalForceImpulseA = bodyA->m_originalBody ? bodyA->m_externalForceImpulse: btVector3(0,0,0); - btVector3 externalTorqueImpulseA = bodyA->m_originalBody ? bodyA->m_externalTorqueImpulse: btVector3(0,0,0); - btVector3 externalForceImpulseB = bodyB->m_originalBody ? bodyB->m_externalForceImpulse: btVector3(0,0,0); - btVector3 externalTorqueImpulseB = bodyB->m_originalBody ?bodyB->m_externalTorqueImpulse : btVector3(0,0,0); + btScalar restitution = 0.f; + btScalar penetration = cp.getDistance() + infoGlobal.m_linearSlop; + { + btVector3 vel1, vel2; - btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(bodyA->m_linearVelocity+externalForceImpulseA) - + solverConstraint.m_relpos1CrossNormal.dot(bodyA->m_angularVelocity+externalTorqueImpulseA); - btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyB->m_linearVelocity+externalForceImpulseB) - + solverConstraint.m_relpos2CrossNormal.dot(bodyB->m_angularVelocity+externalTorqueImpulseB); - btScalar rel_vel = vel1Dotn+vel2Dotn; + vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0, 0, 0); + vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0, 0, 0); - btScalar positionalError = 0.f; - btScalar velocityError = restitution - rel_vel;// * damping; + // btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); + btVector3 vel = vel1 - vel2; + btScalar rel_vel = cp.m_normalWorldOnB.dot(vel); + solverConstraint.m_friction = cp.m_combinedFriction; - - if (penetration>0) - { - positionalError = 0; + restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold); + if (restitution <= btScalar(0.)) + { + restitution = 0.f; + }; + } - velocityError -= penetration *invTimeStep; - } else - { - positionalError = -penetration * erp*invTimeStep; + ///warm starting (or zero if disabled) + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor; + if (rb0) + bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse); + if (rb1) + bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass() , -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse); + } + else + { + solverConstraint.m_appliedImpulse = 0.f; + } - } + solverConstraint.m_appliedPushImpulse = 0.f; - btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; - btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; + { + btVector3 externalForceImpulseA = bodyA->m_originalBody ? bodyA->m_externalForceImpulse : btVector3(0, 0, 0); + btVector3 externalTorqueImpulseA = bodyA->m_originalBody ? bodyA->m_externalTorqueImpulse : btVector3(0, 0, 0); + btVector3 externalForceImpulseB = bodyB->m_originalBody ? bodyB->m_externalForceImpulse : btVector3(0, 0, 0); + btVector3 externalTorqueImpulseB = bodyB->m_originalBody ? bodyB->m_externalTorqueImpulse : btVector3(0, 0, 0); - if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) - { - //combine position and velocity into rhs - solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;//-solverConstraint.m_contactNormal1.dot(bodyA->m_externalForce*bodyA->m_invMass-bodyB->m_externalForce/bodyB->m_invMass)*solverConstraint.m_jacDiagABInv; - solverConstraint.m_rhsPenetration = 0.f; + btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(bodyA->m_linearVelocity + externalForceImpulseA) + solverConstraint.m_relpos1CrossNormal.dot(bodyA->m_angularVelocity + externalTorqueImpulseA); + btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyB->m_linearVelocity + externalForceImpulseB) + solverConstraint.m_relpos2CrossNormal.dot(bodyB->m_angularVelocity + externalTorqueImpulseB); + btScalar rel_vel = vel1Dotn + vel2Dotn; - } else - { - //split position and velocity into rhs and m_rhsPenetration - solverConstraint.m_rhs = velocityImpulse; - solverConstraint.m_rhsPenetration = penetrationImpulse; - } - solverConstraint.m_cfm = cfm*solverConstraint.m_jacDiagABInv; - solverConstraint.m_lowerLimit = 0; - solverConstraint.m_upperLimit = 1e10f; - } + btScalar positionalError = 0.f; + btScalar velocityError = restitution - rel_vel; // * damping; + if (penetration > 0) + { + positionalError = 0; + velocityError -= penetration * invTimeStep; + } + else + { + positionalError = -penetration * erp * invTimeStep; + } + btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv; + if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold)) + { + //combine position and velocity into rhs + solverConstraint.m_rhs = penetrationImpulse + velocityImpulse; //-solverConstraint.m_contactNormal1.dot(bodyA->m_externalForce*bodyA->m_invMass-bodyB->m_externalForce/bodyB->m_invMass)*solverConstraint.m_jacDiagABInv; + solverConstraint.m_rhsPenetration = 0.f; + } + else + { + //split position and velocity into rhs and m_rhsPenetration + solverConstraint.m_rhs = velocityImpulse; + solverConstraint.m_rhsPenetration = penetrationImpulse; + } + solverConstraint.m_cfm = cfm * solverConstraint.m_jacDiagABInv; + solverConstraint.m_lowerLimit = 0; + solverConstraint.m_upperLimit = 1e10f; + } } - - -void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse( btSolverConstraint& solverConstraint, - int solverBodyIdA, int solverBodyIdB, - btManifoldPoint& cp, const btContactSolverInfo& infoGlobal) +void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse(btSolverConstraint& solverConstraint, + int solverBodyIdA, int solverBodyIdB, + btManifoldPoint& cp, const btContactSolverInfo& infoGlobal) { - btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA]; btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB]; @@ -1058,10 +990,11 @@ void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse( btSolver { frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor; if (rb0) - bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal1*rb0->getInvMass()*rb0->getLinearFactor(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse); + bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal1 * rb0->getInvMass() , frictionConstraint1.m_angularComponentA, frictionConstraint1.m_appliedImpulse); if (rb1) - bodyB->internalApplyImpulse(-frictionConstraint1.m_contactNormal2*rb1->getInvMass()*rb1->getLinearFactor(),-frictionConstraint1.m_angularComponentB,-(btScalar)frictionConstraint1.m_appliedImpulse); - } else + bodyB->internalApplyImpulse(-frictionConstraint1.m_contactNormal2 * rb1->getInvMass() , -frictionConstraint1.m_angularComponentB, -(btScalar)frictionConstraint1.m_appliedImpulse); + } + else { frictionConstraint1.m_appliedImpulse = 0.f; } @@ -1069,50 +1002,45 @@ void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse( btSolver if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) { - btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1]; + btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex + 1]; if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) { - frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor; + frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor; if (rb0) - bodyA->internalApplyImpulse(frictionConstraint2.m_contactNormal1*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse); + bodyA->internalApplyImpulse(frictionConstraint2.m_contactNormal1 * rb0->getInvMass(), frictionConstraint2.m_angularComponentA, frictionConstraint2.m_appliedImpulse); if (rb1) - bodyB->internalApplyImpulse(-frictionConstraint2.m_contactNormal2*rb1->getInvMass(),-frictionConstraint2.m_angularComponentB,-(btScalar)frictionConstraint2.m_appliedImpulse); - } else + bodyB->internalApplyImpulse(-frictionConstraint2.m_contactNormal2 * rb1->getInvMass(), -frictionConstraint2.m_angularComponentB, -(btScalar)frictionConstraint2.m_appliedImpulse); + } + else { frictionConstraint2.m_appliedImpulse = 0.f; } } } - - - -void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal) +void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal) { - btCollisionObject* colObj0=0,*colObj1=0; + btCollisionObject *colObj0 = 0, *colObj1 = 0; colObj0 = (btCollisionObject*)manifold->getBody0(); colObj1 = (btCollisionObject*)manifold->getBody1(); - int solverBodyIdA = getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep); - int solverBodyIdB = getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep); + int solverBodyIdA = getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep); + int solverBodyIdB = getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep); -// btRigidBody* bodyA = btRigidBody::upcast(colObj0); -// btRigidBody* bodyB = btRigidBody::upcast(colObj1); + // btRigidBody* bodyA = btRigidBody::upcast(colObj0); + // btRigidBody* bodyB = btRigidBody::upcast(colObj1); btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA]; btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB]; - - ///avoid collision response between two static objects if (!solverBodyA || (solverBodyA->m_invMass.fuzzyZero() && (!solverBodyB || solverBodyB->m_invMass.fuzzyZero()))) return; - int rollingFriction=1; - for (int j=0;j<manifold->getNumContacts();j++) + int rollingFriction = 1; + for (int j = 0; j < manifold->getNumContacts(); j++) { - btManifoldPoint& cp = manifold->getContactPoint(j); if (cp.getDistance() <= manifold->getContactProcessingThreshold()) @@ -1121,7 +1049,6 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m btVector3 rel_pos2; btScalar relaxation; - int frictionIndex = m_tmpSolverContactConstraintPool.size(); btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing(); solverConstraint.m_solverBodyIdA = solverBodyIdA; @@ -1137,43 +1064,38 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m btVector3 vel1; btVector3 vel2; - - solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1,vel1); - solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2,vel2 ); - btVector3 vel = vel1 - vel2; + solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1, vel1); + solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2, vel2); + + btVector3 vel = vel1 - vel2; btScalar rel_vel = cp.m_normalWorldOnB.dot(vel); setupContactConstraint(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2); - - - /////setup the friction constraints solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size(); - if ((cp.m_combinedRollingFriction>0.f) && (rollingFriction>0)) + if ((cp.m_combinedRollingFriction > 0.f) && (rollingFriction > 0)) { - { - addTorsionalFrictionConstraint(cp.m_normalWorldOnB,solverBodyIdA,solverBodyIdB,frictionIndex,cp,cp.m_combinedSpinningFriction, rel_pos1,rel_pos2,colObj0,colObj1, relaxation); - btVector3 axis0,axis1; - btPlaneSpace1(cp.m_normalWorldOnB,axis0,axis1); + addTorsionalFrictionConstraint(cp.m_normalWorldOnB, solverBodyIdA, solverBodyIdB, frictionIndex, cp, cp.m_combinedSpinningFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation); + btVector3 axis0, axis1; + btPlaneSpace1(cp.m_normalWorldOnB, axis0, axis1); axis0.normalize(); axis1.normalize(); - - applyAnisotropicFriction(colObj0,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); - applyAnisotropicFriction(colObj1,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); - applyAnisotropicFriction(colObj0,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); - applyAnisotropicFriction(colObj1,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); - if (axis0.length()>0.001) - addTorsionalFrictionConstraint(axis0,solverBodyIdA,solverBodyIdB,frictionIndex,cp, - cp.m_combinedRollingFriction, rel_pos1,rel_pos2,colObj0,colObj1, relaxation); - if (axis1.length()>0.001) - addTorsionalFrictionConstraint(axis1,solverBodyIdA,solverBodyIdB,frictionIndex,cp, - cp.m_combinedRollingFriction, rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + applyAnisotropicFriction(colObj0, axis0, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj1, axis0, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj0, axis1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj1, axis1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + if (axis0.length() > 0.001) + addTorsionalFrictionConstraint(axis0, solverBodyIdA, solverBodyIdB, frictionIndex, cp, + cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation); + if (axis1.length() > 0.001) + addTorsionalFrictionConstraint(axis1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, + cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation); } } @@ -1188,106 +1110,97 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity. /// ///The user can manually override the friction directions for certain contacts using a contact callback, - ///and set the cp.m_lateralFrictionInitialized to true + ///and use contactPoint.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2) ///this will give a conveyor belt effect /// - - if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags&BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED)) + + if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED)) { cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON) { - cp.m_lateralFrictionDir1 *= 1.f/btSqrt(lat_rel_vel); - applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION); - applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION); - addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,infoGlobal); + cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel); + applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION); + addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal); - if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) { cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB); - cp.m_lateralFrictionDir2.normalize();//?? - applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION); - applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION); - addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal); + cp.m_lateralFrictionDir2.normalize(); //?? + applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION); + addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal); } - - } else + } + else { - btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2); + btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2); - applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION); - applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION); - addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal); + applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION); + addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal); if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) { - applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION); - applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION); - addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal); + applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION); + addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal); } - if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION)) { - cp.m_contactPointFlags|=BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED; + cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED; } } - - } else + } + else { - addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM); + addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM); if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) - addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM); - + addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM); } - setFrictionConstraintImpulse( solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal); - - - - + setFrictionConstraintImpulse(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal); } } } -void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr,int numManifolds, const btContactSolverInfo& infoGlobal) +void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal) { int i; btPersistentManifold* manifold = 0; -// btCollisionObject* colObj0=0,*colObj1=0; - + // btCollisionObject* colObj0=0,*colObj1=0; - for (i=0;i<numManifolds;i++) + for (i = 0; i < numManifolds; i++) { manifold = manifoldPtr[i]; - convertContact(manifold,infoGlobal); + convertContact(manifold, infoGlobal); } } - void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* currentConstraintRow, - btTypedConstraint* constraint, - const btTypedConstraint::btConstraintInfo1& info1, - int solverBodyIdA, - int solverBodyIdB, - const btContactSolverInfo& infoGlobal - ) + btTypedConstraint* constraint, + const btTypedConstraint::btConstraintInfo1& info1, + int solverBodyIdA, + int solverBodyIdB, + const btContactSolverInfo& infoGlobal) { const btRigidBody& rbA = constraint->getRigidBodyA(); const btRigidBody& rbB = constraint->getRigidBodyB(); - const btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA]; - const btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB]; + const btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA]; + const btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB]; int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations; - if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations) + if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations) m_maxOverrideNumSolverIterations = overrideNumSolverIterations; - for (int j=0;j<info1.m_numConstraintRows;j++) + for (int j = 0; j < info1.m_numConstraintRows; j++) { - memset(¤tConstraintRow[j],0,sizeof(btSolverConstraint)); + memset(¤tConstraintRow[j], 0, sizeof(btSolverConstraint)); currentConstraintRow[j].m_lowerLimit = -SIMD_INFINITY; currentConstraintRow[j].m_upperLimit = SIMD_INFINITY; currentConstraintRow[j].m_appliedImpulse = 0.f; @@ -1297,15 +1210,15 @@ void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* curre currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations; } - // these vectors are already cleared in initSolverBody, no need to redundantly clear again - btAssert(bodyAPtr->getDeltaLinearVelocity().isZero()); - btAssert(bodyAPtr->getDeltaAngularVelocity().isZero()); - btAssert(bodyAPtr->getPushVelocity().isZero()); - btAssert(bodyAPtr->getTurnVelocity().isZero()); - btAssert(bodyBPtr->getDeltaLinearVelocity().isZero()); - btAssert(bodyBPtr->getDeltaAngularVelocity().isZero()); - btAssert(bodyBPtr->getPushVelocity().isZero()); - btAssert(bodyBPtr->getTurnVelocity().isZero()); + // these vectors are already cleared in initSolverBody, no need to redundantly clear again + btAssert(bodyAPtr->getDeltaLinearVelocity().isZero()); + btAssert(bodyAPtr->getDeltaAngularVelocity().isZero()); + btAssert(bodyAPtr->getPushVelocity().isZero()); + btAssert(bodyAPtr->getTurnVelocity().isZero()); + btAssert(bodyBPtr->getDeltaLinearVelocity().isZero()); + btAssert(bodyBPtr->getDeltaAngularVelocity().isZero()); + btAssert(bodyBPtr->getPushVelocity().isZero()); + btAssert(bodyBPtr->getTurnVelocity().isZero()); //bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f); //bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f); //bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f); @@ -1315,17 +1228,16 @@ void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* curre //bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f); //bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f); - btTypedConstraint::btConstraintInfo2 info2; - info2.fps = 1.f/infoGlobal.m_timeStep; + info2.fps = 1.f / infoGlobal.m_timeStep; info2.erp = infoGlobal.m_erp; info2.m_J1linearAxis = currentConstraintRow->m_contactNormal1; info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal; info2.m_J2linearAxis = currentConstraintRow->m_contactNormal2; info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal; - info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this + info2.rowskip = sizeof(btSolverConstraint) / sizeof(btScalar); //check this ///the size of btSolverConstraint needs be a multiple of btScalar - btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint)); + btAssert(info2.rowskip * sizeof(btScalar) == sizeof(btSolverConstraint)); info2.m_constraintError = ¤tConstraintRow->m_rhs; currentConstraintRow->m_cfm = infoGlobal.m_globalCfm; info2.m_damping = infoGlobal.m_damping; @@ -1336,16 +1248,16 @@ void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* curre constraint->getInfo2(&info2); ///finalize the constraint setup - for (int j=0;j<info1.m_numConstraintRows;j++) + for (int j = 0; j < info1.m_numConstraintRows; j++) { btSolverConstraint& solverConstraint = currentConstraintRow[j]; - if (solverConstraint.m_upperLimit>=constraint->getBreakingImpulseThreshold()) + if (solverConstraint.m_upperLimit >= constraint->getBreakingImpulseThreshold()) { solverConstraint.m_upperLimit = constraint->getBreakingImpulseThreshold(); } - if (solverConstraint.m_lowerLimit<=-constraint->getBreakingImpulseThreshold()) + if (solverConstraint.m_lowerLimit <= -constraint->getBreakingImpulseThreshold()) { solverConstraint.m_lowerLimit = -constraint->getBreakingImpulseThreshold(); } @@ -1354,18 +1266,18 @@ void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* curre { const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal; - solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor(); + solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld() * ftorqueAxis1 * constraint->getRigidBodyA().getAngularFactor(); } { const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal; - solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor(); + solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld() * ftorqueAxis2 * constraint->getRigidBodyB().getAngularFactor(); } { - btVector3 iMJlA = solverConstraint.m_contactNormal1*rbA.getInvMass(); - btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal; - btVector3 iMJlB = solverConstraint.m_contactNormal2*rbB.getInvMass();//sign of normal? - btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal; + btVector3 iMJlA = solverConstraint.m_contactNormal1 * rbA.getInvMass(); + btVector3 iMJaA = rbA.getInvInertiaTensorWorld() * solverConstraint.m_relpos1CrossNormal; + btVector3 iMJlB = solverConstraint.m_contactNormal2 * rbB.getInvMass(); //sign of normal? + btVector3 iMJaB = rbB.getInvInertiaTensorWorld() * solverConstraint.m_relpos2CrossNormal; btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal1); sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal); @@ -1373,41 +1285,38 @@ void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* curre sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal); btScalar fsum = btFabs(sum); btAssert(fsum > SIMD_EPSILON); - btScalar sorRelaxation = 1.f;//todo: get from globalInfo? - solverConstraint.m_jacDiagABInv = fsum>SIMD_EPSILON?sorRelaxation/sum : 0.f; + btScalar sorRelaxation = 1.f; //todo: get from globalInfo? + solverConstraint.m_jacDiagABInv = fsum > SIMD_EPSILON ? sorRelaxation / sum : 0.f; } { btScalar rel_vel; - btVector3 externalForceImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalForceImpulse : btVector3(0,0,0); - btVector3 externalTorqueImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalTorqueImpulse : btVector3(0,0,0); + btVector3 externalForceImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalForceImpulse : btVector3(0, 0, 0); + btVector3 externalTorqueImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalTorqueImpulse : btVector3(0, 0, 0); - btVector3 externalForceImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalForceImpulse : btVector3(0,0,0); - btVector3 externalTorqueImpulseB = bodyBPtr->m_originalBody ?bodyBPtr->m_externalTorqueImpulse : btVector3(0,0,0); + btVector3 externalForceImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalForceImpulse : btVector3(0, 0, 0); + btVector3 externalTorqueImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalTorqueImpulse : btVector3(0, 0, 0); - btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity()+externalForceImpulseA) - + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity()+externalTorqueImpulseA); + btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity() + externalForceImpulseA) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity() + externalTorqueImpulseA); - btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity()+externalForceImpulseB) - + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity()+externalTorqueImpulseB); + btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity() + externalForceImpulseB) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity() + externalTorqueImpulseB); - rel_vel = vel1Dotn+vel2Dotn; + rel_vel = vel1Dotn + vel2Dotn; btScalar restitution = 0.f; - btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2 - btScalar velocityError = restitution - rel_vel * info2.m_damping; - btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv; - btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv; - solverConstraint.m_rhs = penetrationImpulse+velocityImpulse; + btScalar positionalError = solverConstraint.m_rhs; //already filled in by getConstraintInfo2 + btScalar velocityError = restitution - rel_vel * info2.m_damping; + btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv; + solverConstraint.m_rhs = penetrationImpulse + velocityImpulse; solverConstraint.m_appliedImpulse = 0.f; } } } - -void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal) +void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal) { - BT_PROFILE("convertJoints"); - for (int j=0;j<numConstraints;j++) + BT_PROFILE("convertJoints"); + for (int j = 0; j < numConstraints; j++) { btTypedConstraint* constraint = constraints[j]; constraint->buildJacobian(); @@ -1418,7 +1327,7 @@ void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** cons m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints); //calculate the total number of contraint rows - for (int i=0;i<numConstraints;i++) + for (int i = 0; i < numConstraints; i++) { btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i]; btJointFeedback* fb = constraints[i]->getJointFeedback(); @@ -1433,7 +1342,8 @@ void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** cons if (constraints[i]->isEnabled()) { constraints[i]->getInfo1(&info1); - } else + } + else { info1.m_numConstraintRows = 0; info1.nub = 0; @@ -1442,110 +1352,105 @@ void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** cons } m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows); - ///setup the btSolverConstraints int currentRow = 0; - for (int i=0;i<numConstraints;i++) + for (int i = 0; i < numConstraints; i++) { const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i]; if (info1.m_numConstraintRows) { - btAssert(currentRow<totalNumRows); + btAssert(currentRow < totalNumRows); btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow]; btTypedConstraint* constraint = constraints[i]; btRigidBody& rbA = constraint->getRigidBodyA(); btRigidBody& rbB = constraint->getRigidBodyB(); - int solverBodyIdA = getOrInitSolverBody(rbA,infoGlobal.m_timeStep); - int solverBodyIdB = getOrInitSolverBody(rbB,infoGlobal.m_timeStep); + int solverBodyIdA = getOrInitSolverBody(rbA, infoGlobal.m_timeStep); + int solverBodyIdB = getOrInitSolverBody(rbB, infoGlobal.m_timeStep); - convertJoint(currentConstraintRow, constraint, info1, solverBodyIdA, solverBodyIdB, infoGlobal); - } - currentRow+=info1.m_numConstraintRows; + convertJoint(currentConstraintRow, constraint, info1, solverBodyIdA, solverBodyIdB, infoGlobal); + } + currentRow += info1.m_numConstraintRows; } } - void btSequentialImpulseConstraintSolver::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal) { - BT_PROFILE("convertBodies"); + BT_PROFILE("convertBodies"); for (int i = 0; i < numBodies; i++) { bodies[i]->setCompanionId(-1); } #if BT_THREADSAFE - m_kinematicBodyUniqueIdToSolverBodyTable.resize( 0 ); -#endif // BT_THREADSAFE + m_kinematicBodyUniqueIdToSolverBodyTable.resize(0); +#endif // BT_THREADSAFE - m_tmpSolverBodyPool.reserve(numBodies+1); + m_tmpSolverBodyPool.reserve(numBodies + 1); m_tmpSolverBodyPool.resize(0); //btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); - //initSolverBody(&fixedBody,0); + //initSolverBody(&fixedBody,0); - for (int i=0;i<numBodies;i++) + for (int i = 0; i < numBodies; i++) { - int bodyId = getOrInitSolverBody(*bodies[i],infoGlobal.m_timeStep); + int bodyId = getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep); btRigidBody* body = btRigidBody::upcast(bodies[i]); if (body && body->getInvMass()) { btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId]; - btVector3 gyroForce (0,0,0); - if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT) + btVector3 gyroForce(0, 0, 0); + if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT) { gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce); - solverBody.m_externalTorqueImpulse -= gyroForce*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep; + solverBody.m_externalTorqueImpulse -= gyroForce * body->getInvInertiaTensorWorld() * infoGlobal.m_timeStep; } - if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD) + if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD) { gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep); solverBody.m_externalTorqueImpulse += gyroForce; } - if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY) + if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY) { gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep); solverBody.m_externalTorqueImpulse += gyroForce; - } } } } - -btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) +btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) { m_fixedBodyId = -1; BT_PROFILE("solveGroupCacheFriendlySetup"); (void)debugDrawer; - // if solver mode has changed, - if ( infoGlobal.m_solverMode != m_cachedSolverMode ) - { - // update solver functions to use SIMD or non-SIMD - bool useSimd = !!( infoGlobal.m_solverMode & SOLVER_SIMD ); - setupSolverFunctions( useSimd ); - m_cachedSolverMode = infoGlobal.m_solverMode; - } + // if solver mode has changed, + if (infoGlobal.m_solverMode != m_cachedSolverMode) + { + // update solver functions to use SIMD or non-SIMD + bool useSimd = !!(infoGlobal.m_solverMode & SOLVER_SIMD); + setupSolverFunctions(useSimd); + m_cachedSolverMode = infoGlobal.m_solverMode; + } m_maxOverrideNumSolverIterations = 0; #ifdef BT_ADDITIONAL_DEBUG - //make sure that dynamic bodies exist for all (enabled) constraints - for (int i=0;i<numConstraints;i++) + //make sure that dynamic bodies exist for all (enabled) constraints + for (int i = 0; i < numConstraints; i++) { btTypedConstraint* constraint = constraints[i]; if (constraint->isEnabled()) { if (!constraint->getRigidBodyA().isStaticOrKinematicObject()) { - bool found=false; - for (int b=0;b<numBodies;b++) + bool found = false; + for (int b = 0; b < numBodies; b++) { - - if (&constraint->getRigidBodyA()==bodies[b]) + if (&constraint->getRigidBodyA() == bodies[b]) { found = true; break; @@ -1555,10 +1460,10 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol } if (!constraint->getRigidBodyB().isStaticOrKinematicObject()) { - bool found=false; - for (int b=0;b<numBodies;b++) + bool found = false; + for (int b = 0; b < numBodies; b++) { - if (&constraint->getRigidBodyB()==bodies[b]) + if (&constraint->getRigidBodyB() == bodies[b]) { found = true; break; @@ -1568,50 +1473,46 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol } } } - //make sure that dynamic bodies exist for all contact manifolds - for (int i=0;i<numManifolds;i++) - { - if (!manifoldPtr[i]->getBody0()->isStaticOrKinematicObject()) - { - bool found=false; - for (int b=0;b<numBodies;b++) - { - - if (manifoldPtr[i]->getBody0()==bodies[b]) - { - found = true; - break; - } - } - btAssert(found); - } - if (!manifoldPtr[i]->getBody1()->isStaticOrKinematicObject()) - { - bool found=false; - for (int b=0;b<numBodies;b++) - { - if (manifoldPtr[i]->getBody1()==bodies[b]) - { - found = true; - break; - } - } - btAssert(found); - } - } -#endif //BT_ADDITIONAL_DEBUG - + //make sure that dynamic bodies exist for all contact manifolds + for (int i = 0; i < numManifolds; i++) + { + if (!manifoldPtr[i]->getBody0()->isStaticOrKinematicObject()) + { + bool found = false; + for (int b = 0; b < numBodies; b++) + { + if (manifoldPtr[i]->getBody0() == bodies[b]) + { + found = true; + break; + } + } + btAssert(found); + } + if (!manifoldPtr[i]->getBody1()->isStaticOrKinematicObject()) + { + bool found = false; + for (int b = 0; b < numBodies; b++) + { + if (manifoldPtr[i]->getBody1() == bodies[b]) + { + found = true; + break; + } + } + btAssert(found); + } + } +#endif //BT_ADDITIONAL_DEBUG //convert all bodies - convertBodies(bodies, numBodies, infoGlobal); - - convertJoints(constraints, numConstraints, infoGlobal); + convertBodies(bodies, numBodies, infoGlobal); - convertContacts(manifoldPtr,numManifolds,infoGlobal); + convertJoints(constraints, numConstraints, infoGlobal); + convertContacts(manifoldPtr, numManifolds, infoGlobal); -// btContactSolverInfo info = infoGlobal; - + // btContactSolverInfo info = infoGlobal; int numNonContactPool = m_tmpSolverNonContactConstraintPool.size(); int numConstraintPool = m_tmpSolverContactConstraintPool.size(); @@ -1620,35 +1521,33 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol ///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool); if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) - m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool*2); + m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool * 2); else m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool); m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool); { int i; - for (i=0;i<numNonContactPool;i++) + for (i = 0; i < numNonContactPool; i++) { m_orderNonContactConstraintPool[i] = i; } - for (i=0;i<numConstraintPool;i++) + for (i = 0; i < numConstraintPool; i++) { m_orderTmpConstraintPool[i] = i; } - for (i=0;i<numFrictionPool;i++) + for (i = 0; i < numFrictionPool; i++) { m_orderFrictionConstraintPool[i] = i; } } return 0.f; - } - -btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */,int /*numBodies*/,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/) +btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/) { - BT_PROFILE("solveSingleIteration"); + BT_PROFILE("solveSingleIteration"); btScalar leastSquaresResidual = 0.f; int numNonContactPool = m_tmpSolverNonContactConstraintPool.size(); @@ -1657,29 +1556,31 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER) { - if (1) // uncomment this for a bit less random ((iteration & 7) == 0) + if (1) // uncomment this for a bit less random ((iteration & 7) == 0) { - - for (int j=0; j<numNonContactPool; ++j) { + for (int j = 0; j < numNonContactPool; ++j) + { int tmp = m_orderNonContactConstraintPool[j]; - int swapi = btRandInt2(j+1); + int swapi = btRandInt2(j + 1); m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi]; m_orderNonContactConstraintPool[swapi] = tmp; } //contact/friction constraints are not solved more than - if (iteration< infoGlobal.m_numIterations) + if (iteration < infoGlobal.m_numIterations) { - for (int j=0; j<numConstraintPool; ++j) { + for (int j = 0; j < numConstraintPool; ++j) + { int tmp = m_orderTmpConstraintPool[j]; - int swapi = btRandInt2(j+1); + int swapi = btRandInt2(j + 1); m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi]; m_orderTmpConstraintPool[swapi] = tmp; } - for (int j=0; j<numFrictionPool; ++j) { + for (int j = 0; j < numFrictionPool; ++j) + { int tmp = m_orderFrictionConstraintPool[j]; - int swapi = btRandInt2(j+1); + int swapi = btRandInt2(j + 1); m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi]; m_orderFrictionConstraintPool[swapi] = tmp; } @@ -1687,253 +1588,240 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration } } - ///solve all joint constraints - for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) + ///solve all joint constraints + for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) + { + btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]]; + if (iteration < constraint.m_overrideNumSolverIterations) { - btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]]; - if (iteration < constraint.m_overrideNumSolverIterations) - { - btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint); - leastSquaresResidual = btMax(leastSquaresResidual, residual*residual); - } + btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint); + leastSquaresResidual = btMax(leastSquaresResidual, residual * residual); } + } - if (iteration< infoGlobal.m_numIterations) + if (iteration < infoGlobal.m_numIterations) + { + for (int j = 0; j < numConstraints; j++) { - for (int j=0;j<numConstraints;j++) + if (constraints[j]->isEnabled()) { - if (constraints[j]->isEnabled()) - { - int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(),infoGlobal.m_timeStep); - int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep); - btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid]; - btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid]; - constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep); - } + int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep); + int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep); + btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid]; + btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid]; + constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep); } + } + + ///solve all contact constraints + if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS) + { + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); + int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1; - ///solve all contact constraints - if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS) + for (int c = 0; c < numPoolConstraints; c++) { - int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); - int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)? 2 : 1; + btScalar totalImpulse = 0; - for (int c=0;c<numPoolConstraints;c++) { - btScalar totalImpulse =0; + const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]]; + btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold); + leastSquaresResidual = btMax(leastSquaresResidual, residual * residual); + totalImpulse = solveManifold.m_appliedImpulse; + } + bool applyFriction = true; + if (applyFriction) + { { - const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]]; - btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); - leastSquaresResidual = btMax(leastSquaresResidual, residual*residual); + btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]]; - totalImpulse = solveManifold.m_appliedImpulse; - } - bool applyFriction = true; - if (applyFriction) - { + if (totalImpulse > btScalar(0)) { + solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse; - btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier]]; - - if (totalImpulse>btScalar(0)) - { - solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); - solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; - - btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); - leastSquaresResidual = btMax(leastSquaresResidual, residual*residual); - } + btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold); + leastSquaresResidual = btMax(leastSquaresResidual, residual * residual); } + } - if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) - { - - btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier+1]]; + if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) + { + btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]]; - if (totalImpulse>btScalar(0)) - { - solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); - solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; + if (totalImpulse > btScalar(0)) + { + solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse; - btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); - leastSquaresResidual = btMax(leastSquaresResidual, residual*residual); - } + btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold); + leastSquaresResidual = btMax(leastSquaresResidual, residual * residual); } } } - } - else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS - { - //solve the friction constraints after all contact constraints, don't interleave them - int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); - int j; - - for (j=0;j<numPoolConstraints;j++) - { - const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]]; - btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); - leastSquaresResidual = btMax(leastSquaresResidual, residual*residual); - } + } + else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS + { + //solve the friction constraints after all contact constraints, don't interleave them + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); + int j; + for (j = 0; j < numPoolConstraints; j++) + { + const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]]; + btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold); + leastSquaresResidual = btMax(leastSquaresResidual, residual * residual); + } + ///solve all friction constraints - ///solve all friction constraints + int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size(); + for (j = 0; j < numFrictionPoolConstraints; j++) + { + btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]]; + btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; - int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size(); - for (j=0;j<numFrictionPoolConstraints;j++) + if (totalImpulse > btScalar(0)) { - btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]]; - btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; + solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse; - if (totalImpulse>btScalar(0)) - { - solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse); - solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; - - btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); - leastSquaresResidual = btMax(leastSquaresResidual, residual*residual); - } + btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold); + leastSquaresResidual = btMax(leastSquaresResidual, residual * residual); } } + } + int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size(); + for (int j = 0; j < numRollingFrictionPoolConstraints; j++) + { + btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j]; + btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse; + if (totalImpulse > btScalar(0)) + { + btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse; + if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction) + rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; - int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size(); - for (int j=0;j<numRollingFrictionPoolConstraints;j++) - { - - btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j]; - btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse; - if (totalImpulse>btScalar(0)) - { - btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse; - if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction) - rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; - - rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; - rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; - - btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint); - leastSquaresResidual = btMax(leastSquaresResidual, residual*residual); - } - } - + rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; + rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; + btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint); + leastSquaresResidual = btMax(leastSquaresResidual, residual * residual); + } } + } return leastSquaresResidual; } - -void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) +void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) { BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations"); int iteration; if (infoGlobal.m_splitImpulse) { { - for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++) + for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++) { - btScalar leastSquaresResidual =0.f; + btScalar leastSquaresResidual = 0.f; { int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); int j; - for (j=0;j<numPoolConstraints;j++) + for (j = 0; j < numPoolConstraints; j++) { const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]]; - btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold); - leastSquaresResidual = btMax(leastSquaresResidual, residual*residual); + btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold); + leastSquaresResidual = btMax(leastSquaresResidual, residual * residual); } } - if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration>=(infoGlobal.m_numIterations-1)) + if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1)) { #ifdef VERBOSE_RESIDUAL_PRINTF - printf("residual = %f at iteration #%d\n",leastSquaresResidual,iteration); + printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration); #endif break; } } - } + } } } -btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) +btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) { BT_PROFILE("solveGroupCacheFriendlyIterations"); { ///this is a special step to resolve penetrations (just for contacts) - solveGroupCacheFriendlySplitImpulseIterations(bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer); + solveGroupCacheFriendlySplitImpulseIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer); - int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations; + int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations ? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations; - for ( int iteration = 0 ; iteration< maxIterations ; iteration++) + for (int iteration = 0; iteration < maxIterations; iteration++) //for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--) { - m_leastSquaresResidual = solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer); + m_leastSquaresResidual = solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer); - if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration>= (maxIterations-1))) + if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration >= (maxIterations - 1))) { #ifdef VERBOSE_RESIDUAL_PRINTF - printf("residual = %f at iteration #%d\n",m_leastSquaresResidual,iteration); + printf("residual = %f at iteration #%d\n", m_leastSquaresResidual, iteration); #endif break; } } - } return 0.f; } void btSequentialImpulseConstraintSolver::writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal) { - for (int j=iBegin; j<iEnd; j++) - { - const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j]; - btManifoldPoint* pt = (btManifoldPoint*) solveManifold.m_originalContactPoint; - btAssert(pt); - pt->m_appliedImpulse = solveManifold.m_appliedImpulse; + for (int j = iBegin; j < iEnd; j++) + { + const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j]; + btManifoldPoint* pt = (btManifoldPoint*)solveManifold.m_originalContactPoint; + btAssert(pt); + pt->m_appliedImpulse = solveManifold.m_appliedImpulse; // float f = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; - // printf("pt->m_appliedImpulseLateral1 = %f\n", f); - pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; - //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1); - if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) - { - pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse; - } - //do a callback here? + // printf("pt->m_appliedImpulseLateral1 = %f\n", f); + pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; + //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1); + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)) + { + pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex + 1].m_appliedImpulse; } + //do a callback here? + } } void btSequentialImpulseConstraintSolver::writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal) { - for (int j=iBegin; j<iEnd; j++) + for (int j = iBegin; j < iEnd; j++) { const btSolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j]; btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint; btJointFeedback* fb = constr->getJointFeedback(); if (fb) { - fb->m_appliedForceBodyA += solverConstr.m_contactNormal1*solverConstr.m_appliedImpulse*constr->getRigidBodyA().getLinearFactor()/infoGlobal.m_timeStep; - fb->m_appliedForceBodyB += solverConstr.m_contactNormal2*solverConstr.m_appliedImpulse*constr->getRigidBodyB().getLinearFactor()/infoGlobal.m_timeStep; - fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal* constr->getRigidBodyA().getAngularFactor()*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep; - fb->m_appliedTorqueBodyB += solverConstr.m_relpos2CrossNormal* constr->getRigidBodyB().getAngularFactor()*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep; /*RGM ???? */ - + fb->m_appliedForceBodyA += solverConstr.m_contactNormal1 * solverConstr.m_appliedImpulse * constr->getRigidBodyA().getLinearFactor() / infoGlobal.m_timeStep; + fb->m_appliedForceBodyB += solverConstr.m_contactNormal2 * solverConstr.m_appliedImpulse * constr->getRigidBodyB().getLinearFactor() / infoGlobal.m_timeStep; + fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal * constr->getRigidBodyA().getAngularFactor() * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep; + fb->m_appliedTorqueBodyB += solverConstr.m_relpos2CrossNormal * constr->getRigidBodyB().getAngularFactor() * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep; /*RGM ???? */ } constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse); - if (btFabs(solverConstr.m_appliedImpulse)>=constr->getBreakingImpulseThreshold()) + if (btFabs(solverConstr.m_appliedImpulse) >= constr->getBreakingImpulseThreshold()) { constr->setEnabled(false); } } } - void btSequentialImpulseConstraintSolver::writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal) { - for (int i=iBegin; i<iEnd; i++) + for (int i = iBegin; i < iEnd; i++) { btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody; if (body) @@ -1944,11 +1832,11 @@ void btSequentialImpulseConstraintSolver::writeBackBodies(int iBegin, int iEnd, m_tmpSolverBodyPool[i].writebackVelocity(); m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity( - m_tmpSolverBodyPool[i].m_linearVelocity+ + m_tmpSolverBodyPool[i].m_linearVelocity + m_tmpSolverBodyPool[i].m_externalForceImpulse); m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity( - m_tmpSolverBodyPool[i].m_angularVelocity+ + m_tmpSolverBodyPool[i].m_angularVelocity + m_tmpSolverBodyPool[i].m_externalTorqueImpulse); if (infoGlobal.m_splitImpulse) @@ -1959,17 +1847,17 @@ void btSequentialImpulseConstraintSolver::writeBackBodies(int iBegin, int iEnd, } } -btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal) +btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal) { BT_PROFILE("solveGroupCacheFriendlyFinish"); if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) { - writeBackContacts(0, m_tmpSolverContactConstraintPool.size(), infoGlobal); + writeBackContacts(0, m_tmpSolverContactConstraintPool.size(), infoGlobal); } - writeBackJoints(0, m_tmpSolverNonContactConstraintPool.size(), infoGlobal); - writeBackBodies(0, m_tmpSolverBodyPool.size(), infoGlobal); + writeBackJoints(0, m_tmpSolverNonContactConstraintPool.size(), infoGlobal); + writeBackBodies(0, m_tmpSolverBodyPool.size(), infoGlobal); m_tmpSolverContactConstraintPool.resizeNoInitialize(0); m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0); @@ -1980,25 +1868,22 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCo return 0.f; } - - /// btSequentialImpulseConstraintSolver Sequentially applies impulses -btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btDispatcher* /*dispatcher*/) +btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer, btDispatcher* /*dispatcher*/) { - BT_PROFILE("solveGroup"); //you need to provide at least some bodies - solveGroupCacheFriendlySetup( bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer); + solveGroupCacheFriendlySetup(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer); - solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer); + solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer); solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal); return 0.f; } -void btSequentialImpulseConstraintSolver::reset() +void btSequentialImpulseConstraintSolver::reset() { m_btSeed2 = 0; } diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h index b834c3dac3..70db83b063 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h @@ -27,147 +27,142 @@ class btCollisionObject; #include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" #include "BulletDynamics/ConstraintSolver/btConstraintSolver.h" -typedef btScalar(*btSingleConstraintRowSolver)(btSolverBody&, btSolverBody&, const btSolverConstraint&); +typedef btScalar (*btSingleConstraintRowSolver)(btSolverBody&, btSolverBody&, const btSolverConstraint&); ///The btSequentialImpulseConstraintSolver is a fast SIMD implementation of the Projected Gauss Seidel (iterative LCP) method. -ATTRIBUTE_ALIGNED16(class) btSequentialImpulseConstraintSolver : public btConstraintSolver +ATTRIBUTE_ALIGNED16(class) +btSequentialImpulseConstraintSolver : public btConstraintSolver { protected: - btAlignedObjectArray<btSolverBody> m_tmpSolverBodyPool; - btConstraintArray m_tmpSolverContactConstraintPool; - btConstraintArray m_tmpSolverNonContactConstraintPool; - btConstraintArray m_tmpSolverContactFrictionConstraintPool; - btConstraintArray m_tmpSolverContactRollingFrictionConstraintPool; - - btAlignedObjectArray<int> m_orderTmpConstraintPool; - btAlignedObjectArray<int> m_orderNonContactConstraintPool; - btAlignedObjectArray<int> m_orderFrictionConstraintPool; + btAlignedObjectArray<btSolverBody> m_tmpSolverBodyPool; + btConstraintArray m_tmpSolverContactConstraintPool; + btConstraintArray m_tmpSolverNonContactConstraintPool; + btConstraintArray m_tmpSolverContactFrictionConstraintPool; + btConstraintArray m_tmpSolverContactRollingFrictionConstraintPool; + + btAlignedObjectArray<int> m_orderTmpConstraintPool; + btAlignedObjectArray<int> m_orderNonContactConstraintPool; + btAlignedObjectArray<int> m_orderFrictionConstraintPool; btAlignedObjectArray<btTypedConstraint::btConstraintInfo1> m_tmpConstraintSizesPool; - int m_maxOverrideNumSolverIterations; + int m_maxOverrideNumSolverIterations; int m_fixedBodyId; - // When running solvers on multiple threads, a race condition exists for Kinematic objects that - // participate in more than one solver. - // The getOrInitSolverBody() function writes the companionId of each body (storing the index of the solver body - // for the current solver). For normal dynamic bodies it isn't an issue because they can only be in one island - // (and therefore one thread) at a time. But kinematic bodies can be in multiple islands at once. - // To avoid this race condition, this solver does not write the companionId, instead it stores the solver body - // index in this solver-local table, indexed by the uniqueId of the body. - btAlignedObjectArray<int> m_kinematicBodyUniqueIdToSolverBodyTable; // only used for multithreading + // When running solvers on multiple threads, a race condition exists for Kinematic objects that + // participate in more than one solver. + // The getOrInitSolverBody() function writes the companionId of each body (storing the index of the solver body + // for the current solver). For normal dynamic bodies it isn't an issue because they can only be in one island + // (and therefore one thread) at a time. But kinematic bodies can be in multiple islands at once. + // To avoid this race condition, this solver does not write the companionId, instead it stores the solver body + // index in this solver-local table, indexed by the uniqueId of the body. + btAlignedObjectArray<int> m_kinematicBodyUniqueIdToSolverBodyTable; // only used for multithreading btSingleConstraintRowSolver m_resolveSingleConstraintRowGeneric; btSingleConstraintRowSolver m_resolveSingleConstraintRowLowerLimit; - btSingleConstraintRowSolver m_resolveSplitPenetrationImpulse; - int m_cachedSolverMode; // used to check if SOLVER_SIMD flag has been changed - void setupSolverFunctions( bool useSimd ); + btSingleConstraintRowSolver m_resolveSplitPenetrationImpulse; + int m_cachedSolverMode; // used to check if SOLVER_SIMD flag has been changed + void setupSolverFunctions(bool useSimd); - btScalar m_leastSquaresResidual; + btScalar m_leastSquaresResidual; - void setupFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB, - btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2, - btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, - const btContactSolverInfo& infoGlobal, - btScalar desiredVelocity=0., btScalar cfmSlip=0.); + void setupFrictionConstraint(btSolverConstraint & solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, + btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, + btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, + const btContactSolverInfo& infoGlobal, + btScalar desiredVelocity = 0., btScalar cfmSlip = 0.); - void setupTorsionalFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB, - btManifoldPoint& cp,btScalar combinedTorsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2, - btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, - btScalar desiredVelocity=0., btScalar cfmSlip=0.); + void setupTorsionalFrictionConstraint(btSolverConstraint & solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, + btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, + btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, + btScalar desiredVelocity = 0., btScalar cfmSlip = 0.); - btSolverConstraint& addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity=0., btScalar cfmSlip=0.); - btSolverConstraint& addTorsionalFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,btScalar torsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0, btScalar cfmSlip=0.f); + btSolverConstraint& addFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0., btScalar cfmSlip = 0.); + btSolverConstraint& addTorsionalFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar torsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity = 0, btScalar cfmSlip = 0.f); + void setupContactConstraint(btSolverConstraint & solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, + const btContactSolverInfo& infoGlobal, btScalar& relaxation, const btVector3& rel_pos1, const btVector3& rel_pos2); - void setupContactConstraint(btSolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, - const btContactSolverInfo& infoGlobal,btScalar& relaxation, const btVector3& rel_pos1, const btVector3& rel_pos2); + static void applyAnisotropicFriction(btCollisionObject * colObj, btVector3 & frictionDirection, int frictionMode); - static void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection, int frictionMode); - - void setFrictionConstraintImpulse( btSolverConstraint& solverConstraint, int solverBodyIdA,int solverBodyIdB, - btManifoldPoint& cp, const btContactSolverInfo& infoGlobal); + void setFrictionConstraintImpulse(btSolverConstraint & solverConstraint, int solverBodyIdA, int solverBodyIdB, + btManifoldPoint& cp, const btContactSolverInfo& infoGlobal); ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction - unsigned long m_btSeed2; - + unsigned long m_btSeed2; btScalar restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold); - virtual void convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal); + virtual void convertContacts(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal); - void convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal); + void convertContact(btPersistentManifold * manifold, const btContactSolverInfo& infoGlobal); - virtual void convertJoints(btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal); - void convertJoint(btSolverConstraint* currentConstraintRow, btTypedConstraint* constraint, const btTypedConstraint::btConstraintInfo1& info1, int solverBodyIdA, int solverBodyIdB, const btContactSolverInfo& infoGlobal); + virtual void convertJoints(btTypedConstraint * *constraints, int numConstraints, const btContactSolverInfo& infoGlobal); + void convertJoint(btSolverConstraint * currentConstraintRow, btTypedConstraint * constraint, const btTypedConstraint::btConstraintInfo1& info1, int solverBodyIdA, int solverBodyIdB, const btContactSolverInfo& infoGlobal); - virtual void convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal); + virtual void convertBodies(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal); - btScalar resolveSplitPenetrationSIMD(btSolverBody& bodyA,btSolverBody& bodyB, const btSolverConstraint& contactConstraint) - { - return m_resolveSplitPenetrationImpulse( bodyA, bodyB, contactConstraint ); - } + btScalar resolveSplitPenetrationSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint) + { + return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint); + } - btScalar resolveSplitPenetrationImpulseCacheFriendly(btSolverBody& bodyA,btSolverBody& bodyB, const btSolverConstraint& contactConstraint) - { - return m_resolveSplitPenetrationImpulse( bodyA, bodyB, contactConstraint ); - } + btScalar resolveSplitPenetrationImpulseCacheFriendly(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint) + { + return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint); + } //internal method - int getOrInitSolverBody(btCollisionObject& body,btScalar timeStep); - void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep); - - btScalar resolveSingleConstraintRowGeneric(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint); - btScalar resolveSingleConstraintRowGenericSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint); - btScalar resolveSingleConstraintRowLowerLimit(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint); - btScalar resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint); - btScalar resolveSplitPenetrationImpulse(btSolverBody& bodyA,btSolverBody& bodyB, const btSolverConstraint& contactConstraint) - { - return m_resolveSplitPenetrationImpulse( bodyA, bodyB, contactConstraint ); - } + int getOrInitSolverBody(btCollisionObject & body, btScalar timeStep); + void initSolverBody(btSolverBody * solverBody, btCollisionObject * collisionObject, btScalar timeStep); + + btScalar resolveSingleConstraintRowGeneric(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint); + btScalar resolveSingleConstraintRowGenericSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint); + btScalar resolveSingleConstraintRowLowerLimit(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint); + btScalar resolveSingleConstraintRowLowerLimitSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint); + btScalar resolveSplitPenetrationImpulse(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint) + { + return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint); + } protected: + void writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); + void writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); + void writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); + virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer); + virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal); + virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer); - void writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); - void writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); - void writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); - virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); - virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal); - virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); - - virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); - virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer); - + virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer); + virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer); public: - BT_DECLARE_ALIGNED_ALLOCATOR(); btSequentialImpulseConstraintSolver(); virtual ~btSequentialImpulseConstraintSolver(); - virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher); + virtual btScalar solveGroup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher); ///clear internal cached data and reset random seed - virtual void reset(); + virtual void reset(); unsigned long btRand2(); - int btRandInt2 (int n); + int btRandInt2(int n); - void setRandSeed(unsigned long seed) + void setRandSeed(unsigned long seed) { m_btSeed2 = seed; } - unsigned long getRandSeed() const + unsigned long getRandSeed() const { return m_btSeed2; } - - virtual btConstraintSolverType getSolverType() const + virtual btConstraintSolverType getSolverType() const { return BT_SEQUENTIAL_IMPULSE_SOLVER; } - btSingleConstraintRowSolver getActiveConstraintRowSolverGeneric() + btSingleConstraintRowSolver getActiveConstraintRowSolverGeneric() { return m_resolveSingleConstraintRowGeneric; } @@ -175,7 +170,7 @@ public: { m_resolveSingleConstraintRowGeneric = rowSolver; } - btSingleConstraintRowSolver getActiveConstraintRowSolverLowerLimit() + btSingleConstraintRowSolver getActiveConstraintRowSolverLowerLimit() { return m_resolveSingleConstraintRowLowerLimit; } @@ -185,18 +180,14 @@ public: } ///Various implementations of solving a single constraint row using a generic equality constraint, using scalar reference, SSE2 or SSE4 - btSingleConstraintRowSolver getScalarConstraintRowSolverGeneric(); - btSingleConstraintRowSolver getSSE2ConstraintRowSolverGeneric(); - btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverGeneric(); + btSingleConstraintRowSolver getScalarConstraintRowSolverGeneric(); + btSingleConstraintRowSolver getSSE2ConstraintRowSolverGeneric(); + btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverGeneric(); ///Various implementations of solving a single constraint row using an inequality (lower limit) constraint, using scalar reference, SSE2 or SSE4 - btSingleConstraintRowSolver getScalarConstraintRowSolverLowerLimit(); - btSingleConstraintRowSolver getSSE2ConstraintRowSolverLowerLimit(); - btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverLowerLimit(); + btSingleConstraintRowSolver getScalarConstraintRowSolverLowerLimit(); + btSingleConstraintRowSolver getSSE2ConstraintRowSolverLowerLimit(); + btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverLowerLimit(); }; - - - -#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H - +#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp index 4306c37e49..2718da4a50 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp @@ -13,7 +13,6 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ - #include "btSequentialImpulseConstraintSolverMt.h" #include "LinearMath/btQuickprof.h" @@ -23,8 +22,6 @@ subject to the following restrictions: #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" - - bool btSequentialImpulseConstraintSolverMt::s_allowNestedParallelForLoops = false; // some task schedulers don't like nested loops int btSequentialImpulseConstraintSolverMt::s_minimumContactManifoldsForBatching = 250; int btSequentialImpulseConstraintSolverMt::s_minBatchSize = 50; @@ -32,613 +29,594 @@ int btSequentialImpulseConstraintSolverMt::s_maxBatchSize = 100; btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_contactBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D; btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_jointBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D; - btSequentialImpulseConstraintSolverMt::btSequentialImpulseConstraintSolverMt() { - m_numFrictionDirections = 1; - m_useBatching = false; - m_useObsoleteJointConstraints = false; + m_numFrictionDirections = 1; + m_useBatching = false; + m_useObsoleteJointConstraints = false; } - btSequentialImpulseConstraintSolverMt::~btSequentialImpulseConstraintSolverMt() { } - void btSequentialImpulseConstraintSolverMt::setupBatchedContactConstraints() { - BT_PROFILE("setupBatchedContactConstraints"); - m_batchedContactConstraints.setup( &m_tmpSolverContactConstraintPool, - m_tmpSolverBodyPool, - s_contactBatchingMethod, - s_minBatchSize, - s_maxBatchSize, - &m_scratchMemory - ); + BT_PROFILE("setupBatchedContactConstraints"); + m_batchedContactConstraints.setup(&m_tmpSolverContactConstraintPool, + m_tmpSolverBodyPool, + s_contactBatchingMethod, + s_minBatchSize, + s_maxBatchSize, + &m_scratchMemory); } - void btSequentialImpulseConstraintSolverMt::setupBatchedJointConstraints() { - BT_PROFILE("setupBatchedJointConstraints"); - m_batchedJointConstraints.setup( &m_tmpSolverNonContactConstraintPool, - m_tmpSolverBodyPool, - s_jointBatchingMethod, - s_minBatchSize, - s_maxBatchSize, - &m_scratchMemory - ); + BT_PROFILE("setupBatchedJointConstraints"); + m_batchedJointConstraints.setup(&m_tmpSolverNonContactConstraintPool, + m_tmpSolverBodyPool, + s_jointBatchingMethod, + s_minBatchSize, + s_maxBatchSize, + &m_scratchMemory); } - void btSequentialImpulseConstraintSolverMt::internalSetupContactConstraints(int iContactConstraint, const btContactSolverInfo& infoGlobal) { - btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[iContactConstraint]; - - btVector3 rel_pos1; - btVector3 rel_pos2; - btScalar relaxation; - - int solverBodyIdA = contactConstraint.m_solverBodyIdA; - int solverBodyIdB = contactConstraint.m_solverBodyIdB; - - btSolverBody* solverBodyA = &m_tmpSolverBodyPool[ solverBodyIdA ]; - btSolverBody* solverBodyB = &m_tmpSolverBodyPool[ solverBodyIdB ]; - - btRigidBody* colObj0 = solverBodyA->m_originalBody; - btRigidBody* colObj1 = solverBodyB->m_originalBody; - - btManifoldPoint& cp = *static_cast<btManifoldPoint*>( contactConstraint.m_originalContactPoint ); - - const btVector3& pos1 = cp.getPositionWorldOnA(); - const btVector3& pos2 = cp.getPositionWorldOnB(); - - rel_pos1 = pos1 - solverBodyA->getWorldTransform().getOrigin(); - rel_pos2 = pos2 - solverBodyB->getWorldTransform().getOrigin(); - - btVector3 vel1; - btVector3 vel2; - - solverBodyA->getVelocityInLocalPointNoDelta( rel_pos1, vel1 ); - solverBodyB->getVelocityInLocalPointNoDelta( rel_pos2, vel2 ); - - btVector3 vel = vel1 - vel2; - btScalar rel_vel = cp.m_normalWorldOnB.dot( vel ); - - setupContactConstraint( contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2 ); - - // setup rolling friction constraints - int rollingFrictionIndex = m_rollingFrictionIndexTable[iContactConstraint]; - if (rollingFrictionIndex >= 0) - { - btSolverConstraint& spinningFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ rollingFrictionIndex ]; - btAssert( spinningFrictionConstraint.m_frictionIndex == iContactConstraint ); - setupTorsionalFrictionConstraint( spinningFrictionConstraint, - cp.m_normalWorldOnB, - solverBodyIdA, - solverBodyIdB, - cp, - cp.m_combinedSpinningFriction, - rel_pos1, - rel_pos2, - colObj0, - colObj1, - relaxation, - 0.0f, - 0.0f - ); - btVector3 axis[2]; - btPlaneSpace1( cp.m_normalWorldOnB, axis[0], axis[1] ); - axis[0].normalize(); - axis[1].normalize(); - - applyAnisotropicFriction( colObj0, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION ); - applyAnisotropicFriction( colObj1, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION ); - applyAnisotropicFriction( colObj0, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION ); - applyAnisotropicFriction( colObj1, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION ); - // put the largest axis first - if (axis[1].length2() > axis[0].length2()) - { - btSwap(axis[0], axis[1]); - } - const btScalar kRollingFrictionThreshold = 0.001f; - for (int i = 0; i < 2; ++i) - { - int iRollingFric = rollingFrictionIndex + 1 + i; - btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ iRollingFric ]; - btAssert(rollingFrictionConstraint.m_frictionIndex == iContactConstraint); - btVector3 dir = axis[i]; - if ( dir.length() > kRollingFrictionThreshold ) - { - setupTorsionalFrictionConstraint( rollingFrictionConstraint, - dir, - solverBodyIdA, - solverBodyIdB, - cp, - cp.m_combinedRollingFriction, - rel_pos1, - rel_pos2, - colObj0, - colObj1, - relaxation, - 0.0f, - 0.0f - ); - } - else - { - rollingFrictionConstraint.m_frictionIndex = -1; // disable constraint - } - } - } - - // setup friction constraints - // setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip); - { - ///Bullet has several options to set the friction directions - ///By default, each contact has only a single friction direction that is recomputed automatically very frame - ///based on the relative linear velocity. - ///If the relative velocity it zero, it will automatically compute a friction direction. - - ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS. - ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction. - /// - ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity. - /// - ///The user can manually override the friction directions for certain contacts using a contact callback, - ///and set the cp.m_lateralFrictionInitialized to true - ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2) - ///this will give a conveyor belt effect - /// - btSolverConstraint* frictionConstraint1 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex]; - btAssert(frictionConstraint1->m_frictionIndex == iContactConstraint); - - btSolverConstraint* frictionConstraint2 = NULL; - if ( infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS ) - { - frictionConstraint2 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex + 1]; - btAssert( frictionConstraint2->m_frictionIndex == iContactConstraint ); - } - - if ( !( infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING ) || !( cp.m_contactPointFlags&BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED ) ) - { - cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; - btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); - if ( !( infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION ) && lat_rel_vel > SIMD_EPSILON ) - { - cp.m_lateralFrictionDir1 *= 1.f / btSqrt( lat_rel_vel ); - applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - setupFrictionConstraint( *frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal ); - - if ( frictionConstraint2 ) - { - cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross( cp.m_normalWorldOnB ); - cp.m_lateralFrictionDir2.normalize();//?? - applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - setupFrictionConstraint( *frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal ); - } - } - else - { - btPlaneSpace1( cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2 ); - - applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - setupFrictionConstraint( *frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal ); - - if ( frictionConstraint2 ) - { - applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - setupFrictionConstraint( *frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal ); - } - - if ( ( infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS ) && ( infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION ) ) - { - cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED; - } - } - } - else - { - setupFrictionConstraint( *frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM ); - if ( frictionConstraint2 ) - { - setupFrictionConstraint( *frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM ); - } - } - } - - setFrictionConstraintImpulse( contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal ); -} + btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[iContactConstraint]; + + btVector3 rel_pos1; + btVector3 rel_pos2; + btScalar relaxation; + + int solverBodyIdA = contactConstraint.m_solverBodyIdA; + int solverBodyIdB = contactConstraint.m_solverBodyIdB; + + btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA]; + btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB]; + + btRigidBody* colObj0 = solverBodyA->m_originalBody; + btRigidBody* colObj1 = solverBodyB->m_originalBody; + + btManifoldPoint& cp = *static_cast<btManifoldPoint*>(contactConstraint.m_originalContactPoint); + + const btVector3& pos1 = cp.getPositionWorldOnA(); + const btVector3& pos2 = cp.getPositionWorldOnB(); + + rel_pos1 = pos1 - solverBodyA->getWorldTransform().getOrigin(); + rel_pos2 = pos2 - solverBodyB->getWorldTransform().getOrigin(); + + btVector3 vel1; + btVector3 vel2; + + solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1, vel1); + solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2, vel2); + + btVector3 vel = vel1 - vel2; + btScalar rel_vel = cp.m_normalWorldOnB.dot(vel); + + setupContactConstraint(contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2); + + // setup rolling friction constraints + int rollingFrictionIndex = m_rollingFrictionIndexTable[iContactConstraint]; + if (rollingFrictionIndex >= 0) + { + btSolverConstraint& spinningFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[rollingFrictionIndex]; + btAssert(spinningFrictionConstraint.m_frictionIndex == iContactConstraint); + setupTorsionalFrictionConstraint(spinningFrictionConstraint, + cp.m_normalWorldOnB, + solverBodyIdA, + solverBodyIdB, + cp, + cp.m_combinedSpinningFriction, + rel_pos1, + rel_pos2, + colObj0, + colObj1, + relaxation, + 0.0f, + 0.0f); + btVector3 axis[2]; + btPlaneSpace1(cp.m_normalWorldOnB, axis[0], axis[1]); + axis[0].normalize(); + axis[1].normalize(); + + applyAnisotropicFriction(colObj0, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj1, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj0, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj1, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + // put the largest axis first + if (axis[1].length2() > axis[0].length2()) + { + btSwap(axis[0], axis[1]); + } + const btScalar kRollingFrictionThreshold = 0.001f; + for (int i = 0; i < 2; ++i) + { + int iRollingFric = rollingFrictionIndex + 1 + i; + btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric]; + btAssert(rollingFrictionConstraint.m_frictionIndex == iContactConstraint); + btVector3 dir = axis[i]; + if (dir.length() > kRollingFrictionThreshold) + { + setupTorsionalFrictionConstraint(rollingFrictionConstraint, + dir, + solverBodyIdA, + solverBodyIdB, + cp, + cp.m_combinedRollingFriction, + rel_pos1, + rel_pos2, + colObj0, + colObj1, + relaxation, + 0.0f, + 0.0f); + } + else + { + rollingFrictionConstraint.m_frictionIndex = -1; // disable constraint + } + } + } + + // setup friction constraints + // setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip); + { + ///Bullet has several options to set the friction directions + ///By default, each contact has only a single friction direction that is recomputed automatically very frame + ///based on the relative linear velocity. + ///If the relative velocity it zero, it will automatically compute a friction direction. + + ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS. + ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction. + /// + ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity. + /// + ///The user can manually override the friction directions for certain contacts using a contact callback, + ///and set the cp.m_lateralFrictionInitialized to true + ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2) + ///this will give a conveyor belt effect + /// + btSolverConstraint* frictionConstraint1 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex]; + btAssert(frictionConstraint1->m_frictionIndex == iContactConstraint); + + btSolverConstraint* frictionConstraint2 = NULL; + if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) + { + frictionConstraint2 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex + 1]; + btAssert(frictionConstraint2->m_frictionIndex == iContactConstraint); + } + + if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED)) + { + cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; + btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); + if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON) + { + cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel); + applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION); + setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal); + + if (frictionConstraint2) + { + cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB); + cp.m_lateralFrictionDir2.normalize(); //?? + applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION); + setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal); + } + } + else + { + btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2); + + applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION); + setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal); + + if (frictionConstraint2) + { + applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION); + setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal); + } + + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION)) + { + cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED; + } + } + } + else + { + setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM); + if (frictionConstraint2) + { + setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM); + } + } + } + setFrictionConstraintImpulse(contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal); +} struct SetupContactConstraintsLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btBatchedConstraints* m_bc; - const btContactSolverInfo* m_infoGlobal; - - SetupContactConstraintsLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, const btContactSolverInfo& infoGlobal ) - { - m_solver = solver; - m_bc = bc; - m_infoGlobal = &infoGlobal; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "SetupContactConstraintsLoop" ); - for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch ) - { - const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ]; - for (int i = batch.begin; i < batch.end; ++i) - { - int iContact = m_bc->m_constraintIndices[i]; - m_solver->internalSetupContactConstraints( iContact, *m_infoGlobal ); - } - } - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btBatchedConstraints* m_bc; + const btContactSolverInfo* m_infoGlobal; + SetupContactConstraintsLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, const btContactSolverInfo& infoGlobal) + { + m_solver = solver; + m_bc = bc; + m_infoGlobal = &infoGlobal; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("SetupContactConstraintsLoop"); + for (int iBatch = iBegin; iBatch < iEnd; ++iBatch) + { + const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch]; + for (int i = batch.begin; i < batch.end; ++i) + { + int iContact = m_bc->m_constraintIndices[i]; + m_solver->internalSetupContactConstraints(iContact, *m_infoGlobal); + } + } + } +}; void btSequentialImpulseConstraintSolverMt::setupAllContactConstraints(const btContactSolverInfo& infoGlobal) { - BT_PROFILE( "setupAllContactConstraints" ); - if ( m_useBatching ) - { - const btBatchedConstraints& batchedCons = m_batchedContactConstraints; - SetupContactConstraintsLoop loop( this, &batchedCons, infoGlobal ); - for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase ) - { - int iPhase = batchedCons.m_phaseOrder[ iiPhase ]; - const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ]; - int grainSize = 1; - btParallelFor( phase.begin, phase.end, grainSize, loop ); - } - } - else - { - for ( int i = 0; i < m_tmpSolverContactConstraintPool.size(); ++i ) - { - internalSetupContactConstraints( i, infoGlobal ); - } - } + BT_PROFILE("setupAllContactConstraints"); + if (m_useBatching) + { + const btBatchedConstraints& batchedCons = m_batchedContactConstraints; + SetupContactConstraintsLoop loop(this, &batchedCons, infoGlobal); + for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase) + { + int iPhase = batchedCons.m_phaseOrder[iiPhase]; + const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase]; + int grainSize = 1; + btParallelFor(phase.begin, phase.end, grainSize, loop); + } + } + else + { + for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); ++i) + { + internalSetupContactConstraints(i, infoGlobal); + } + } } - -int btSequentialImpulseConstraintSolverMt::getOrInitSolverBodyThreadsafe(btCollisionObject& body,btScalar timeStep) +int btSequentialImpulseConstraintSolverMt::getOrInitSolverBodyThreadsafe(btCollisionObject& body, btScalar timeStep) { - // - // getOrInitSolverBody is threadsafe only for a single thread per solver (with potentially multiple solvers) - // - // getOrInitSolverBodyThreadsafe -- attempts to be fully threadsafe (however may affect determinism) - // - int solverBodyId = -1; - bool isRigidBodyType = btRigidBody::upcast( &body ) != NULL; - if ( isRigidBodyType && !body.isStaticOrKinematicObject() ) - { - // dynamic body - // Dynamic bodies can only be in one island, so it's safe to write to the companionId - solverBodyId = body.getCompanionId(); - if ( solverBodyId < 0 ) - { - m_bodySolverArrayMutex.lock(); - // now that we have the lock, check again - solverBodyId = body.getCompanionId(); - if ( solverBodyId < 0 ) - { - solverBodyId = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody( &solverBody, &body, timeStep ); - body.setCompanionId( solverBodyId ); - } - m_bodySolverArrayMutex.unlock(); - } - } - else if (isRigidBodyType && body.isKinematicObject()) - { - // - // NOTE: must test for kinematic before static because some kinematic objects also - // identify as "static" - // - // Kinematic bodies can be in multiple islands at once, so it is a - // race condition to write to them, so we use an alternate method - // to record the solverBodyId - int uniqueId = body.getWorldArrayIndex(); - const int INVALID_SOLVER_BODY_ID = -1; - if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId ) - { - m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock(); - // now that we have the lock, check again - if ( m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId ) - { - m_kinematicBodyUniqueIdToSolverBodyTable.resize( uniqueId + 1, INVALID_SOLVER_BODY_ID ); - } - m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock(); - } - solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ]; - // if no table entry yet, - if ( INVALID_SOLVER_BODY_ID == solverBodyId ) - { - // need to acquire both locks - m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock(); - m_bodySolverArrayMutex.lock(); - // now that we have the lock, check again - solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ]; - if ( INVALID_SOLVER_BODY_ID == solverBodyId ) - { - // create a table entry for this body - solverBodyId = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody( &solverBody, &body, timeStep ); - m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ] = solverBodyId; - } - m_bodySolverArrayMutex.unlock(); - m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock(); - } - } - else - { - // all fixed bodies (inf mass) get mapped to a single solver id - if ( m_fixedBodyId < 0 ) - { - m_bodySolverArrayMutex.lock(); - // now that we have the lock, check again - if ( m_fixedBodyId < 0 ) - { - m_fixedBodyId = m_tmpSolverBodyPool.size(); - btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); - initSolverBody( &fixedBody, 0, timeStep ); - } - m_bodySolverArrayMutex.unlock(); - } - solverBodyId = m_fixedBodyId; - } - btAssert( solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size() ); + // + // getOrInitSolverBody is threadsafe only for a single thread per solver (with potentially multiple solvers) + // + // getOrInitSolverBodyThreadsafe -- attempts to be fully threadsafe (however may affect determinism) + // + int solverBodyId = -1; + bool isRigidBodyType = btRigidBody::upcast(&body) != NULL; + if (isRigidBodyType && !body.isStaticOrKinematicObject()) + { + // dynamic body + // Dynamic bodies can only be in one island, so it's safe to write to the companionId + solverBodyId = body.getCompanionId(); + if (solverBodyId < 0) + { + m_bodySolverArrayMutex.lock(); + // now that we have the lock, check again + solverBodyId = body.getCompanionId(); + if (solverBodyId < 0) + { + solverBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody, &body, timeStep); + body.setCompanionId(solverBodyId); + } + m_bodySolverArrayMutex.unlock(); + } + } + else if (isRigidBodyType && body.isKinematicObject()) + { + // + // NOTE: must test for kinematic before static because some kinematic objects also + // identify as "static" + // + // Kinematic bodies can be in multiple islands at once, so it is a + // race condition to write to them, so we use an alternate method + // to record the solverBodyId + int uniqueId = body.getWorldArrayIndex(); + const int INVALID_SOLVER_BODY_ID = -1; + if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId) + { + m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock(); + // now that we have the lock, check again + if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId) + { + m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID); + } + m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock(); + } + solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId]; + // if no table entry yet, + if (INVALID_SOLVER_BODY_ID == solverBodyId) + { + // need to acquire both locks + m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock(); + m_bodySolverArrayMutex.lock(); + // now that we have the lock, check again + solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId]; + if (INVALID_SOLVER_BODY_ID == solverBodyId) + { + // create a table entry for this body + solverBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody, &body, timeStep); + m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId; + } + m_bodySolverArrayMutex.unlock(); + m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock(); + } + } + else + { + // all fixed bodies (inf mass) get mapped to a single solver id + if (m_fixedBodyId < 0) + { + m_bodySolverArrayMutex.lock(); + // now that we have the lock, check again + if (m_fixedBodyId < 0) + { + m_fixedBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&fixedBody, 0, timeStep); + } + m_bodySolverArrayMutex.unlock(); + } + solverBodyId = m_fixedBodyId; + } + btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size()); return solverBodyId; } - void btSequentialImpulseConstraintSolverMt::internalCollectContactManifoldCachedInfo(btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal) { - BT_PROFILE("internalCollectContactManifoldCachedInfo"); - for (int i = 0; i < numManifolds; ++i) - { - btContactManifoldCachedInfo* cachedInfo = &cachedInfoArray[i]; - btPersistentManifold* manifold = manifoldPtr[i]; - btCollisionObject* colObj0 = (btCollisionObject*) manifold->getBody0(); - btCollisionObject* colObj1 = (btCollisionObject*) manifold->getBody1(); - - int solverBodyIdA = getOrInitSolverBodyThreadsafe( *colObj0, infoGlobal.m_timeStep ); - int solverBodyIdB = getOrInitSolverBodyThreadsafe( *colObj1, infoGlobal.m_timeStep ); - - cachedInfo->solverBodyIds[ 0 ] = solverBodyIdA; - cachedInfo->solverBodyIds[ 1 ] = solverBodyIdB; - cachedInfo->numTouchingContacts = 0; - - btSolverBody* solverBodyA = &m_tmpSolverBodyPool[ solverBodyIdA ]; - btSolverBody* solverBodyB = &m_tmpSolverBodyPool[ solverBodyIdB ]; - - // A contact manifold between 2 static object should not exist! - // check the collision flags of your objects if this assert fires. - // Incorrectly set collision object flags can degrade performance in various ways. - btAssert( !m_tmpSolverBodyPool[ solverBodyIdA ].m_invMass.isZero() || !m_tmpSolverBodyPool[ solverBodyIdB ].m_invMass.isZero() ); - - int iContact = 0; - for ( int j = 0; j < manifold->getNumContacts(); j++ ) - { - btManifoldPoint& cp = manifold->getContactPoint( j ); - - if ( cp.getDistance() <= manifold->getContactProcessingThreshold() ) - { - cachedInfo->contactPoints[ iContact ] = &cp; - cachedInfo->contactHasRollingFriction[ iContact ] = ( cp.m_combinedRollingFriction > 0.f ); - iContact++; - } - } - cachedInfo->numTouchingContacts = iContact; - } -} + BT_PROFILE("internalCollectContactManifoldCachedInfo"); + for (int i = 0; i < numManifolds; ++i) + { + btContactManifoldCachedInfo* cachedInfo = &cachedInfoArray[i]; + btPersistentManifold* manifold = manifoldPtr[i]; + btCollisionObject* colObj0 = (btCollisionObject*)manifold->getBody0(); + btCollisionObject* colObj1 = (btCollisionObject*)manifold->getBody1(); + + int solverBodyIdA = getOrInitSolverBodyThreadsafe(*colObj0, infoGlobal.m_timeStep); + int solverBodyIdB = getOrInitSolverBodyThreadsafe(*colObj1, infoGlobal.m_timeStep); + + cachedInfo->solverBodyIds[0] = solverBodyIdA; + cachedInfo->solverBodyIds[1] = solverBodyIdB; + cachedInfo->numTouchingContacts = 0; + + btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA]; + btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB]; + // A contact manifold between 2 static object should not exist! + // check the collision flags of your objects if this assert fires. + // Incorrectly set collision object flags can degrade performance in various ways. + btAssert(!m_tmpSolverBodyPool[solverBodyIdA].m_invMass.isZero() || !m_tmpSolverBodyPool[solverBodyIdB].m_invMass.isZero()); + + int iContact = 0; + for (int j = 0; j < manifold->getNumContacts(); j++) + { + btManifoldPoint& cp = manifold->getContactPoint(j); + + if (cp.getDistance() <= manifold->getContactProcessingThreshold()) + { + cachedInfo->contactPoints[iContact] = &cp; + cachedInfo->contactHasRollingFriction[iContact] = (cp.m_combinedRollingFriction > 0.f); + iContact++; + } + } + cachedInfo->numTouchingContacts = iContact; + } +} struct CollectContactManifoldCachedInfoLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray; - btPersistentManifold** m_manifoldPtr; - const btContactSolverInfo* m_infoGlobal; - - CollectContactManifoldCachedInfoLoop( btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, const btContactSolverInfo& infoGlobal ) - { - m_solver = solver; - m_cachedInfoArray = cachedInfoArray; - m_manifoldPtr = manifoldPtr; - m_infoGlobal = &infoGlobal; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalCollectContactManifoldCachedInfo( m_cachedInfoArray + iBegin, m_manifoldPtr + iBegin, iEnd - iBegin, *m_infoGlobal ); - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray; + btPersistentManifold** m_manifoldPtr; + const btContactSolverInfo* m_infoGlobal; + CollectContactManifoldCachedInfoLoop(btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, const btContactSolverInfo& infoGlobal) + { + m_solver = solver; + m_cachedInfoArray = cachedInfoArray; + m_manifoldPtr = manifoldPtr; + m_infoGlobal = &infoGlobal; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalCollectContactManifoldCachedInfo(m_cachedInfoArray + iBegin, m_manifoldPtr + iBegin, iEnd - iBegin, *m_infoGlobal); + } +}; void btSequentialImpulseConstraintSolverMt::internalAllocContactConstraints(const btContactManifoldCachedInfo* cachedInfoArray, int numManifolds) { - BT_PROFILE("internalAllocContactConstraints"); - // possibly parallel part - for ( int iManifold = 0; iManifold < numManifolds; ++iManifold ) - { - const btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[ iManifold ]; - int contactIndex = cachedInfo.contactIndex; - int frictionIndex = contactIndex * m_numFrictionDirections; - int rollingFrictionIndex = cachedInfo.rollingFrictionIndex; - for ( int i = 0; i < cachedInfo.numTouchingContacts; i++ ) - { - btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[contactIndex]; - contactConstraint.m_solverBodyIdA = cachedInfo.solverBodyIds[ 0 ]; - contactConstraint.m_solverBodyIdB = cachedInfo.solverBodyIds[ 1 ]; - contactConstraint.m_originalContactPoint = cachedInfo.contactPoints[ i ]; - - // allocate the friction constraints - contactConstraint.m_frictionIndex = frictionIndex; - for ( int iDir = 0; iDir < m_numFrictionDirections; ++iDir ) - { - btSolverConstraint& frictionConstraint = m_tmpSolverContactFrictionConstraintPool[frictionIndex]; - frictionConstraint.m_frictionIndex = contactIndex; - frictionIndex++; - } - - // allocate rolling friction constraints - if ( cachedInfo.contactHasRollingFriction[ i ] ) - { - m_rollingFrictionIndexTable[ contactIndex ] = rollingFrictionIndex; - // allocate 3 (although we may use only 2 sometimes) - for ( int i = 0; i < 3; i++ ) - { - m_tmpSolverContactRollingFrictionConstraintPool[ rollingFrictionIndex ].m_frictionIndex = contactIndex; - rollingFrictionIndex++; - } - } - else - { - // indicate there is no rolling friction for this contact point - m_rollingFrictionIndexTable[ contactIndex ] = -1; - } - contactIndex++; - } - } -} + BT_PROFILE("internalAllocContactConstraints"); + // possibly parallel part + for (int iManifold = 0; iManifold < numManifolds; ++iManifold) + { + const btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[iManifold]; + int contactIndex = cachedInfo.contactIndex; + int frictionIndex = contactIndex * m_numFrictionDirections; + int rollingFrictionIndex = cachedInfo.rollingFrictionIndex; + for (int i = 0; i < cachedInfo.numTouchingContacts; i++) + { + btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[contactIndex]; + contactConstraint.m_solverBodyIdA = cachedInfo.solverBodyIds[0]; + contactConstraint.m_solverBodyIdB = cachedInfo.solverBodyIds[1]; + contactConstraint.m_originalContactPoint = cachedInfo.contactPoints[i]; + + // allocate the friction constraints + contactConstraint.m_frictionIndex = frictionIndex; + for (int iDir = 0; iDir < m_numFrictionDirections; ++iDir) + { + btSolverConstraint& frictionConstraint = m_tmpSolverContactFrictionConstraintPool[frictionIndex]; + frictionConstraint.m_frictionIndex = contactIndex; + frictionIndex++; + } + // allocate rolling friction constraints + if (cachedInfo.contactHasRollingFriction[i]) + { + m_rollingFrictionIndexTable[contactIndex] = rollingFrictionIndex; + // allocate 3 (although we may use only 2 sometimes) + for (int i = 0; i < 3; i++) + { + m_tmpSolverContactRollingFrictionConstraintPool[rollingFrictionIndex].m_frictionIndex = contactIndex; + rollingFrictionIndex++; + } + } + else + { + // indicate there is no rolling friction for this contact point + m_rollingFrictionIndexTable[contactIndex] = -1; + } + contactIndex++; + } + } +} struct AllocContactConstraintsLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray; - - AllocContactConstraintsLoop( btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray ) - { - m_solver = solver; - m_cachedInfoArray = cachedInfoArray; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalAllocContactConstraints( m_cachedInfoArray + iBegin, iEnd - iBegin ); - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray; + AllocContactConstraintsLoop(btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray) + { + m_solver = solver; + m_cachedInfoArray = cachedInfoArray; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalAllocContactConstraints(m_cachedInfoArray + iBegin, iEnd - iBegin); + } +}; void btSequentialImpulseConstraintSolverMt::allocAllContactConstraints(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal) { - BT_PROFILE( "allocAllContactConstraints" ); - btAlignedObjectArray<btContactManifoldCachedInfo> cachedInfoArray; // = m_manifoldCachedInfoArray; - cachedInfoArray.resizeNoInitialize( numManifolds ); - if (/* DISABLES CODE */ (false)) - { - // sequential - internalCollectContactManifoldCachedInfo(&cachedInfoArray[ 0 ], manifoldPtr, numManifolds, infoGlobal); - } - else - { - // may alter ordering of bodies which affects determinism - CollectContactManifoldCachedInfoLoop loop( this, &cachedInfoArray[ 0 ], manifoldPtr, infoGlobal ); - int grainSize = 200; - btParallelFor( 0, numManifolds, grainSize, loop ); - } - - { - // serial part - int numContacts = 0; - int numRollingFrictionConstraints = 0; - for ( int iManifold = 0; iManifold < numManifolds; ++iManifold ) - { - btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[ iManifold ]; - cachedInfo.contactIndex = numContacts; - cachedInfo.rollingFrictionIndex = numRollingFrictionConstraints; - numContacts += cachedInfo.numTouchingContacts; - for (int i = 0; i < cachedInfo.numTouchingContacts; ++i) - { - if (cachedInfo.contactHasRollingFriction[i]) - { - numRollingFrictionConstraints += 3; - } - } - } - { - BT_PROFILE( "allocPools" ); - if ( m_tmpSolverContactConstraintPool.capacity() < numContacts ) - { - // if we need to reallocate, reserve some extra so we don't have to reallocate again next frame - int extraReserve = numContacts / 16; - m_tmpSolverContactConstraintPool.reserve( numContacts + extraReserve ); - m_rollingFrictionIndexTable.reserve( numContacts + extraReserve ); - m_tmpSolverContactFrictionConstraintPool.reserve( ( numContacts + extraReserve )*m_numFrictionDirections ); - m_tmpSolverContactRollingFrictionConstraintPool.reserve( numRollingFrictionConstraints + extraReserve ); - } - m_tmpSolverContactConstraintPool.resizeNoInitialize( numContacts ); - m_rollingFrictionIndexTable.resizeNoInitialize( numContacts ); - m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize( numContacts*m_numFrictionDirections ); - m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize( numRollingFrictionConstraints ); - } - } - { - AllocContactConstraintsLoop loop(this, &cachedInfoArray[0]); - int grainSize = 200; - btParallelFor( 0, numManifolds, grainSize, loop ); - } -} + BT_PROFILE("allocAllContactConstraints"); + btAlignedObjectArray<btContactManifoldCachedInfo> cachedInfoArray; // = m_manifoldCachedInfoArray; + cachedInfoArray.resizeNoInitialize(numManifolds); + if (/* DISABLES CODE */ (false)) + { + // sequential + internalCollectContactManifoldCachedInfo(&cachedInfoArray[0], manifoldPtr, numManifolds, infoGlobal); + } + else + { + // may alter ordering of bodies which affects determinism + CollectContactManifoldCachedInfoLoop loop(this, &cachedInfoArray[0], manifoldPtr, infoGlobal); + int grainSize = 200; + btParallelFor(0, numManifolds, grainSize, loop); + } + { + // serial part + int numContacts = 0; + int numRollingFrictionConstraints = 0; + for (int iManifold = 0; iManifold < numManifolds; ++iManifold) + { + btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[iManifold]; + cachedInfo.contactIndex = numContacts; + cachedInfo.rollingFrictionIndex = numRollingFrictionConstraints; + numContacts += cachedInfo.numTouchingContacts; + for (int i = 0; i < cachedInfo.numTouchingContacts; ++i) + { + if (cachedInfo.contactHasRollingFriction[i]) + { + numRollingFrictionConstraints += 3; + } + } + } + { + BT_PROFILE("allocPools"); + if (m_tmpSolverContactConstraintPool.capacity() < numContacts) + { + // if we need to reallocate, reserve some extra so we don't have to reallocate again next frame + int extraReserve = numContacts / 16; + m_tmpSolverContactConstraintPool.reserve(numContacts + extraReserve); + m_rollingFrictionIndexTable.reserve(numContacts + extraReserve); + m_tmpSolverContactFrictionConstraintPool.reserve((numContacts + extraReserve) * m_numFrictionDirections); + m_tmpSolverContactRollingFrictionConstraintPool.reserve(numRollingFrictionConstraints + extraReserve); + } + m_tmpSolverContactConstraintPool.resizeNoInitialize(numContacts); + m_rollingFrictionIndexTable.resizeNoInitialize(numContacts); + m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(numContacts * m_numFrictionDirections); + m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(numRollingFrictionConstraints); + } + } + { + AllocContactConstraintsLoop loop(this, &cachedInfoArray[0]); + int grainSize = 200; + btParallelFor(0, numManifolds, grainSize, loop); + } +} void btSequentialImpulseConstraintSolverMt::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal) { - if (!m_useBatching) - { - btSequentialImpulseConstraintSolver::convertContacts(manifoldPtr, numManifolds, infoGlobal); - return; - } - BT_PROFILE( "convertContacts" ); - if (numManifolds > 0) - { - if ( m_fixedBodyId < 0 ) - { - m_fixedBodyId = m_tmpSolverBodyPool.size(); - btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); - initSolverBody( &fixedBody, 0, infoGlobal.m_timeStep ); - } - allocAllContactConstraints( manifoldPtr, numManifolds, infoGlobal ); - if ( m_useBatching ) - { - setupBatchedContactConstraints(); - } - setupAllContactConstraints( infoGlobal ); - } + if (!m_useBatching) + { + btSequentialImpulseConstraintSolver::convertContacts(manifoldPtr, numManifolds, infoGlobal); + return; + } + BT_PROFILE("convertContacts"); + if (numManifolds > 0) + { + if (m_fixedBodyId < 0) + { + m_fixedBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&fixedBody, 0, infoGlobal.m_timeStep); + } + allocAllContactConstraints(manifoldPtr, numManifolds, infoGlobal); + if (m_useBatching) + { + setupBatchedContactConstraints(); + } + setupAllContactConstraints(infoGlobal); + } } - -void btSequentialImpulseConstraintSolverMt::internalInitMultipleJoints( btTypedConstraint** constraints, int iBegin, int iEnd ) +void btSequentialImpulseConstraintSolverMt::internalInitMultipleJoints(btTypedConstraint** constraints, int iBegin, int iEnd) { - BT_PROFILE("internalInitMultipleJoints"); - for ( int i = iBegin; i < iEnd; i++ ) + BT_PROFILE("internalInitMultipleJoints"); + for (int i = iBegin; i < iEnd; i++) { btTypedConstraint* constraint = constraints[i]; btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i]; if (constraint->isEnabled()) - { - constraint->buildJacobian(); - constraint->internalSetAppliedImpulse( 0.0f ); - btJointFeedback* fb = constraint->getJointFeedback(); - if ( fb ) - { - fb->m_appliedForceBodyA.setZero(); - fb->m_appliedTorqueBodyA.setZero(); - fb->m_appliedForceBodyB.setZero(); - fb->m_appliedTorqueBodyB.setZero(); - } - constraint->getInfo1( &info1 ); - } - else + { + constraint->buildJacobian(); + constraint->internalSetAppliedImpulse(0.0f); + btJointFeedback* fb = constraint->getJointFeedback(); + if (fb) + { + fb->m_appliedForceBodyA.setZero(); + fb->m_appliedTorqueBodyA.setZero(); + fb->m_appliedForceBodyB.setZero(); + fb->m_appliedTorqueBodyB.setZero(); + } + constraint->getInfo1(&info1); + } + else { info1.m_numConstraintRows = 0; info1.nub = 0; @@ -646,158 +624,151 @@ void btSequentialImpulseConstraintSolverMt::internalInitMultipleJoints( btTypedC } } - struct InitJointsLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - btTypedConstraint** m_constraints; - - InitJointsLoop( btSequentialImpulseConstraintSolverMt* solver, btTypedConstraint** constraints ) - { - m_solver = solver; - m_constraints = constraints; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalInitMultipleJoints( m_constraints, iBegin, iEnd ); - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + btTypedConstraint** m_constraints; + InitJointsLoop(btSequentialImpulseConstraintSolverMt* solver, btTypedConstraint** constraints) + { + m_solver = solver; + m_constraints = constraints; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalInitMultipleJoints(m_constraints, iBegin, iEnd); + } +}; -void btSequentialImpulseConstraintSolverMt::internalConvertMultipleJoints( const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal ) +void btSequentialImpulseConstraintSolverMt::internalConvertMultipleJoints(const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal) { - BT_PROFILE("internalConvertMultipleJoints"); - for ( int i = iBegin; i < iEnd; ++i ) - { - const JointParams& jointParams = jointParamsArray[ i ]; - int currentRow = jointParams.m_solverConstraint; - if ( currentRow != -1 ) - { - const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[ i ]; - btAssert( currentRow < m_tmpSolverNonContactConstraintPool.size() ); - btAssert( info1.m_numConstraintRows > 0 ); - - btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[ currentRow ]; - btTypedConstraint* constraint = constraints[ i ]; - - convertJoint( currentConstraintRow, constraint, info1, jointParams.m_solverBodyA, jointParams.m_solverBodyB, infoGlobal ); - } - } -} + BT_PROFILE("internalConvertMultipleJoints"); + for (int i = iBegin; i < iEnd; ++i) + { + const JointParams& jointParams = jointParamsArray[i]; + int currentRow = jointParams.m_solverConstraint; + if (currentRow != -1) + { + const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i]; + btAssert(currentRow < m_tmpSolverNonContactConstraintPool.size()); + btAssert(info1.m_numConstraintRows > 0); + + btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow]; + btTypedConstraint* constraint = constraints[i]; + convertJoint(currentConstraintRow, constraint, info1, jointParams.m_solverBodyA, jointParams.m_solverBodyB, infoGlobal); + } + } +} struct ConvertJointsLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& m_jointParamsArray; - btTypedConstraint** m_srcConstraints; - const btContactSolverInfo& m_infoGlobal; - - ConvertJointsLoop( btSequentialImpulseConstraintSolverMt* solver, - const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& jointParamsArray, - btTypedConstraint** srcConstraints, - const btContactSolverInfo& infoGlobal - ) : - m_jointParamsArray(jointParamsArray), - m_infoGlobal(infoGlobal) - { - m_solver = solver; - m_srcConstraints = srcConstraints; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalConvertMultipleJoints( m_jointParamsArray, m_srcConstraints, iBegin, iEnd, m_infoGlobal ); - } + btSequentialImpulseConstraintSolverMt* m_solver; + const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& m_jointParamsArray; + btTypedConstraint** m_srcConstraints; + const btContactSolverInfo& m_infoGlobal; + + ConvertJointsLoop(btSequentialImpulseConstraintSolverMt* solver, + const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& jointParamsArray, + btTypedConstraint** srcConstraints, + const btContactSolverInfo& infoGlobal) : m_jointParamsArray(jointParamsArray), + m_infoGlobal(infoGlobal) + { + m_solver = solver; + m_srcConstraints = srcConstraints; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalConvertMultipleJoints(m_jointParamsArray, m_srcConstraints, iBegin, iEnd, m_infoGlobal); + } }; - void btSequentialImpulseConstraintSolverMt::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal) { - if ( !m_useBatching ) - { - btSequentialImpulseConstraintSolver::convertJoints(constraints, numConstraints, infoGlobal); - return; - } - BT_PROFILE("convertJoints"); - bool parallelJointSetup = true; + if (!m_useBatching) + { + btSequentialImpulseConstraintSolver::convertJoints(constraints, numConstraints, infoGlobal); + return; + } + BT_PROFILE("convertJoints"); + bool parallelJointSetup = true; m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints); - if (parallelJointSetup) - { - InitJointsLoop loop(this, constraints); - int grainSize = 40; - btParallelFor(0, numConstraints, grainSize, loop); - } - else - { - internalInitMultipleJoints( constraints, 0, numConstraints ); - } + if (parallelJointSetup) + { + InitJointsLoop loop(this, constraints); + int grainSize = 40; + btParallelFor(0, numConstraints, grainSize, loop); + } + else + { + internalInitMultipleJoints(constraints, 0, numConstraints); + } int totalNumRows = 0; - btAlignedObjectArray<JointParams> jointParamsArray; - jointParamsArray.resizeNoInitialize(numConstraints); + btAlignedObjectArray<JointParams> jointParamsArray; + jointParamsArray.resizeNoInitialize(numConstraints); //calculate the total number of contraint rows - for (int i=0;i<numConstraints;i++) + for (int i = 0; i < numConstraints; i++) { - btTypedConstraint* constraint = constraints[ i ]; + btTypedConstraint* constraint = constraints[i]; - JointParams& params = jointParamsArray[ i ]; + JointParams& params = jointParamsArray[i]; const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i]; if (info1.m_numConstraintRows) { - params.m_solverConstraint = totalNumRows; - params.m_solverBodyA = getOrInitSolverBody( constraint->getRigidBodyA(), infoGlobal.m_timeStep ); - params.m_solverBodyB = getOrInitSolverBody( constraint->getRigidBodyB(), infoGlobal.m_timeStep ); + params.m_solverConstraint = totalNumRows; + params.m_solverBodyA = getOrInitSolverBody(constraint->getRigidBodyA(), infoGlobal.m_timeStep); + params.m_solverBodyB = getOrInitSolverBody(constraint->getRigidBodyB(), infoGlobal.m_timeStep); } - else + else { - params.m_solverConstraint = -1; + params.m_solverConstraint = -1; } totalNumRows += info1.m_numConstraintRows; } m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows); ///setup the btSolverConstraints - if ( parallelJointSetup ) - { - ConvertJointsLoop loop(this, jointParamsArray, constraints, infoGlobal); - int grainSize = 20; - btParallelFor(0, numConstraints, grainSize, loop); - } - else - { - internalConvertMultipleJoints( jointParamsArray, constraints, 0, numConstraints, infoGlobal ); - } - setupBatchedJointConstraints(); + if (parallelJointSetup) + { + ConvertJointsLoop loop(this, jointParamsArray, constraints, infoGlobal); + int grainSize = 20; + btParallelFor(0, numConstraints, grainSize, loop); + } + else + { + internalConvertMultipleJoints(jointParamsArray, constraints, 0, numConstraints, infoGlobal); + } + setupBatchedJointConstraints(); } - void btSequentialImpulseConstraintSolverMt::internalConvertBodies(btCollisionObject** bodies, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal) { - BT_PROFILE("internalConvertBodies"); - for (int i=iBegin; i < iEnd; i++) + BT_PROFILE("internalConvertBodies"); + for (int i = iBegin; i < iEnd; i++) { - btCollisionObject* obj = bodies[i]; + btCollisionObject* obj = bodies[i]; obj->setCompanionId(i); btSolverBody& solverBody = m_tmpSolverBodyPool[i]; - initSolverBody(&solverBody, obj, infoGlobal.m_timeStep); + initSolverBody(&solverBody, obj, infoGlobal.m_timeStep); btRigidBody* body = btRigidBody::upcast(obj); if (body && body->getInvMass()) { - btVector3 gyroForce (0,0,0); - if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT) + btVector3 gyroForce(0, 0, 0); + if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT) { gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce); - solverBody.m_externalTorqueImpulse -= gyroForce*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep; + solverBody.m_externalTorqueImpulse -= gyroForce * body->getInvInertiaTensorWorld() * infoGlobal.m_timeStep; } - if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD) + if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD) { gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep); solverBody.m_externalTorqueImpulse += gyroForce; } - if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY) + if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY) { gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep); solverBody.m_externalTorqueImpulse += gyroForce; @@ -806,809 +777,772 @@ void btSequentialImpulseConstraintSolverMt::internalConvertBodies(btCollisionObj } } - struct ConvertBodiesLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - btCollisionObject** m_bodies; - int m_numBodies; - const btContactSolverInfo& m_infoGlobal; - - ConvertBodiesLoop( btSequentialImpulseConstraintSolverMt* solver, - btCollisionObject** bodies, - int numBodies, - const btContactSolverInfo& infoGlobal - ) : - m_infoGlobal(infoGlobal) - { - m_solver = solver; - m_bodies = bodies; - m_numBodies = numBodies; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalConvertBodies( m_bodies, iBegin, iEnd, m_infoGlobal ); - } + btSequentialImpulseConstraintSolverMt* m_solver; + btCollisionObject** m_bodies; + int m_numBodies; + const btContactSolverInfo& m_infoGlobal; + + ConvertBodiesLoop(btSequentialImpulseConstraintSolverMt* solver, + btCollisionObject** bodies, + int numBodies, + const btContactSolverInfo& infoGlobal) : m_infoGlobal(infoGlobal) + { + m_solver = solver; + m_bodies = bodies; + m_numBodies = numBodies; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalConvertBodies(m_bodies, iBegin, iEnd, m_infoGlobal); + } }; - void btSequentialImpulseConstraintSolverMt::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal) { - BT_PROFILE("convertBodies"); - m_kinematicBodyUniqueIdToSolverBodyTable.resize( 0 ); - - m_tmpSolverBodyPool.resizeNoInitialize(numBodies+1); - - m_fixedBodyId = numBodies; - { - btSolverBody& fixedBody = m_tmpSolverBodyPool[ m_fixedBodyId ]; - initSolverBody( &fixedBody, NULL, infoGlobal.m_timeStep ); - } - - bool parallelBodySetup = true; - if (parallelBodySetup) - { - ConvertBodiesLoop loop(this, bodies, numBodies, infoGlobal); - int grainSize = 40; - btParallelFor(0, numBodies, grainSize, loop); - } - else - { - internalConvertBodies( bodies, 0, numBodies, infoGlobal ); - } -} + BT_PROFILE("convertBodies"); + m_kinematicBodyUniqueIdToSolverBodyTable.resize(0); + m_tmpSolverBodyPool.resizeNoInitialize(numBodies + 1); + + m_fixedBodyId = numBodies; + { + btSolverBody& fixedBody = m_tmpSolverBodyPool[m_fixedBodyId]; + initSolverBody(&fixedBody, NULL, infoGlobal.m_timeStep); + } + + bool parallelBodySetup = true; + if (parallelBodySetup) + { + ConvertBodiesLoop loop(this, bodies, numBodies, infoGlobal); + int grainSize = 40; + btParallelFor(0, numBodies, grainSize, loop); + } + else + { + internalConvertBodies(bodies, 0, numBodies, infoGlobal); + } +} btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySetup( - btCollisionObject** bodies, - int numBodies, - btPersistentManifold** manifoldPtr, - int numManifolds, - btTypedConstraint** constraints, - int numConstraints, - const btContactSolverInfo& infoGlobal, - btIDebugDraw* debugDrawer - ) + btCollisionObject** bodies, + int numBodies, + btPersistentManifold** manifoldPtr, + int numManifolds, + btTypedConstraint** constraints, + int numConstraints, + const btContactSolverInfo& infoGlobal, + btIDebugDraw* debugDrawer) { - m_numFrictionDirections = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1; - m_useBatching = false; - if ( numManifolds >= s_minimumContactManifoldsForBatching && - (s_allowNestedParallelForLoops || !btThreadsAreRunning()) - ) - { - m_useBatching = true; - m_batchedContactConstraints.m_debugDrawer = debugDrawer; - m_batchedJointConstraints.m_debugDrawer = debugDrawer; - } - btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup( bodies, - numBodies, - manifoldPtr, - numManifolds, - constraints, - numConstraints, - infoGlobal, - debugDrawer - ); - return 0.0f; + m_numFrictionDirections = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1; + m_useBatching = false; + if (numManifolds >= s_minimumContactManifoldsForBatching && + (s_allowNestedParallelForLoops || !btThreadsAreRunning())) + { + m_useBatching = true; + m_batchedContactConstraints.m_debugDrawer = debugDrawer; + m_batchedJointConstraints.m_debugDrawer = debugDrawer; + } + btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies, + numBodies, + manifoldPtr, + numManifolds, + constraints, + numConstraints, + infoGlobal, + debugDrawer); + return 0.0f; } - -btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactSplitPenetrationImpulseConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd ) +btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactSplitPenetrationImpulseConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd) { - btScalar leastSquaresResidual = 0.f; - for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons ) - { - int iCons = consIndices[ iiCons ]; - const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[ iCons ]; - btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ]; - btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ]; - btScalar residual = resolveSplitPenetrationImpulse( bodyA, bodyB, solveManifold ); - leastSquaresResidual += residual*residual; - } - return leastSquaresResidual; + btScalar leastSquaresResidual = 0.f; + for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons) + { + int iCons = consIndices[iiCons]; + const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iCons]; + btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA]; + btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB]; + btScalar residual = resolveSplitPenetrationImpulse(bodyA, bodyB, solveManifold); + leastSquaresResidual += residual * residual; + } + return leastSquaresResidual; } - struct ContactSplitPenetrationImpulseSolverLoop : public btIParallelSumBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btBatchedConstraints* m_bc; - - ContactSplitPenetrationImpulseSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc ) - { - m_solver = solver; - m_bc = bc; - } - btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "ContactSplitPenetrationImpulseSolverLoop" ); - btScalar sum = 0; - for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch ) - { - const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ]; - sum += m_solver->resolveMultipleContactSplitPenetrationImpulseConstraints( m_bc->m_constraintIndices, batch.begin, batch.end ); - } - return sum; - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btBatchedConstraints* m_bc; + ContactSplitPenetrationImpulseSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc) + { + m_solver = solver; + m_bc = bc; + } + btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("ContactSplitPenetrationImpulseSolverLoop"); + btScalar sum = 0; + for (int iBatch = iBegin; iBatch < iEnd; ++iBatch) + { + const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch]; + sum += m_solver->resolveMultipleContactSplitPenetrationImpulseConstraints(m_bc->m_constraintIndices, batch.begin, batch.end); + } + return sum; + } +}; -void btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) +void btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) { BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations"); if (infoGlobal.m_splitImpulse) { - for ( int iteration = 0; iteration < infoGlobal.m_numIterations; iteration++ ) - { - btScalar leastSquaresResidual = 0.f; - if (m_useBatching) - { - const btBatchedConstraints& batchedCons = m_batchedContactConstraints; - ContactSplitPenetrationImpulseSolverLoop loop( this, &batchedCons ); - btScalar leastSquaresResidual = 0.f; - for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase ) - { - int iPhase = batchedCons.m_phaseOrder[ iiPhase ]; - const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ]; - int grainSize = batchedCons.m_phaseGrainSize[iPhase]; - leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop ); - } - } - else - { - // non-batched - leastSquaresResidual = resolveMultipleContactSplitPenetrationImpulseConstraints(m_orderTmpConstraintPool, 0, m_tmpSolverContactConstraintPool.size()); - } - if ( leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= ( infoGlobal.m_numIterations - 1 ) ) - { + for (int iteration = 0; iteration < infoGlobal.m_numIterations; iteration++) + { + btScalar leastSquaresResidual = 0.f; + if (m_useBatching) + { + const btBatchedConstraints& batchedCons = m_batchedContactConstraints; + ContactSplitPenetrationImpulseSolverLoop loop(this, &batchedCons); + btScalar leastSquaresResidual = 0.f; + for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase) + { + int iPhase = batchedCons.m_phaseOrder[iiPhase]; + const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase]; + int grainSize = batchedCons.m_phaseGrainSize[iPhase]; + leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop); + } + } + else + { + // non-batched + leastSquaresResidual = resolveMultipleContactSplitPenetrationImpulseConstraints(m_orderTmpConstraintPool, 0, m_tmpSolverContactConstraintPool.size()); + } + if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1)) + { #ifdef VERBOSE_RESIDUAL_PRINTF - printf( "residual = %f at iteration #%d\n", leastSquaresResidual, iteration ); + printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration); #endif - break; - } - } + break; + } + } } } - -btScalar btSequentialImpulseConstraintSolverMt::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) +btScalar btSequentialImpulseConstraintSolverMt::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) { - if ( !m_useBatching ) - { - return btSequentialImpulseConstraintSolver::solveSingleIteration( iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer ); - } - BT_PROFILE( "solveSingleIterationMt" ); - btScalar leastSquaresResidual = 0.f; + if (!m_useBatching) + { + return btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer); + } + BT_PROFILE("solveSingleIterationMt"); + btScalar leastSquaresResidual = 0.f; if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER) { - if (1) // uncomment this for a bit less random ((iteration & 7) == 0) + if (1) // uncomment this for a bit less random ((iteration & 7) == 0) { - randomizeConstraintOrdering(iteration, infoGlobal.m_numIterations); + randomizeConstraintOrdering(iteration, infoGlobal.m_numIterations); } } { ///solve all joint constraints - leastSquaresResidual += resolveAllJointConstraints(iteration); + leastSquaresResidual += resolveAllJointConstraints(iteration); - if (iteration< infoGlobal.m_numIterations) + if (iteration < infoGlobal.m_numIterations) { - // this loop is only used for cone-twist constraints, - // it would be nice to skip this loop if none of the constraints need it - if ( m_useObsoleteJointConstraints ) - { - for ( int j = 0; j<numConstraints; j++ ) - { - if ( constraints[ j ]->isEnabled() ) - { - int bodyAid = getOrInitSolverBody( constraints[ j ]->getRigidBodyA(), infoGlobal.m_timeStep ); - int bodyBid = getOrInitSolverBody( constraints[ j ]->getRigidBodyB(), infoGlobal.m_timeStep ); - btSolverBody& bodyA = m_tmpSolverBodyPool[ bodyAid ]; - btSolverBody& bodyB = m_tmpSolverBodyPool[ bodyBid ]; - constraints[ j ]->solveConstraintObsolete( bodyA, bodyB, infoGlobal.m_timeStep ); - } - } - } + // this loop is only used for cone-twist constraints, + // it would be nice to skip this loop if none of the constraints need it + if (m_useObsoleteJointConstraints) + { + for (int j = 0; j < numConstraints; j++) + { + if (constraints[j]->isEnabled()) + { + int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep); + int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep); + btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid]; + btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid]; + constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep); + } + } + } if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS) { - // solve all contact, contact-friction, and rolling friction constraints interleaved - leastSquaresResidual += resolveAllContactConstraintsInterleaved(); + // solve all contact, contact-friction, and rolling friction constraints interleaved + leastSquaresResidual += resolveAllContactConstraintsInterleaved(); } - else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS + else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS { - // don't interleave them + // don't interleave them // solve all contact constraints - leastSquaresResidual += resolveAllContactConstraints(); + leastSquaresResidual += resolveAllContactConstraints(); // solve all contact friction constraints - leastSquaresResidual += resolveAllContactFrictionConstraints(); + leastSquaresResidual += resolveAllContactFrictionConstraints(); - // solve all rolling friction constraints - leastSquaresResidual += resolveAllRollingFrictionConstraints(); + // solve all rolling friction constraints + leastSquaresResidual += resolveAllRollingFrictionConstraints(); } } } - return leastSquaresResidual; + return leastSquaresResidual; } - -btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleJointConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration ) +btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleJointConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration) { - btScalar leastSquaresResidual = 0.f; - for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons ) - { - int iCons = consIndices[ iiCons ]; - const btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[ iCons ]; - if ( iteration < constraint.m_overrideNumSolverIterations ) - { - btSolverBody& bodyA = m_tmpSolverBodyPool[ constraint.m_solverBodyIdA ]; - btSolverBody& bodyB = m_tmpSolverBodyPool[ constraint.m_solverBodyIdB ]; - btScalar residual = resolveSingleConstraintRowGeneric( bodyA, bodyB, constraint ); - leastSquaresResidual += residual*residual; - } - } - return leastSquaresResidual; + btScalar leastSquaresResidual = 0.f; + for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons) + { + int iCons = consIndices[iiCons]; + const btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[iCons]; + if (iteration < constraint.m_overrideNumSolverIterations) + { + btSolverBody& bodyA = m_tmpSolverBodyPool[constraint.m_solverBodyIdA]; + btSolverBody& bodyB = m_tmpSolverBodyPool[constraint.m_solverBodyIdB]; + btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, constraint); + leastSquaresResidual += residual * residual; + } + } + return leastSquaresResidual; } - -btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd ) +btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd) { - btScalar leastSquaresResidual = 0.f; - for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons ) - { - int iCons = consIndices[ iiCons ]; - const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[ iCons ]; - btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ]; - btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ]; - btScalar residual = resolveSingleConstraintRowLowerLimit( bodyA, bodyB, solveManifold ); - leastSquaresResidual += residual*residual; - } - return leastSquaresResidual; + btScalar leastSquaresResidual = 0.f; + for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons) + { + int iCons = consIndices[iiCons]; + const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iCons]; + btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA]; + btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB]; + btScalar residual = resolveSingleConstraintRowLowerLimit(bodyA, bodyB, solveManifold); + leastSquaresResidual += residual * residual; + } + return leastSquaresResidual; } - -btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactFrictionConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd ) +btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd) { - btScalar leastSquaresResidual = 0.f; - for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons ) - { - int iContact = consIndices[ iiCons ]; - btScalar totalImpulse = m_tmpSolverContactConstraintPool[ iContact ].m_appliedImpulse; - - // apply sliding friction - if ( totalImpulse > 0.0f ) - { - int iBegin = iContact * m_numFrictionDirections; - int iEnd = iBegin + m_numFrictionDirections; - for ( int iFriction = iBegin; iFriction < iEnd; ++iFriction ) - { - btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[ iFriction++ ]; - btAssert( solveManifold.m_frictionIndex == iContact ); - - solveManifold.m_lowerLimit = -( solveManifold.m_friction*totalImpulse ); - solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; - - btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ]; - btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ]; - btScalar residual = resolveSingleConstraintRowGeneric( bodyA, bodyB, solveManifold ); - leastSquaresResidual += residual*residual; - } - } - } - return leastSquaresResidual; -} + btScalar leastSquaresResidual = 0.f; + for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons) + { + int iContact = consIndices[iiCons]; + btScalar totalImpulse = m_tmpSolverContactConstraintPool[iContact].m_appliedImpulse; + // apply sliding friction + if (totalImpulse > 0.0f) + { + int iBegin = iContact * m_numFrictionDirections; + int iEnd = iBegin + m_numFrictionDirections; + for (int iFriction = iBegin; iFriction < iEnd; ++iFriction) + { + btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[iFriction++]; + btAssert(solveManifold.m_frictionIndex == iContact); -btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactRollingFrictionConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd ) -{ - btScalar leastSquaresResidual = 0.f; - for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons ) - { - int iContact = consIndices[ iiCons ]; - int iFirstRollingFriction = m_rollingFrictionIndexTable[ iContact ]; - if ( iFirstRollingFriction >= 0 ) - { - btScalar totalImpulse = m_tmpSolverContactConstraintPool[ iContact ].m_appliedImpulse; - // apply rolling friction - if ( totalImpulse > 0.0f ) - { - int iBegin = iFirstRollingFriction; - int iEnd = iBegin + 3; - for ( int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric ) - { - btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ iRollingFric ]; - if ( rollingFrictionConstraint.m_frictionIndex != iContact ) - { - break; - } - btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse; - if ( rollingFrictionMagnitude > rollingFrictionConstraint.m_friction ) - { - rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; - } - - rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; - rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; - - btScalar residual = resolveSingleConstraintRowGeneric( m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdA ], m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdB ], rollingFrictionConstraint ); - leastSquaresResidual += residual*residual; - } - } - } - } - return leastSquaresResidual; -} + solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse; + btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA]; + btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB]; + btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, solveManifold); + leastSquaresResidual += residual * residual; + } + } + } + return leastSquaresResidual; +} -btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraintsInterleaved( const btAlignedObjectArray<int>& contactIndices, - int batchBegin, - int batchEnd - ) +btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactRollingFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd) { - btScalar leastSquaresResidual = 0.f; - int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); - - for ( int iiCons = batchBegin; iiCons < batchEnd; iiCons++ ) - { - btScalar totalImpulse = 0; - int iContact = contactIndices[ iiCons ]; - // apply penetration constraint - { - const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[ iContact ]; - btScalar residual = resolveSingleConstraintRowLowerLimit( m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ], m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ], solveManifold ); - leastSquaresResidual += residual*residual; - totalImpulse = solveManifold.m_appliedImpulse; - } - - // apply sliding friction - if ( totalImpulse > 0.0f ) - { - int iBegin = iContact * m_numFrictionDirections; - int iEnd = iBegin + m_numFrictionDirections; - for ( int iFriction = iBegin; iFriction < iEnd; ++iFriction ) - { - btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[ iFriction ]; - btAssert( solveManifold.m_frictionIndex == iContact ); - - solveManifold.m_lowerLimit = -( solveManifold.m_friction*totalImpulse ); - solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; - - btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ]; - btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ]; - btScalar residual = resolveSingleConstraintRowGeneric( bodyA, bodyB, solveManifold ); - leastSquaresResidual += residual*residual; - } - } - - // apply rolling friction - int iFirstRollingFriction = m_rollingFrictionIndexTable[ iContact ]; - if ( totalImpulse > 0.0f && iFirstRollingFriction >= 0) - { - int iBegin = iFirstRollingFriction; - int iEnd = iBegin + 3; - for ( int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric ) - { - btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ iRollingFric ]; - if ( rollingFrictionConstraint.m_frictionIndex != iContact ) - { - break; - } - btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse; - if ( rollingFrictionMagnitude > rollingFrictionConstraint.m_friction ) - { - rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; - } - - rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; - rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; - - btScalar residual = resolveSingleConstraintRowGeneric( m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdA ], m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdB ], rollingFrictionConstraint ); - leastSquaresResidual += residual*residual; - } - } - } - return leastSquaresResidual; + btScalar leastSquaresResidual = 0.f; + for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons) + { + int iContact = consIndices[iiCons]; + int iFirstRollingFriction = m_rollingFrictionIndexTable[iContact]; + if (iFirstRollingFriction >= 0) + { + btScalar totalImpulse = m_tmpSolverContactConstraintPool[iContact].m_appliedImpulse; + // apply rolling friction + if (totalImpulse > 0.0f) + { + int iBegin = iFirstRollingFriction; + int iEnd = iBegin + 3; + for (int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric) + { + btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric]; + if (rollingFrictionConstraint.m_frictionIndex != iContact) + { + break; + } + btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse; + if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction) + { + rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; + } + + rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; + rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; + + btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint); + leastSquaresResidual += residual * residual; + } + } + } + } + return leastSquaresResidual; } - -void btSequentialImpulseConstraintSolverMt::randomizeBatchedConstraintOrdering( btBatchedConstraints* batchedConstraints ) +btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraintsInterleaved(const btAlignedObjectArray<int>& contactIndices, + int batchBegin, + int batchEnd) { - btBatchedConstraints& bc = *batchedConstraints; - // randomize ordering of phases - for ( int ii = 1; ii < bc.m_phaseOrder.size(); ++ii ) - { - int iSwap = btRandInt2( ii + 1 ); - bc.m_phaseOrder.swap( ii, iSwap ); - } - - // for each batch, - for ( int iBatch = 0; iBatch < bc.m_batches.size(); ++iBatch ) - { - // randomize ordering of constraints within the batch - const btBatchedConstraints::Range& batch = bc.m_batches[ iBatch ]; - for ( int iiCons = batch.begin; iiCons < batch.end; ++iiCons ) - { - int iSwap = batch.begin + btRandInt2( iiCons - batch.begin + 1 ); - btAssert(iSwap >= batch.begin && iSwap < batch.end); - bc.m_constraintIndices.swap( iiCons, iSwap ); - } - } + btScalar leastSquaresResidual = 0.f; + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); + + for (int iiCons = batchBegin; iiCons < batchEnd; iiCons++) + { + btScalar totalImpulse = 0; + int iContact = contactIndices[iiCons]; + // apply penetration constraint + { + const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iContact]; + btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold); + leastSquaresResidual += residual * residual; + totalImpulse = solveManifold.m_appliedImpulse; + } + + // apply sliding friction + if (totalImpulse > 0.0f) + { + int iBegin = iContact * m_numFrictionDirections; + int iEnd = iBegin + m_numFrictionDirections; + for (int iFriction = iBegin; iFriction < iEnd; ++iFriction) + { + btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[iFriction]; + btAssert(solveManifold.m_frictionIndex == iContact); + + solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse; + + btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA]; + btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB]; + btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, solveManifold); + leastSquaresResidual += residual * residual; + } + } + + // apply rolling friction + int iFirstRollingFriction = m_rollingFrictionIndexTable[iContact]; + if (totalImpulse > 0.0f && iFirstRollingFriction >= 0) + { + int iBegin = iFirstRollingFriction; + int iEnd = iBegin + 3; + for (int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric) + { + btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric]; + if (rollingFrictionConstraint.m_frictionIndex != iContact) + { + break; + } + btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse; + if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction) + { + rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; + } + + rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; + rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; + + btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint); + leastSquaresResidual += residual * residual; + } + } + } + return leastSquaresResidual; } +void btSequentialImpulseConstraintSolverMt::randomizeBatchedConstraintOrdering(btBatchedConstraints* batchedConstraints) +{ + btBatchedConstraints& bc = *batchedConstraints; + // randomize ordering of phases + for (int ii = 1; ii < bc.m_phaseOrder.size(); ++ii) + { + int iSwap = btRandInt2(ii + 1); + bc.m_phaseOrder.swap(ii, iSwap); + } + + // for each batch, + for (int iBatch = 0; iBatch < bc.m_batches.size(); ++iBatch) + { + // randomize ordering of constraints within the batch + const btBatchedConstraints::Range& batch = bc.m_batches[iBatch]; + for (int iiCons = batch.begin; iiCons < batch.end; ++iiCons) + { + int iSwap = batch.begin + btRandInt2(iiCons - batch.begin + 1); + btAssert(iSwap >= batch.begin && iSwap < batch.end); + bc.m_constraintIndices.swap(iiCons, iSwap); + } + } +} void btSequentialImpulseConstraintSolverMt::randomizeConstraintOrdering(int iteration, int numIterations) { - // randomize ordering of joint constraints - randomizeBatchedConstraintOrdering( &m_batchedJointConstraints ); - - //contact/friction constraints are not solved more than numIterations - if ( iteration < numIterations ) - { - randomizeBatchedConstraintOrdering( &m_batchedContactConstraints ); - } -} + // randomize ordering of joint constraints + randomizeBatchedConstraintOrdering(&m_batchedJointConstraints); + //contact/friction constraints are not solved more than numIterations + if (iteration < numIterations) + { + randomizeBatchedConstraintOrdering(&m_batchedContactConstraints); + } +} struct JointSolverLoop : public btIParallelSumBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btBatchedConstraints* m_bc; - int m_iteration; - - JointSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, int iteration ) - { - m_solver = solver; - m_bc = bc; - m_iteration = iteration; - } - btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "JointSolverLoop" ); - btScalar sum = 0; - for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch ) - { - const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ]; - sum += m_solver->resolveMultipleJointConstraints( m_bc->m_constraintIndices, batch.begin, batch.end, m_iteration ); - } - return sum; - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btBatchedConstraints* m_bc; + int m_iteration; + JointSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, int iteration) + { + m_solver = solver; + m_bc = bc; + m_iteration = iteration; + } + btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("JointSolverLoop"); + btScalar sum = 0; + for (int iBatch = iBegin; iBatch < iEnd; ++iBatch) + { + const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch]; + sum += m_solver->resolveMultipleJointConstraints(m_bc->m_constraintIndices, batch.begin, batch.end, m_iteration); + } + return sum; + } +}; btScalar btSequentialImpulseConstraintSolverMt::resolveAllJointConstraints(int iteration) { - BT_PROFILE( "resolveAllJointConstraints" ); - const btBatchedConstraints& batchedCons = m_batchedJointConstraints; - JointSolverLoop loop( this, &batchedCons, iteration ); - btScalar leastSquaresResidual = 0.f; - for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase ) - { - int iPhase = batchedCons.m_phaseOrder[ iiPhase ]; - const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ]; - int grainSize = 1; - leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop ); - } - return leastSquaresResidual; + BT_PROFILE("resolveAllJointConstraints"); + const btBatchedConstraints& batchedCons = m_batchedJointConstraints; + JointSolverLoop loop(this, &batchedCons, iteration); + btScalar leastSquaresResidual = 0.f; + for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase) + { + int iPhase = batchedCons.m_phaseOrder[iiPhase]; + const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase]; + int grainSize = 1; + leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop); + } + return leastSquaresResidual; } - struct ContactSolverLoop : public btIParallelSumBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btBatchedConstraints* m_bc; - - ContactSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc ) - { - m_solver = solver; - m_bc = bc; - } - btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "ContactSolverLoop" ); - btScalar sum = 0; - for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch ) - { - const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ]; - sum += m_solver->resolveMultipleContactConstraints( m_bc->m_constraintIndices, batch.begin, batch.end ); - } - return sum; - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btBatchedConstraints* m_bc; + ContactSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc) + { + m_solver = solver; + m_bc = bc; + } + btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("ContactSolverLoop"); + btScalar sum = 0; + for (int iBatch = iBegin; iBatch < iEnd; ++iBatch) + { + const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch]; + sum += m_solver->resolveMultipleContactConstraints(m_bc->m_constraintIndices, batch.begin, batch.end); + } + return sum; + } +}; btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraints() { - BT_PROFILE( "resolveAllContactConstraints" ); - const btBatchedConstraints& batchedCons = m_batchedContactConstraints; - ContactSolverLoop loop( this, &batchedCons ); - btScalar leastSquaresResidual = 0.f; - for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase ) - { - int iPhase = batchedCons.m_phaseOrder[ iiPhase ]; - const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ]; - int grainSize = batchedCons.m_phaseGrainSize[iPhase]; - leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop ); - } - return leastSquaresResidual; + BT_PROFILE("resolveAllContactConstraints"); + const btBatchedConstraints& batchedCons = m_batchedContactConstraints; + ContactSolverLoop loop(this, &batchedCons); + btScalar leastSquaresResidual = 0.f; + for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase) + { + int iPhase = batchedCons.m_phaseOrder[iiPhase]; + const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase]; + int grainSize = batchedCons.m_phaseGrainSize[iPhase]; + leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop); + } + return leastSquaresResidual; } - struct ContactFrictionSolverLoop : public btIParallelSumBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btBatchedConstraints* m_bc; - - ContactFrictionSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc ) - { - m_solver = solver; - m_bc = bc; - } - btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "ContactFrictionSolverLoop" ); - btScalar sum = 0; - for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch ) - { - const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ]; - sum += m_solver->resolveMultipleContactFrictionConstraints( m_bc->m_constraintIndices, batch.begin, batch.end ); - } - return sum; - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btBatchedConstraints* m_bc; + ContactFrictionSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc) + { + m_solver = solver; + m_bc = bc; + } + btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("ContactFrictionSolverLoop"); + btScalar sum = 0; + for (int iBatch = iBegin; iBatch < iEnd; ++iBatch) + { + const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch]; + sum += m_solver->resolveMultipleContactFrictionConstraints(m_bc->m_constraintIndices, batch.begin, batch.end); + } + return sum; + } +}; btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactFrictionConstraints() { - BT_PROFILE( "resolveAllContactFrictionConstraints" ); - const btBatchedConstraints& batchedCons = m_batchedContactConstraints; - ContactFrictionSolverLoop loop( this, &batchedCons ); - btScalar leastSquaresResidual = 0.f; - for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase ) - { - int iPhase = batchedCons.m_phaseOrder[ iiPhase ]; - const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ]; - int grainSize = batchedCons.m_phaseGrainSize[iPhase]; - leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop ); - } - return leastSquaresResidual; + BT_PROFILE("resolveAllContactFrictionConstraints"); + const btBatchedConstraints& batchedCons = m_batchedContactConstraints; + ContactFrictionSolverLoop loop(this, &batchedCons); + btScalar leastSquaresResidual = 0.f; + for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase) + { + int iPhase = batchedCons.m_phaseOrder[iiPhase]; + const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase]; + int grainSize = batchedCons.m_phaseGrainSize[iPhase]; + leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop); + } + return leastSquaresResidual; } - struct InterleavedContactSolverLoop : public btIParallelSumBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btBatchedConstraints* m_bc; - - InterleavedContactSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc ) - { - m_solver = solver; - m_bc = bc; - } - btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "InterleavedContactSolverLoop" ); - btScalar sum = 0; - for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch ) - { - const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ]; - sum += m_solver->resolveMultipleContactConstraintsInterleaved( m_bc->m_constraintIndices, batch.begin, batch.end ); - } - return sum; - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btBatchedConstraints* m_bc; + InterleavedContactSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc) + { + m_solver = solver; + m_bc = bc; + } + btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("InterleavedContactSolverLoop"); + btScalar sum = 0; + for (int iBatch = iBegin; iBatch < iEnd; ++iBatch) + { + const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch]; + sum += m_solver->resolveMultipleContactConstraintsInterleaved(m_bc->m_constraintIndices, batch.begin, batch.end); + } + return sum; + } +}; btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraintsInterleaved() { - BT_PROFILE( "resolveAllContactConstraintsInterleaved" ); - const btBatchedConstraints& batchedCons = m_batchedContactConstraints; - InterleavedContactSolverLoop loop( this, &batchedCons ); - btScalar leastSquaresResidual = 0.f; - for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase ) - { - int iPhase = batchedCons.m_phaseOrder[ iiPhase ]; - const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ]; - int grainSize = 1; - leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop ); - } - return leastSquaresResidual; + BT_PROFILE("resolveAllContactConstraintsInterleaved"); + const btBatchedConstraints& batchedCons = m_batchedContactConstraints; + InterleavedContactSolverLoop loop(this, &batchedCons); + btScalar leastSquaresResidual = 0.f; + for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase) + { + int iPhase = batchedCons.m_phaseOrder[iiPhase]; + const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase]; + int grainSize = 1; + leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop); + } + return leastSquaresResidual; } - struct ContactRollingFrictionSolverLoop : public btIParallelSumBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btBatchedConstraints* m_bc; - - ContactRollingFrictionSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc ) - { - m_solver = solver; - m_bc = bc; - } - btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "ContactFrictionSolverLoop" ); - btScalar sum = 0; - for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch ) - { - const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ]; - sum += m_solver->resolveMultipleContactRollingFrictionConstraints( m_bc->m_constraintIndices, batch.begin, batch.end ); - } - return sum; - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btBatchedConstraints* m_bc; + ContactRollingFrictionSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc) + { + m_solver = solver; + m_bc = bc; + } + btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("ContactFrictionSolverLoop"); + btScalar sum = 0; + for (int iBatch = iBegin; iBatch < iEnd; ++iBatch) + { + const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch]; + sum += m_solver->resolveMultipleContactRollingFrictionConstraints(m_bc->m_constraintIndices, batch.begin, batch.end); + } + return sum; + } +}; btScalar btSequentialImpulseConstraintSolverMt::resolveAllRollingFrictionConstraints() { - BT_PROFILE( "resolveAllRollingFrictionConstraints" ); - btScalar leastSquaresResidual = 0.f; - // - // We do not generate batches for rolling friction constraints. We assume that - // one of two cases is true: - // - // 1. either most bodies in the simulation have rolling friction, in which case we can use the - // batches for contacts and use a lookup table to translate contact indices to rolling friction - // (ignoring any contact indices that don't map to a rolling friction constraint). As long as - // most contacts have a corresponding rolling friction constraint, this should parallelize well. - // - // -OR- - // - // 2. few bodies in the simulation have rolling friction, so it is not worth trying to use the - // batches from contacts as most of the contacts won't have corresponding rolling friction - // constraints and most threads would end up doing very little work. Most of the time would - // go to threading overhead, so we don't bother with threading. - // - int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size(); - if (numRollingFrictionPoolConstraints >= m_tmpSolverContactConstraintPool.size()) - { - // use batching if there are many rolling friction constraints - const btBatchedConstraints& batchedCons = m_batchedContactConstraints; - ContactRollingFrictionSolverLoop loop( this, &batchedCons ); - btScalar leastSquaresResidual = 0.f; - for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase ) - { - int iPhase = batchedCons.m_phaseOrder[ iiPhase ]; - const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ]; - int grainSize = 1; - leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop ); - } - } - else - { - // no batching, also ignores SOLVER_RANDMIZE_ORDER - for ( int j = 0; j < numRollingFrictionPoolConstraints; j++ ) - { - btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ j ]; - if ( rollingFrictionConstraint.m_frictionIndex >= 0 ) - { - btScalar totalImpulse = m_tmpSolverContactConstraintPool[ rollingFrictionConstraint.m_frictionIndex ].m_appliedImpulse; - if ( totalImpulse > 0.0f ) - { - btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse; - if ( rollingFrictionMagnitude > rollingFrictionConstraint.m_friction ) - rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; - - rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; - rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; - - btScalar residual = resolveSingleConstraintRowGeneric( m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdA ], m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdB ], rollingFrictionConstraint ); - leastSquaresResidual += residual*residual; - } - } - } - } - return leastSquaresResidual; + BT_PROFILE("resolveAllRollingFrictionConstraints"); + btScalar leastSquaresResidual = 0.f; + // + // We do not generate batches for rolling friction constraints. We assume that + // one of two cases is true: + // + // 1. either most bodies in the simulation have rolling friction, in which case we can use the + // batches for contacts and use a lookup table to translate contact indices to rolling friction + // (ignoring any contact indices that don't map to a rolling friction constraint). As long as + // most contacts have a corresponding rolling friction constraint, this should parallelize well. + // + // -OR- + // + // 2. few bodies in the simulation have rolling friction, so it is not worth trying to use the + // batches from contacts as most of the contacts won't have corresponding rolling friction + // constraints and most threads would end up doing very little work. Most of the time would + // go to threading overhead, so we don't bother with threading. + // + int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size(); + if (numRollingFrictionPoolConstraints >= m_tmpSolverContactConstraintPool.size()) + { + // use batching if there are many rolling friction constraints + const btBatchedConstraints& batchedCons = m_batchedContactConstraints; + ContactRollingFrictionSolverLoop loop(this, &batchedCons); + btScalar leastSquaresResidual = 0.f; + for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase) + { + int iPhase = batchedCons.m_phaseOrder[iiPhase]; + const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase]; + int grainSize = 1; + leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop); + } + } + else + { + // no batching, also ignores SOLVER_RANDMIZE_ORDER + for (int j = 0; j < numRollingFrictionPoolConstraints; j++) + { + btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j]; + if (rollingFrictionConstraint.m_frictionIndex >= 0) + { + btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse; + if (totalImpulse > 0.0f) + { + btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse; + if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction) + rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; + + rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; + rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; + + btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint); + leastSquaresResidual += residual * residual; + } + } + } + } + return leastSquaresResidual; } - -void btSequentialImpulseConstraintSolverMt::internalWriteBackContacts( int iBegin, int iEnd, const btContactSolverInfo& infoGlobal ) +void btSequentialImpulseConstraintSolverMt::internalWriteBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal) { - BT_PROFILE("internalWriteBackContacts"); - writeBackContacts(iBegin, iEnd, infoGlobal); - //for ( int iContact = iBegin; iContact < iEnd; ++iContact) - //{ - // const btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[ iContact ]; - // btManifoldPoint* pt = (btManifoldPoint*) contactConstraint.m_originalContactPoint; - // btAssert( pt ); - // pt->m_appliedImpulse = contactConstraint.m_appliedImpulse; - // pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex ].m_appliedImpulse; - // if ( m_numFrictionDirections == 2 ) - // { - // pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex + 1 ].m_appliedImpulse; - // } - //} + BT_PROFILE("internalWriteBackContacts"); + writeBackContacts(iBegin, iEnd, infoGlobal); + //for ( int iContact = iBegin; iContact < iEnd; ++iContact) + //{ + // const btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[ iContact ]; + // btManifoldPoint* pt = (btManifoldPoint*) contactConstraint.m_originalContactPoint; + // btAssert( pt ); + // pt->m_appliedImpulse = contactConstraint.m_appliedImpulse; + // pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex ].m_appliedImpulse; + // if ( m_numFrictionDirections == 2 ) + // { + // pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex + 1 ].m_appliedImpulse; + // } + //} } - -void btSequentialImpulseConstraintSolverMt::internalWriteBackJoints( int iBegin, int iEnd, const btContactSolverInfo& infoGlobal ) +void btSequentialImpulseConstraintSolverMt::internalWriteBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal) { BT_PROFILE("internalWriteBackJoints"); - writeBackJoints(iBegin, iEnd, infoGlobal); + writeBackJoints(iBegin, iEnd, infoGlobal); } - -void btSequentialImpulseConstraintSolverMt::internalWriteBackBodies( int iBegin, int iEnd, const btContactSolverInfo& infoGlobal ) +void btSequentialImpulseConstraintSolverMt::internalWriteBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal) { BT_PROFILE("internalWriteBackBodies"); - writeBackBodies( iBegin, iEnd, infoGlobal ); + writeBackBodies(iBegin, iEnd, infoGlobal); } - struct WriteContactPointsLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btContactSolverInfo* m_infoGlobal; - - WriteContactPointsLoop( btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal ) - { - m_solver = solver; - m_infoGlobal = &infoGlobal; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalWriteBackContacts( iBegin, iEnd, *m_infoGlobal ); - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btContactSolverInfo* m_infoGlobal; + WriteContactPointsLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal) + { + m_solver = solver; + m_infoGlobal = &infoGlobal; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalWriteBackContacts(iBegin, iEnd, *m_infoGlobal); + } +}; struct WriteJointsLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btContactSolverInfo* m_infoGlobal; - - WriteJointsLoop( btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal ) - { - m_solver = solver; - m_infoGlobal = &infoGlobal; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalWriteBackJoints( iBegin, iEnd, *m_infoGlobal ); - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btContactSolverInfo* m_infoGlobal; + WriteJointsLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal) + { + m_solver = solver; + m_infoGlobal = &infoGlobal; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalWriteBackJoints(iBegin, iEnd, *m_infoGlobal); + } +}; struct WriteBodiesLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btContactSolverInfo* m_infoGlobal; - - WriteBodiesLoop( btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal ) - { - m_solver = solver; - m_infoGlobal = &infoGlobal; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalWriteBackBodies( iBegin, iEnd, *m_infoGlobal ); - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btContactSolverInfo* m_infoGlobal; + WriteBodiesLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal) + { + m_solver = solver; + m_infoGlobal = &infoGlobal; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalWriteBackBodies(iBegin, iEnd, *m_infoGlobal); + } +}; btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal) { BT_PROFILE("solveGroupCacheFriendlyFinish"); if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) - { - WriteContactPointsLoop loop( this, infoGlobal ); - int grainSize = 500; - btParallelFor( 0, m_tmpSolverContactConstraintPool.size(), grainSize, loop ); - } - - { - WriteJointsLoop loop( this, infoGlobal ); - int grainSize = 400; - btParallelFor( 0, m_tmpSolverNonContactConstraintPool.size(), grainSize, loop ); - } - { - WriteBodiesLoop loop( this, infoGlobal ); - int grainSize = 100; - btParallelFor( 0, m_tmpSolverBodyPool.size(), grainSize, loop ); - } + { + WriteContactPointsLoop loop(this, infoGlobal); + int grainSize = 500; + btParallelFor(0, m_tmpSolverContactConstraintPool.size(), grainSize, loop); + } + + { + WriteJointsLoop loop(this, infoGlobal); + int grainSize = 400; + btParallelFor(0, m_tmpSolverNonContactConstraintPool.size(), grainSize, loop); + } + { + WriteBodiesLoop loop(this, infoGlobal); + int grainSize = 100; + btParallelFor(0, m_tmpSolverBodyPool.size(), grainSize, loop); + } m_tmpSolverContactConstraintPool.resizeNoInitialize(0); m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0); @@ -1618,4 +1552,3 @@ btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlyFinish(bt m_tmpSolverBodyPool.resizeNoInitialize(0); return 0.f; } - diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h index 55d53474c4..1861ddd7d7 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h @@ -53,102 +53,98 @@ subject to the following restrictions: /// because floating point addition is not associative due to rounding errors. /// The task scheduler can and should ensure that the result of any parallelSum operation is deterministic. /// -ATTRIBUTE_ALIGNED16(class) btSequentialImpulseConstraintSolverMt : public btSequentialImpulseConstraintSolver +ATTRIBUTE_ALIGNED16(class) +btSequentialImpulseConstraintSolverMt : public btSequentialImpulseConstraintSolver { public: - virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) BT_OVERRIDE; - virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) BT_OVERRIDE; - virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) BT_OVERRIDE; - virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal) BT_OVERRIDE; - - // temp struct used to collect info from persistent manifolds into a cache-friendly struct using multiple threads - struct btContactManifoldCachedInfo - { - static const int MAX_NUM_CONTACT_POINTS = 4; - - int numTouchingContacts; - int solverBodyIds[ 2 ]; - int contactIndex; - int rollingFrictionIndex; - bool contactHasRollingFriction[ MAX_NUM_CONTACT_POINTS ]; - btManifoldPoint* contactPoints[ MAX_NUM_CONTACT_POINTS ]; - }; - // temp struct used for setting up joint constraints in parallel - struct JointParams - { - int m_solverConstraint; - int m_solverBodyA; - int m_solverBodyB; - }; - void internalInitMultipleJoints(btTypedConstraint** constraints, int iBegin, int iEnd); - void internalConvertMultipleJoints( const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal ); - - // parameters to control batching - static bool s_allowNestedParallelForLoops; // whether to allow nested parallel operations - static int s_minimumContactManifoldsForBatching; // don't even try to batch if fewer manifolds than this - static btBatchedConstraints::BatchingMethod s_contactBatchingMethod; - static btBatchedConstraints::BatchingMethod s_jointBatchingMethod; - static int s_minBatchSize; // desired number of constraints per batch - static int s_maxBatchSize; + virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) BT_OVERRIDE; + virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) BT_OVERRIDE; + virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) BT_OVERRIDE; + virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal) BT_OVERRIDE; + + // temp struct used to collect info from persistent manifolds into a cache-friendly struct using multiple threads + struct btContactManifoldCachedInfo + { + static const int MAX_NUM_CONTACT_POINTS = 4; + + int numTouchingContacts; + int solverBodyIds[2]; + int contactIndex; + int rollingFrictionIndex; + bool contactHasRollingFriction[MAX_NUM_CONTACT_POINTS]; + btManifoldPoint* contactPoints[MAX_NUM_CONTACT_POINTS]; + }; + // temp struct used for setting up joint constraints in parallel + struct JointParams + { + int m_solverConstraint; + int m_solverBodyA; + int m_solverBodyB; + }; + void internalInitMultipleJoints(btTypedConstraint * *constraints, int iBegin, int iEnd); + void internalConvertMultipleJoints(const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); + + // parameters to control batching + static bool s_allowNestedParallelForLoops; // whether to allow nested parallel operations + static int s_minimumContactManifoldsForBatching; // don't even try to batch if fewer manifolds than this + static btBatchedConstraints::BatchingMethod s_contactBatchingMethod; + static btBatchedConstraints::BatchingMethod s_jointBatchingMethod; + static int s_minBatchSize; // desired number of constraints per batch + static int s_maxBatchSize; protected: - static const int CACHE_LINE_SIZE = 64; - - btBatchedConstraints m_batchedContactConstraints; - btBatchedConstraints m_batchedJointConstraints; - int m_numFrictionDirections; - bool m_useBatching; - bool m_useObsoleteJointConstraints; - btAlignedObjectArray<btContactManifoldCachedInfo> m_manifoldCachedInfoArray; - btAlignedObjectArray<int> m_rollingFrictionIndexTable; // lookup table mapping contact index to rolling friction index - btSpinMutex m_bodySolverArrayMutex; - char m_antiFalseSharingPadding[CACHE_LINE_SIZE]; // padding to keep mutexes in separate cachelines - btSpinMutex m_kinematicBodyUniqueIdToSolverBodyTableMutex; - btAlignedObjectArray<char> m_scratchMemory; - - virtual void randomizeConstraintOrdering( int iteration, int numIterations ); - virtual btScalar resolveAllJointConstraints( int iteration ); - virtual btScalar resolveAllContactConstraints(); - virtual btScalar resolveAllContactFrictionConstraints(); - virtual btScalar resolveAllContactConstraintsInterleaved(); - virtual btScalar resolveAllRollingFrictionConstraints(); - - virtual void setupBatchedContactConstraints(); - virtual void setupBatchedJointConstraints(); - virtual void convertJoints(btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal) BT_OVERRIDE; - virtual void convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal) BT_OVERRIDE; - virtual void convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal) BT_OVERRIDE; - - int getOrInitSolverBodyThreadsafe(btCollisionObject& body, btScalar timeStep); - void allocAllContactConstraints(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal); - void setupAllContactConstraints(const btContactSolverInfo& infoGlobal); - void randomizeBatchedConstraintOrdering( btBatchedConstraints* batchedConstraints ); + static const int CACHE_LINE_SIZE = 64; + + btBatchedConstraints m_batchedContactConstraints; + btBatchedConstraints m_batchedJointConstraints; + int m_numFrictionDirections; + bool m_useBatching; + bool m_useObsoleteJointConstraints; + btAlignedObjectArray<btContactManifoldCachedInfo> m_manifoldCachedInfoArray; + btAlignedObjectArray<int> m_rollingFrictionIndexTable; // lookup table mapping contact index to rolling friction index + btSpinMutex m_bodySolverArrayMutex; + char m_antiFalseSharingPadding[CACHE_LINE_SIZE]; // padding to keep mutexes in separate cachelines + btSpinMutex m_kinematicBodyUniqueIdToSolverBodyTableMutex; + btAlignedObjectArray<char> m_scratchMemory; + + virtual void randomizeConstraintOrdering(int iteration, int numIterations); + virtual btScalar resolveAllJointConstraints(int iteration); + virtual btScalar resolveAllContactConstraints(); + virtual btScalar resolveAllContactFrictionConstraints(); + virtual btScalar resolveAllContactConstraintsInterleaved(); + virtual btScalar resolveAllRollingFrictionConstraints(); + + virtual void setupBatchedContactConstraints(); + virtual void setupBatchedJointConstraints(); + virtual void convertJoints(btTypedConstraint * *constraints, int numConstraints, const btContactSolverInfo& infoGlobal) BT_OVERRIDE; + virtual void convertContacts(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal) BT_OVERRIDE; + virtual void convertBodies(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal) BT_OVERRIDE; + + int getOrInitSolverBodyThreadsafe(btCollisionObject & body, btScalar timeStep); + void allocAllContactConstraints(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal); + void setupAllContactConstraints(const btContactSolverInfo& infoGlobal); + void randomizeBatchedConstraintOrdering(btBatchedConstraints * batchedConstraints); public: - BT_DECLARE_ALIGNED_ALLOCATOR(); btSequentialImpulseConstraintSolverMt(); virtual ~btSequentialImpulseConstraintSolverMt(); - btScalar resolveMultipleJointConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration ); - btScalar resolveMultipleContactConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd ); - btScalar resolveMultipleContactSplitPenetrationImpulseConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd ); - btScalar resolveMultipleContactFrictionConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd ); - btScalar resolveMultipleContactRollingFrictionConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd ); - btScalar resolveMultipleContactConstraintsInterleaved( const btAlignedObjectArray<int>& contactIndices, int batchBegin, int batchEnd ); - - void internalCollectContactManifoldCachedInfo(btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal); - void internalAllocContactConstraints(const btContactManifoldCachedInfo* cachedInfoArray, int numManifolds); - void internalSetupContactConstraints(int iContactConstraint, const btContactSolverInfo& infoGlobal); - void internalConvertBodies(btCollisionObject** bodies, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); - void internalWriteBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); - void internalWriteBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); - void internalWriteBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); + btScalar resolveMultipleJointConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration); + btScalar resolveMultipleContactConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd); + btScalar resolveMultipleContactSplitPenetrationImpulseConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd); + btScalar resolveMultipleContactFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd); + btScalar resolveMultipleContactRollingFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd); + btScalar resolveMultipleContactConstraintsInterleaved(const btAlignedObjectArray<int>& contactIndices, int batchBegin, int batchEnd); + + void internalCollectContactManifoldCachedInfo(btContactManifoldCachedInfo * cachedInfoArray, btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal); + void internalAllocContactConstraints(const btContactManifoldCachedInfo* cachedInfoArray, int numManifolds); + void internalSetupContactConstraints(int iContactConstraint, const btContactSolverInfo& infoGlobal); + void internalConvertBodies(btCollisionObject * *bodies, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); + void internalWriteBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); + void internalWriteBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); + void internalWriteBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal); }; - - - -#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_MT_H - +#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_MT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp index d63cef0316..cac5302a73 100755 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp @@ -18,8 +18,6 @@ Added by Roman Ponomarev (rponom@gmail.com) April 04, 2008 */ - - #include "btSliderConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" @@ -29,10 +27,10 @@ April 04, 2008 void btSliderConstraint::initParams() { - m_lowerLinLimit = btScalar(1.0); - m_upperLinLimit = btScalar(-1.0); - m_lowerAngLimit = btScalar(0.); - m_upperAngLimit = btScalar(0.); + m_lowerLinLimit = btScalar(1.0); + m_upperLinLimit = btScalar(-1.0); + m_lowerAngLimit = btScalar(0.); + m_upperAngLimit = btScalar(0.); m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; m_dampingDirLin = btScalar(0.); @@ -59,13 +57,13 @@ void btSliderConstraint::initParams() m_cfmLimAng = SLIDER_CONSTRAINT_DEF_CFM; m_poweredLinMotor = false; - m_targetLinMotorVelocity = btScalar(0.); - m_maxLinMotorForce = btScalar(0.); + m_targetLinMotorVelocity = btScalar(0.); + m_maxLinMotorForce = btScalar(0.); m_accumulatedLinMotorImpulse = btScalar(0.0); m_poweredAngMotor = false; - m_targetAngMotorVelocity = btScalar(0.); - m_maxAngMotorForce = btScalar(0.); + m_targetAngMotorVelocity = btScalar(0.); + m_maxAngMotorForce = btScalar(0.); m_accumulatedAngMotorImpulse = btScalar(0.0); m_flags = 0; @@ -73,43 +71,32 @@ void btSliderConstraint::initParams() m_useOffsetForConstraintFrame = USE_OFFSET_FOR_CONSTANT_FRAME; - calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform()); } - - - - btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) - : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB), - m_useSolveConstraintObsolete(false), - m_frameInA(frameInA), - m_frameInB(frameInB), - m_useLinearReferenceFrameA(useLinearReferenceFrameA) + : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB), + m_useSolveConstraintObsolete(false), + m_frameInA(frameInA), + m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameA) { initParams(); } - - btSliderConstraint::btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA) - : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB), - m_useSolveConstraintObsolete(false), - m_frameInB(frameInB), - m_useLinearReferenceFrameA(useLinearReferenceFrameA) + : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB), + m_useSolveConstraintObsolete(false), + m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameA) { ///not providing rigidbody A means implicitly using worldspace for body A m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB; -// m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin()); + // m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin()); initParams(); } - - - - - void btSliderConstraint::getInfo1(btConstraintInfo1* info) { if (m_useSolveConstraintObsolete) @@ -119,46 +106,39 @@ void btSliderConstraint::getInfo1(btConstraintInfo1* info) } else { - info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular - info->nub = 2; + info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular + info->nub = 2; //prepare constraint - calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform()); testAngLimits(); testLinLimits(); - if(getSolveLinLimit() || getPoweredLinMotor()) + if (getSolveLinLimit() || getPoweredLinMotor()) { - info->m_numConstraintRows++; // limit 3rd linear as well - info->nub--; + info->m_numConstraintRows++; // limit 3rd linear as well + info->nub--; } - if(getSolveAngLimit() || getPoweredAngMotor()) + if (getSolveAngLimit() || getPoweredAngMotor()) { - info->m_numConstraintRows++; // limit 3rd angular as well - info->nub--; + info->m_numConstraintRows++; // limit 3rd angular as well + info->nub--; } } } void btSliderConstraint::getInfo1NonVirtual(btConstraintInfo1* info) { - - info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used) - info->nub = 0; + info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used) + info->nub = 0; } void btSliderConstraint::getInfo2(btConstraintInfo2* info) { - getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(),m_rbB.getLinearVelocity(), m_rbA.getInvMass(),m_rbB.getInvMass()); + getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(), m_rbB.getLinearVelocity(), m_rbA.getInvMass(), m_rbB.getInvMass()); } - - - - - - -void btSliderConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB) +void btSliderConstraint::calculateTransforms(const btTransform& transA, const btTransform& transB) { - if(m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete)) + if (m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete)) { m_calculatedTransformA = transA * m_frameInA; m_calculatedTransformB = transB * m_frameInB; @@ -170,8 +150,8 @@ void btSliderConstraint::calculateTransforms(const btTransform& transA,const btT } m_realPivotAInW = m_calculatedTransformA.getOrigin(); m_realPivotBInW = m_calculatedTransformB.getOrigin(); - m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X - if(m_useLinearReferenceFrameA || m_useSolveConstraintObsolete) + m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X + if (m_useLinearReferenceFrameA || m_useSolveConstraintObsolete) { m_delta = m_realPivotBInW - m_realPivotAInW; } @@ -180,30 +160,28 @@ void btSliderConstraint::calculateTransforms(const btTransform& transA,const btT m_delta = m_realPivotAInW - m_realPivotBInW; } m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; - btVector3 normalWorld; - int i; - //linear part - for(i = 0; i < 3; i++) - { + btVector3 normalWorld; + int i; + //linear part + for (i = 0; i < 3; i++) + { normalWorld = m_calculatedTransformA.getBasis().getColumn(i); m_depth[i] = m_delta.dot(normalWorld); - } + } } - - void btSliderConstraint::testLinLimits(void) { m_solveLinLim = false; m_linPos = m_depth[0]; - if(m_lowerLinLimit <= m_upperLinLimit) + if (m_lowerLinLimit <= m_upperLinLimit) { - if(m_depth[0] > m_upperLinLimit) + if (m_depth[0] > m_upperLinLimit) { m_depth[0] -= m_upperLinLimit; m_solveLinLim = true; } - else if(m_depth[0] < m_lowerLinLimit) + else if (m_depth[0] < m_lowerLinLimit) { m_depth[0] -= m_lowerLinLimit; m_solveLinLim = true; @@ -219,27 +197,25 @@ void btSliderConstraint::testLinLimits(void) } } - - void btSliderConstraint::testAngLimits(void) { m_angDepth = btScalar(0.); m_solveAngLim = false; - if(m_lowerAngLimit <= m_upperAngLimit) + if (m_lowerAngLimit <= m_upperAngLimit) { const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1); const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2); const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1); -// btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0)); - btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0)); + // btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0)); + btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0)); rot = btAdjustAngleToLimits(rot, m_lowerAngLimit, m_upperAngLimit); m_angPos = rot; - if(rot < m_lowerAngLimit) + if (rot < m_lowerAngLimit) { m_angDepth = rot - m_lowerAngLimit; m_solveAngLim = true; - } - else if(rot > m_upperAngLimit) + } + else if (rot > m_upperAngLimit) { m_angDepth = rot - m_upperAngLimit; m_solveAngLim = true; @@ -255,8 +231,6 @@ btVector3 btSliderConstraint::getAncorInA(void) return ancorInA; } - - btVector3 btSliderConstraint::getAncorInB(void) { btVector3 ancorInB; @@ -264,17 +238,16 @@ btVector3 btSliderConstraint::getAncorInB(void) return ancorInB; } - -void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB, const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass ) +void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, btScalar rbAinvMass, btScalar rbBinvMass) { const btTransform& trA = getCalculatedTransformA(); const btTransform& trB = getCalculatedTransformB(); - + btAssert(!m_useSolveConstraintObsolete); int i, s = info->rowskip; - + btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f); - + // difference between frames in WCS btVector3 ofs = trB.getOrigin() - trA.getOrigin(); // now get weight factors depending on masses @@ -283,11 +256,11 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON); btScalar miS = miA + miB; btScalar factA, factB; - if(miS > btScalar(0.f)) + if (miS > btScalar(0.f)) { factA = miB / miS; } - else + else { factA = btScalar(0.5f); } @@ -295,17 +268,17 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra btVector3 ax1, p, q; btVector3 ax1A = trA.getBasis().getColumn(0); btVector3 ax1B = trB.getBasis().getColumn(0); - if(m_useOffsetForConstraintFrame) + if (m_useOffsetForConstraintFrame) { // get the desired direction of slider axis // as weighted sum of X-orthos of frameA and frameB in WCS ax1 = ax1A * factA + ax1B * factB; ax1.normalize(); // construct two orthos to slider axis - btPlaneSpace1 (ax1, p, q); + btPlaneSpace1(ax1, p, q); } else - { // old way - use frameA + { // old way - use frameA ax1 = trA.getBasis().getColumn(0); // get 2 orthos to slider axis (Y, Z) p = trA.getBasis().getColumn(1); @@ -322,16 +295,16 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra info->m_J1angularAxis[0] = p[0]; info->m_J1angularAxis[1] = p[1]; info->m_J1angularAxis[2] = p[2]; - info->m_J1angularAxis[s+0] = q[0]; - info->m_J1angularAxis[s+1] = q[1]; - info->m_J1angularAxis[s+2] = q[2]; + info->m_J1angularAxis[s + 0] = q[0]; + info->m_J1angularAxis[s + 1] = q[1]; + info->m_J1angularAxis[s + 2] = q[2]; info->m_J2angularAxis[0] = -p[0]; info->m_J2angularAxis[1] = -p[1]; info->m_J2angularAxis[2] = -p[2]; - info->m_J2angularAxis[s+0] = -q[0]; - info->m_J2angularAxis[s+1] = -q[1]; - info->m_J2angularAxis[s+2] = -q[2]; + info->m_J2angularAxis[s + 0] = -q[0]; + info->m_J2angularAxis[s + 1] = -q[1]; + info->m_J2angularAxis[s + 2] = -q[2]; // compute the right hand side of the constraint equation. set relative // body velocities along p and q to bring the slider back into alignment. // if ax1A,ax1B are the unit length slider axes as computed from bodyA and @@ -347,25 +320,25 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra // angular_velocity = (erp*fps) * (ax1 x ax2) // ax1 x ax2 is in the plane space of ax1, so we project the angular // velocity to p and q to find the right hand side. -// btScalar k = info->fps * info->erp * getSoftnessOrthoAng(); + // btScalar k = info->fps * info->erp * getSoftnessOrthoAng(); btScalar currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTANG) ? m_softnessOrthoAng : m_softnessOrthoAng * info->erp; btScalar k = info->fps * currERP; btVector3 u = ax1A.cross(ax1B); info->m_constraintError[0] = k * u.dot(p); info->m_constraintError[s] = k * u.dot(q); - if(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG) + if (m_flags & BT_SLIDER_FLAGS_CFM_ORTANG) { info->cfm[0] = m_cfmOrthoAng; info->cfm[s] = m_cfmOrthoAng; } - int nrow = 1; // last filled row + int nrow = 1; // last filled row int srow; btScalar limit_err; int limit; - // next two rows. + // next two rows. // we want: velA + wA x relA == velB + wB x relB ... but this would // result in three equations, so we project along two orthos to the slider axis @@ -375,8 +348,8 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra int s2 = nrow * s; nrow++; int s3 = nrow * s; - btVector3 tmpA(0,0,0), tmpB(0,0,0), relA(0,0,0), relB(0,0,0), c(0,0,0); - if(m_useOffsetForConstraintFrame) + btVector3 tmpA(0, 0, 0), tmpB(0, 0, 0), relA(0, 0, 0), relB(0, 0, 0), c(0, 0, 0); + if (m_useOffsetForConstraintFrame) { // get vector from bodyB to frameB in WCS relB = trB.getOrigin() - bodyB_trans.getOrigin(); @@ -398,7 +371,7 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra // now choose average ortho to slider axis p = orthoB * factA + orthoA * factB; btScalar len2 = p.length2(); - if(len2 > SIMD_EPSILON) + if (len2 > SIMD_EPSILON) { p /= btSqrt(len2); } @@ -411,38 +384,38 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra // fill two rows tmpA = relA.cross(p); tmpB = relB.cross(p); - for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i]; - for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i]; + for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = tmpA[i]; + for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = -tmpB[i]; tmpA = relA.cross(q); tmpB = relB.cross(q); - if(hasStaticBody && getSolveAngLimit()) - { // to make constraint between static and dynamic objects more rigid + if (hasStaticBody && getSolveAngLimit()) + { // to make constraint between static and dynamic objects more rigid // remove wA (or wB) from equation if angular limit is hit tmpB *= factB; tmpA *= factA; } - for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = tmpA[i]; - for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = -tmpB[i]; - for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i]; - for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i]; - for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i]; - for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i]; + for (i = 0; i < 3; i++) info->m_J1angularAxis[s3 + i] = tmpA[i]; + for (i = 0; i < 3; i++) info->m_J2angularAxis[s3 + i] = -tmpB[i]; + for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = p[i]; + for (i = 0; i < 3; i++) info->m_J1linearAxis[s3 + i] = q[i]; + for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -p[i]; + for (i = 0; i < 3; i++) info->m_J2linearAxis[s3 + i] = -q[i]; } else - { // old way - maybe incorrect if bodies are not on the slider axis + { // old way - maybe incorrect if bodies are not on the slider axis // see discussion "Bug in slider constraint" http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4024&start=0 c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin(); btVector3 tmp = c.cross(p); - for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i]; - for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i]; + for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = factA * tmp[i]; + for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = factB * tmp[i]; tmp = c.cross(q); - for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i]; - for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i]; + for (i = 0; i < 3; i++) info->m_J1angularAxis[s3 + i] = factA * tmp[i]; + for (i = 0; i < 3; i++) info->m_J2angularAxis[s3 + i] = factB * tmp[i]; - for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i]; - for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i]; - for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i]; - for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i]; + for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = p[i]; + for (i = 0; i < 3; i++) info->m_J1linearAxis[s3 + i] = q[i]; + for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -p[i]; + for (i = 0; i < 3; i++) info->m_J2linearAxis[s3 + i] = -q[i]; } // compute two elements of right hand side @@ -454,19 +427,18 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra info->m_constraintError[s2] = rhs; rhs = k * q.dot(ofs); info->m_constraintError[s3] = rhs; - if(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN) + if (m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN) { info->cfm[s2] = m_cfmOrthoLin; info->cfm[s3] = m_cfmOrthoLin; } - // check linear limits limit_err = btScalar(0.0); limit = 0; - if(getSolveLinLimit()) + if (getSolveLinLimit()) { - limit_err = getLinDepth() * signFact; + limit_err = getLinDepth() * signFact; limit = (limit_err > btScalar(0.0)) ? 2 : 1; } bool powered = getPoweredLinMotor(); @@ -475,12 +447,12 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra { nrow++; srow = nrow * info->rowskip; - info->m_J1linearAxis[srow+0] = ax1[0]; - info->m_J1linearAxis[srow+1] = ax1[1]; - info->m_J1linearAxis[srow+2] = ax1[2]; - info->m_J2linearAxis[srow+0] = -ax1[0]; - info->m_J2linearAxis[srow+1] = -ax1[1]; - info->m_J2linearAxis[srow+2] = -ax1[2]; + info->m_J1linearAxis[srow + 0] = ax1[0]; + info->m_J1linearAxis[srow + 1] = ax1[1]; + info->m_J1linearAxis[srow + 2] = ax1[2]; + info->m_J2linearAxis[srow + 0] = -ax1[0]; + info->m_J2linearAxis[srow + 1] = -ax1[1]; + info->m_J2linearAxis[srow + 2] = -ax1[2]; // linear torque decoupling step: // // we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies @@ -488,36 +460,36 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra // constraint force is applied at must lie along the same ax1 axis. // a torque couple will result in limited slider-jointed free // bodies from gaining angular momentum. - if(m_useOffsetForConstraintFrame) + if (m_useOffsetForConstraintFrame) { // this is needed only when bodyA and bodyB are both dynamic. - if(!hasStaticBody) + if (!hasStaticBody) { tmpA = relA.cross(ax1); tmpB = relB.cross(ax1); - info->m_J1angularAxis[srow+0] = tmpA[0]; - info->m_J1angularAxis[srow+1] = tmpA[1]; - info->m_J1angularAxis[srow+2] = tmpA[2]; - info->m_J2angularAxis[srow+0] = -tmpB[0]; - info->m_J2angularAxis[srow+1] = -tmpB[1]; - info->m_J2angularAxis[srow+2] = -tmpB[2]; + info->m_J1angularAxis[srow + 0] = tmpA[0]; + info->m_J1angularAxis[srow + 1] = tmpA[1]; + info->m_J1angularAxis[srow + 2] = tmpA[2]; + info->m_J2angularAxis[srow + 0] = -tmpB[0]; + info->m_J2angularAxis[srow + 1] = -tmpB[1]; + info->m_J2angularAxis[srow + 2] = -tmpB[2]; } } else - { // The old way. May be incorrect if bodies are not on the slider axis - btVector3 ltd; // Linear Torque Decoupling vector (a torque) + { // The old way. May be incorrect if bodies are not on the slider axis + btVector3 ltd; // Linear Torque Decoupling vector (a torque) ltd = c.cross(ax1); - info->m_J1angularAxis[srow+0] = factA*ltd[0]; - info->m_J1angularAxis[srow+1] = factA*ltd[1]; - info->m_J1angularAxis[srow+2] = factA*ltd[2]; - info->m_J2angularAxis[srow+0] = factB*ltd[0]; - info->m_J2angularAxis[srow+1] = factB*ltd[1]; - info->m_J2angularAxis[srow+2] = factB*ltd[2]; + info->m_J1angularAxis[srow + 0] = factA * ltd[0]; + info->m_J1angularAxis[srow + 1] = factA * ltd[1]; + info->m_J1angularAxis[srow + 2] = factA * ltd[2]; + info->m_J2angularAxis[srow + 0] = factB * ltd[0]; + info->m_J2angularAxis[srow + 1] = factB * ltd[1]; + info->m_J2angularAxis[srow + 2] = factB * ltd[2]; } // right-hand part btScalar lostop = getLowerLinLimit(); btScalar histop = getUpperLinLimit(); - if(limit && (lostop == histop)) + if (limit && (lostop == histop)) { // the joint motor is ineffective powered = false; } @@ -525,9 +497,9 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra info->m_lowerLimit[srow] = 0.; info->m_upperLimit[srow] = 0.; currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN) ? m_softnessLimLin : info->erp; - if(powered) + if (powered) { - if(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN) + if (m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN) { info->cfm[srow] = m_cfmDirLin; } @@ -537,41 +509,41 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra info->m_lowerLimit[srow] += -getMaxLinMotorForce() / info->fps; info->m_upperLimit[srow] += getMaxLinMotorForce() / info->fps; } - if(limit) + if (limit) { k = info->fps * currERP; info->m_constraintError[srow] += k * limit_err; - if(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN) + if (m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN) { info->cfm[srow] = m_cfmLimLin; } - if(lostop == histop) - { // limited low and high simultaneously + if (lostop == histop) + { // limited low and high simultaneously info->m_lowerLimit[srow] = -SIMD_INFINITY; info->m_upperLimit[srow] = SIMD_INFINITY; } - else if(limit == 1) - { // low limit + else if (limit == 1) + { // low limit info->m_lowerLimit[srow] = -SIMD_INFINITY; info->m_upperLimit[srow] = 0; } - else - { // high limit + else + { // high limit info->m_lowerLimit[srow] = 0; info->m_upperLimit[srow] = SIMD_INFINITY; } // bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that) btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin()); - if(bounce > btScalar(0.0)) + if (bounce > btScalar(0.0)) { btScalar vel = linVelA.dot(ax1); vel -= linVelB.dot(ax1); vel *= signFact; // only apply bounce if the velocity is incoming, and if the // resulting c[] exceeds what we already have. - if(limit == 1) - { // low limit - if(vel < 0) + if (limit == 1) + { // low limit + if (vel < 0) { btScalar newc = -bounce * vel; if (newc > info->m_constraintError[srow]) @@ -581,11 +553,11 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra } } else - { // high limit - all those computations are reversed - if(vel > 0) + { // high limit - all those computations are reversed + if (vel > 0) { btScalar newc = -bounce * vel; - if(newc < info->m_constraintError[srow]) + if (newc < info->m_constraintError[srow]) { info->m_constraintError[srow] = newc; } @@ -593,40 +565,40 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra } } info->m_constraintError[srow] *= getSoftnessLimLin(); - } // if(limit) - } // if linear limit + } // if(limit) + } // if linear limit // check angular limits limit_err = btScalar(0.0); limit = 0; - if(getSolveAngLimit()) + if (getSolveAngLimit()) { limit_err = getAngDepth(); limit = (limit_err > btScalar(0.0)) ? 1 : 2; } // if the slider has joint limits, add in the extra row powered = getPoweredAngMotor(); - if(limit || powered) + if (limit || powered) { nrow++; srow = nrow * info->rowskip; - info->m_J1angularAxis[srow+0] = ax1[0]; - info->m_J1angularAxis[srow+1] = ax1[1]; - info->m_J1angularAxis[srow+2] = ax1[2]; + info->m_J1angularAxis[srow + 0] = ax1[0]; + info->m_J1angularAxis[srow + 1] = ax1[1]; + info->m_J1angularAxis[srow + 2] = ax1[2]; - info->m_J2angularAxis[srow+0] = -ax1[0]; - info->m_J2angularAxis[srow+1] = -ax1[1]; - info->m_J2angularAxis[srow+2] = -ax1[2]; + info->m_J2angularAxis[srow + 0] = -ax1[0]; + info->m_J2angularAxis[srow + 1] = -ax1[1]; + info->m_J2angularAxis[srow + 2] = -ax1[2]; btScalar lostop = getLowerAngLimit(); btScalar histop = getUpperAngLimit(); - if(limit && (lostop == histop)) + if (limit && (lostop == histop)) { // the joint motor is ineffective powered = false; } currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMANG) ? m_softnessLimAng : info->erp; - if(powered) + if (powered) { - if(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG) + if (m_flags & BT_SLIDER_FLAGS_CFM_DIRANG) { info->cfm[srow] = m_cfmDirAng; } @@ -635,55 +607,55 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra info->m_lowerLimit[srow] = -getMaxAngMotorForce() / info->fps; info->m_upperLimit[srow] = getMaxAngMotorForce() / info->fps; } - if(limit) + if (limit) { k = info->fps * currERP; info->m_constraintError[srow] += k * limit_err; - if(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG) + if (m_flags & BT_SLIDER_FLAGS_CFM_LIMANG) { info->cfm[srow] = m_cfmLimAng; } - if(lostop == histop) + if (lostop == histop) { // limited low and high simultaneously info->m_lowerLimit[srow] = -SIMD_INFINITY; info->m_upperLimit[srow] = SIMD_INFINITY; } - else if(limit == 1) - { // low limit + else if (limit == 1) + { // low limit info->m_lowerLimit[srow] = 0; info->m_upperLimit[srow] = SIMD_INFINITY; } - else - { // high limit + else + { // high limit info->m_lowerLimit[srow] = -SIMD_INFINITY; info->m_upperLimit[srow] = 0; } // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng()); - if(bounce > btScalar(0.0)) + if (bounce > btScalar(0.0)) { btScalar vel = m_rbA.getAngularVelocity().dot(ax1); vel -= m_rbB.getAngularVelocity().dot(ax1); // only apply bounce if the velocity is incoming, and if the // resulting c[] exceeds what we already have. - if(limit == 1) - { // low limit - if(vel < 0) + if (limit == 1) + { // low limit + if (vel < 0) { btScalar newc = -bounce * vel; - if(newc > info->m_constraintError[srow]) + if (newc > info->m_constraintError[srow]) { info->m_constraintError[srow] = newc; } } } else - { // high limit - all those computations are reversed - if(vel > 0) + { // high limit - all those computations are reversed + if (vel > 0) { btScalar newc = -bounce * vel; - if(newc < info->m_constraintError[srow]) + if (newc < info->m_constraintError[srow]) { info->m_constraintError[srow] = newc; } @@ -691,165 +663,161 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra } } info->m_constraintError[srow] *= getSoftnessLimAng(); - } // if(limit) - } // if angular limit or powered + } // if(limit) + } // if angular limit or powered } - -///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). +///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). ///If no axis is provided, it uses the default axis for this constraint. void btSliderConstraint::setParam(int num, btScalar value, int axis) { - switch(num) + switch (num) { - case BT_CONSTRAINT_STOP_ERP : - if(axis < 1) - { - m_softnessLimLin = value; - m_flags |= BT_SLIDER_FLAGS_ERP_LIMLIN; - } - else if(axis < 3) - { - m_softnessOrthoLin = value; - m_flags |= BT_SLIDER_FLAGS_ERP_ORTLIN; - } - else if(axis == 3) - { - m_softnessLimAng = value; - m_flags |= BT_SLIDER_FLAGS_ERP_LIMANG; - } - else if(axis < 6) - { - m_softnessOrthoAng = value; - m_flags |= BT_SLIDER_FLAGS_ERP_ORTANG; - } - else - { - btAssertConstrParams(0); - } - break; - case BT_CONSTRAINT_CFM : - if(axis < 1) - { - m_cfmDirLin = value; - m_flags |= BT_SLIDER_FLAGS_CFM_DIRLIN; - } - else if(axis == 3) - { - m_cfmDirAng = value; - m_flags |= BT_SLIDER_FLAGS_CFM_DIRANG; - } - else - { - btAssertConstrParams(0); - } - break; - case BT_CONSTRAINT_STOP_CFM : - if(axis < 1) - { - m_cfmLimLin = value; - m_flags |= BT_SLIDER_FLAGS_CFM_LIMLIN; - } - else if(axis < 3) - { - m_cfmOrthoLin = value; - m_flags |= BT_SLIDER_FLAGS_CFM_ORTLIN; - } - else if(axis == 3) - { - m_cfmLimAng = value; - m_flags |= BT_SLIDER_FLAGS_CFM_LIMANG; - } - else if(axis < 6) - { - m_cfmOrthoAng = value; - m_flags |= BT_SLIDER_FLAGS_CFM_ORTANG; - } - else - { - btAssertConstrParams(0); - } - break; + case BT_CONSTRAINT_STOP_ERP: + if (axis < 1) + { + m_softnessLimLin = value; + m_flags |= BT_SLIDER_FLAGS_ERP_LIMLIN; + } + else if (axis < 3) + { + m_softnessOrthoLin = value; + m_flags |= BT_SLIDER_FLAGS_ERP_ORTLIN; + } + else if (axis == 3) + { + m_softnessLimAng = value; + m_flags |= BT_SLIDER_FLAGS_ERP_LIMANG; + } + else if (axis < 6) + { + m_softnessOrthoAng = value; + m_flags |= BT_SLIDER_FLAGS_ERP_ORTANG; + } + else + { + btAssertConstrParams(0); + } + break; + case BT_CONSTRAINT_CFM: + if (axis < 1) + { + m_cfmDirLin = value; + m_flags |= BT_SLIDER_FLAGS_CFM_DIRLIN; + } + else if (axis == 3) + { + m_cfmDirAng = value; + m_flags |= BT_SLIDER_FLAGS_CFM_DIRANG; + } + else + { + btAssertConstrParams(0); + } + break; + case BT_CONSTRAINT_STOP_CFM: + if (axis < 1) + { + m_cfmLimLin = value; + m_flags |= BT_SLIDER_FLAGS_CFM_LIMLIN; + } + else if (axis < 3) + { + m_cfmOrthoLin = value; + m_flags |= BT_SLIDER_FLAGS_CFM_ORTLIN; + } + else if (axis == 3) + { + m_cfmLimAng = value; + m_flags |= BT_SLIDER_FLAGS_CFM_LIMANG; + } + else if (axis < 6) + { + m_cfmOrthoAng = value; + m_flags |= BT_SLIDER_FLAGS_CFM_ORTANG; + } + else + { + btAssertConstrParams(0); + } + break; } } ///return the local value of parameter -btScalar btSliderConstraint::getParam(int num, int axis) const +btScalar btSliderConstraint::getParam(int num, int axis) const { btScalar retVal(SIMD_INFINITY); - switch(num) + switch (num) { - case BT_CONSTRAINT_STOP_ERP : - if(axis < 1) - { - btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN); - retVal = m_softnessLimLin; - } - else if(axis < 3) - { - btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN); - retVal = m_softnessOrthoLin; - } - else if(axis == 3) - { - btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMANG); - retVal = m_softnessLimAng; - } - else if(axis < 6) - { - btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTANG); - retVal = m_softnessOrthoAng; - } - else - { - btAssertConstrParams(0); - } - break; - case BT_CONSTRAINT_CFM : - if(axis < 1) - { - btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN); - retVal = m_cfmDirLin; - } - else if(axis == 3) - { - btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG); - retVal = m_cfmDirAng; - } - else - { - btAssertConstrParams(0); - } - break; - case BT_CONSTRAINT_STOP_CFM : - if(axis < 1) - { - btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN); - retVal = m_cfmLimLin; - } - else if(axis < 3) - { - btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN); - retVal = m_cfmOrthoLin; - } - else if(axis == 3) - { - btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG); - retVal = m_cfmLimAng; - } - else if(axis < 6) - { - btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG); - retVal = m_cfmOrthoAng; - } - else - { - btAssertConstrParams(0); - } - break; + case BT_CONSTRAINT_STOP_ERP: + if (axis < 1) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN); + retVal = m_softnessLimLin; + } + else if (axis < 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN); + retVal = m_softnessOrthoLin; + } + else if (axis == 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMANG); + retVal = m_softnessLimAng; + } + else if (axis < 6) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTANG); + retVal = m_softnessOrthoAng; + } + else + { + btAssertConstrParams(0); + } + break; + case BT_CONSTRAINT_CFM: + if (axis < 1) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN); + retVal = m_cfmDirLin; + } + else if (axis == 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG); + retVal = m_cfmDirAng; + } + else + { + btAssertConstrParams(0); + } + break; + case BT_CONSTRAINT_STOP_CFM: + if (axis < 1) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN); + retVal = m_cfmLimLin; + } + else if (axis < 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN); + retVal = m_cfmOrthoLin; + } + else if (axis == 3) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG); + retVal = m_cfmLimAng; + } + else if (axis < 6) + { + btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG); + retVal = m_cfmOrthoAng; + } + else + { + btAssertConstrParams(0); + } + break; } return retVal; } - - - diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h index 1957f08a96..75ca34e978 100755 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h @@ -25,31 +25,26 @@ TODO: #ifndef BT_SLIDER_CONSTRAINT_H #define BT_SLIDER_CONSTRAINT_H -#include "LinearMath/btScalar.h"//for BT_USE_DOUBLE_PRECISION +#include "LinearMath/btScalar.h" //for BT_USE_DOUBLE_PRECISION #ifdef BT_USE_DOUBLE_PRECISION -#define btSliderConstraintData2 btSliderConstraintDoubleData -#define btSliderConstraintDataName "btSliderConstraintDoubleData" +#define btSliderConstraintData2 btSliderConstraintDoubleData +#define btSliderConstraintDataName "btSliderConstraintDoubleData" #else -#define btSliderConstraintData2 btSliderConstraintData -#define btSliderConstraintDataName "btSliderConstraintData" -#endif //BT_USE_DOUBLE_PRECISION +#define btSliderConstraintData2 btSliderConstraintData +#define btSliderConstraintDataName "btSliderConstraintData" +#endif //BT_USE_DOUBLE_PRECISION #include "LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" - - class btRigidBody; - - -#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0)) -#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0)) -#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7)) -#define SLIDER_CONSTRAINT_DEF_CFM (btScalar(0.f)) - +#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0)) +#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0)) +#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7)) +#define SLIDER_CONSTRAINT_DEF_CFM (btScalar(0.f)) enum btSliderFlags { @@ -67,15 +62,15 @@ enum btSliderFlags BT_SLIDER_FLAGS_ERP_LIMANG = (1 << 11) }; - -ATTRIBUTE_ALIGNED16(class) btSliderConstraint : public btTypedConstraint +ATTRIBUTE_ALIGNED16(class) +btSliderConstraint : public btTypedConstraint { protected: ///for backwards compatibility during the transition to 'getInfo/getInfo2' - bool m_useSolveConstraintObsolete; - bool m_useOffsetForConstraintFrame; - btTransform m_frameInA; - btTransform m_frameInB; + bool m_useSolveConstraintObsolete; + bool m_useOffsetForConstraintFrame; + btTransform m_frameInA; + btTransform m_frameInB; // use frameA fo define limits, if true bool m_useLinearReferenceFrameA; // linear limits @@ -119,21 +114,21 @@ protected: btScalar m_restitutionOrthoAng; btScalar m_dampingOrthoAng; btScalar m_cfmOrthoAng; - + // for interlal use bool m_solveLinLim; bool m_solveAngLim; int m_flags; - btJacobianEntry m_jacLin[3]; - btScalar m_jacLinDiagABInv[3]; + btJacobianEntry m_jacLin[3]; + btScalar m_jacLinDiagABInv[3]; - btJacobianEntry m_jacAng[3]; + btJacobianEntry m_jacAng[3]; btScalar m_timeStep; - btTransform m_calculatedTransformA; - btTransform m_calculatedTransformB; + btTransform m_calculatedTransformA; + btTransform m_calculatedTransformB; btVector3 m_sliderAxis; btVector3 m_realPivotAInW; @@ -150,57 +145,57 @@ protected: btScalar m_angDepth; btScalar m_kAngle; - bool m_poweredLinMotor; - btScalar m_targetLinMotorVelocity; - btScalar m_maxLinMotorForce; - btScalar m_accumulatedLinMotorImpulse; - - bool m_poweredAngMotor; - btScalar m_targetAngMotorVelocity; - btScalar m_maxAngMotorForce; - btScalar m_accumulatedAngMotorImpulse; - - //------------------------ + bool m_poweredLinMotor; + btScalar m_targetLinMotorVelocity; + btScalar m_maxLinMotorForce; + btScalar m_accumulatedLinMotorImpulse; + + bool m_poweredAngMotor; + btScalar m_targetAngMotorVelocity; + btScalar m_maxAngMotorForce; + btScalar m_accumulatedAngMotorImpulse; + + //------------------------ void initParams(); + public: BT_DECLARE_ALIGNED_ALLOCATOR(); - + // constructors - btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); - btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA); + btSliderConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA); + btSliderConstraint(btRigidBody & rbB, const btTransform& frameInB, bool useLinearReferenceFrameA); // overrides - virtual void getInfo1 (btConstraintInfo1* info); + virtual void getInfo1(btConstraintInfo1 * info); - void getInfo1NonVirtual(btConstraintInfo1* info); - - virtual void getInfo2 (btConstraintInfo2* info); + void getInfo1NonVirtual(btConstraintInfo1 * info); - void getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass); + virtual void getInfo2(btConstraintInfo2 * info); + void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, btScalar rbAinvMass, btScalar rbBinvMass); // access - const btRigidBody& getRigidBodyA() const { return m_rbA; } - const btRigidBody& getRigidBodyB() const { return m_rbB; } - const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; } - const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; } - const btTransform & getFrameOffsetA() const { return m_frameInA; } - const btTransform & getFrameOffsetB() const { return m_frameInB; } - btTransform & getFrameOffsetA() { return m_frameInA; } - btTransform & getFrameOffsetB() { return m_frameInB; } - btScalar getLowerLinLimit() { return m_lowerLinLimit; } - void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; } - btScalar getUpperLinLimit() { return m_upperLinLimit; } - void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; } - btScalar getLowerAngLimit() { return m_lowerAngLimit; } - void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = btNormalizeAngle(lowerLimit); } - btScalar getUpperAngLimit() { return m_upperAngLimit; } - void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = btNormalizeAngle(upperLimit); } + const btRigidBody& getRigidBodyA() const { return m_rbA; } + const btRigidBody& getRigidBodyB() const { return m_rbB; } + const btTransform& getCalculatedTransformA() const { return m_calculatedTransformA; } + const btTransform& getCalculatedTransformB() const { return m_calculatedTransformB; } + const btTransform& getFrameOffsetA() const { return m_frameInA; } + const btTransform& getFrameOffsetB() const { return m_frameInB; } + btTransform& getFrameOffsetA() { return m_frameInA; } + btTransform& getFrameOffsetB() { return m_frameInB; } + btScalar getLowerLinLimit() { return m_lowerLinLimit; } + void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; } + btScalar getUpperLinLimit() { return m_upperLinLimit; } + void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; } + btScalar getLowerAngLimit() { return m_lowerAngLimit; } + void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = btNormalizeAngle(lowerLimit); } + btScalar getUpperAngLimit() { return m_upperAngLimit; } + void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = btNormalizeAngle(upperLimit); } bool getUseLinearReferenceFrameA() { return m_useLinearReferenceFrameA; } btScalar getSoftnessDirLin() { return m_softnessDirLin; } btScalar getRestitutionDirLin() { return m_restitutionDirLin; } - btScalar getDampingDirLin() { return m_dampingDirLin ; } + btScalar getDampingDirLin() { return m_dampingDirLin; } btScalar getSoftnessDirAng() { return m_softnessDirAng; } btScalar getRestitutionDirAng() { return m_restitutionDirAng; } btScalar getDampingDirAng() { return m_dampingDirAng; } @@ -249,8 +244,6 @@ public: btScalar getLinearPos() const { return m_linPos; } btScalar getAngularPos() const { return m_angPos; } - - // access for ODE solver bool getSolveLinLimit() { return m_solveLinLim; } @@ -258,9 +251,9 @@ public: bool getSolveAngLimit() { return m_solveAngLim; } btScalar getAngDepth() { return m_angDepth; } // shared code used by ODE solver - void calculateTransforms(const btTransform& transA,const btTransform& transB); - void testLinLimits(); - void testAngLimits(); + void calculateTransforms(const btTransform& transA, const btTransform& transB); + void testLinLimits(); + void testAngLimits(); // access for PE Solver btVector3 getAncorInA(); btVector3 getAncorInB(); @@ -268,84 +261,75 @@ public: bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; } void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; } - void setFrames(const btTransform& frameA, const btTransform& frameB) - { - m_frameInA=frameA; - m_frameInB=frameB; - calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); + void setFrames(const btTransform& frameA, const btTransform& frameB) + { + m_frameInA = frameA; + m_frameInB = frameB; + calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform()); buildJacobian(); - } - + } - ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). ///If no axis is provided, it uses the default axis for this constraint. - virtual void setParam(int num, btScalar value, int axis = -1); + virtual void setParam(int num, btScalar value, int axis = -1); ///return the local value of parameter - virtual btScalar getParam(int num, int axis = -1) const; - - virtual int getFlags() const - { + virtual btScalar getParam(int num, int axis = -1) const; + + virtual int getFlags() const + { return m_flags; } - virtual int calculateSerializeBufferSize() const; + virtual int calculateSerializeBufferSize() const; ///fills the dataBuffer and returns the struct name (and 0 on failure) - virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; - - + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; }; - ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 - struct btSliderConstraintData { - btTypedConstraintData m_typeConstraintData; - btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTypedConstraintData m_typeConstraintData; + btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis. btTransformFloatData m_rbBFrame; - - float m_linearUpperLimit; - float m_linearLowerLimit; - float m_angularUpperLimit; - float m_angularLowerLimit; + float m_linearUpperLimit; + float m_linearLowerLimit; - int m_useLinearReferenceFrameA; - int m_useOffsetForConstraintFrame; + float m_angularUpperLimit; + float m_angularLowerLimit; + int m_useLinearReferenceFrameA; + int m_useOffsetForConstraintFrame; }; - struct btSliderConstraintDoubleData { - btTypedConstraintDoubleData m_typeConstraintData; - btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTypedConstraintDoubleData m_typeConstraintData; + btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. btTransformDoubleData m_rbBFrame; - - double m_linearUpperLimit; - double m_linearLowerLimit; - double m_angularUpperLimit; - double m_angularLowerLimit; + double m_linearUpperLimit; + double m_linearLowerLimit; - int m_useLinearReferenceFrameA; - int m_useOffsetForConstraintFrame; + double m_angularUpperLimit; + double m_angularLowerLimit; + int m_useLinearReferenceFrameA; + int m_useOffsetForConstraintFrame; }; -SIMD_FORCE_INLINE int btSliderConstraint::calculateSerializeBufferSize() const +SIMD_FORCE_INLINE int btSliderConstraint::calculateSerializeBufferSize() const { return sizeof(btSliderConstraintData2); } - ///fills the dataBuffer and returns the struct name (and 0 on failure) -SIMD_FORCE_INLINE const char* btSliderConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +///fills the dataBuffer and returns the struct name (and 0 on failure) +SIMD_FORCE_INLINE const char* btSliderConstraint::serialize(void* dataBuffer, btSerializer* serializer) const { - - btSliderConstraintData2* sliderData = (btSliderConstraintData2*) dataBuffer; - btTypedConstraint::serialize(&sliderData->m_typeConstraintData,serializer); + btSliderConstraintData2* sliderData = (btSliderConstraintData2*)dataBuffer; + btTypedConstraint::serialize(&sliderData->m_typeConstraintData, serializer); m_frameInA.serialize(sliderData->m_rbAFrame); m_frameInB.serialize(sliderData->m_rbBFrame); @@ -362,7 +346,4 @@ SIMD_FORCE_INLINE const char* btSliderConstraint::serialize(void* dataBuffer, bt return btSliderConstraintDataName; } - - -#endif //BT_SLIDER_CONSTRAINT_H - +#endif //BT_SLIDER_CONSTRAINT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp index 0c7dbd668b..1ea20edcb2 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp @@ -13,43 +13,38 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ - - #include "btSolve2LinearConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btVector3.h" #include "btJacobianEntry.h" - void btSolve2LinearConstraint::resolveUnilateralPairConstraint( - btRigidBody* body1, - btRigidBody* body2, - - const btMatrix3x3& world2A, - const btMatrix3x3& world2B, - - const btVector3& invInertiaADiag, - const btScalar invMassA, - const btVector3& linvelA,const btVector3& angvelA, - const btVector3& rel_posA1, - const btVector3& invInertiaBDiag, - const btScalar invMassB, - const btVector3& linvelB,const btVector3& angvelB, - const btVector3& rel_posA2, - - btScalar depthA, const btVector3& normalA, - const btVector3& rel_posB1,const btVector3& rel_posB2, - btScalar depthB, const btVector3& normalB, - btScalar& imp0,btScalar& imp1) + btRigidBody* body1, + btRigidBody* body2, + + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA, const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB, const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1, const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0, btScalar& imp1) { (void)linvelA; (void)linvelB; (void)angvelB; (void)angvelA; - - imp0 = btScalar(0.); imp1 = btScalar(0.); @@ -59,86 +54,76 @@ void btSolve2LinearConstraint::resolveUnilateralPairConstraint( btAssert(len < SIMD_EPSILON); - //this jacobian entry could be re-used for all iterations - btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA, - invInertiaBDiag,invMassB); - btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA, - invInertiaBDiag,invMassB); - + btJacobianEntry jacA(world2A, world2B, rel_posA1, rel_posA2, normalA, invInertiaADiag, invMassA, + invInertiaBDiag, invMassB); + btJacobianEntry jacB(world2A, world2B, rel_posB1, rel_posB2, normalB, invInertiaADiag, invMassA, + invInertiaBDiag, invMassB); + //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); - const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1)); - const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1)); + const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1) - body2->getVelocityInLocalPoint(rel_posA1)); + const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1) - body2->getVelocityInLocalPoint(rel_posB1)); -// btScalar penetrationImpulse = (depth*contactTau*timeCorrection) * massTerm;//jacDiagABInv + // btScalar penetrationImpulse = (depth*contactTau*timeCorrection) * massTerm;//jacDiagABInv btScalar massTerm = btScalar(1.) / (invMassA + invMassB); - // calculate rhs (or error) terms - const btScalar dv0 = depthA * m_tau * massTerm - vel0 * m_damping; - const btScalar dv1 = depthB * m_tau * massTerm - vel1 * m_damping; - + const btScalar dv0 = depthA * m_tau * massTerm - vel0 * m_damping; + const btScalar dv1 = depthB * m_tau * massTerm - vel1 * m_damping; // dC/dv * dv = -C - + // jacobian * impulse = -error // //impulse = jacobianInverse * -error // inverting 2x2 symmetric system (offdiagonal are equal!) - // + // + btScalar nonDiag = jacA.getNonDiagonal(jacB, invMassA, invMassB); + btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag); - btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB); - btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag ); - //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; - imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; + imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * -nonDiag * invDet; //[a b] [d -c] //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc) //[jA nD] * [imp0] = [dv0] //[nD jB] [imp1] [dv1] - } - - void btSolve2LinearConstraint::resolveBilateralPairConstraint( - btRigidBody* body1, - btRigidBody* body2, - const btMatrix3x3& world2A, - const btMatrix3x3& world2B, - - const btVector3& invInertiaADiag, - const btScalar invMassA, - const btVector3& linvelA,const btVector3& angvelA, - const btVector3& rel_posA1, - const btVector3& invInertiaBDiag, - const btScalar invMassB, - const btVector3& linvelB,const btVector3& angvelB, - const btVector3& rel_posA2, - - btScalar depthA, const btVector3& normalA, - const btVector3& rel_posB1,const btVector3& rel_posB2, - btScalar depthB, const btVector3& normalB, - btScalar& imp0,btScalar& imp1) + btRigidBody* body1, + btRigidBody* body2, + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA, const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB, const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1, const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0, btScalar& imp1) { - (void)linvelA; (void)linvelB; (void)angvelA; (void)angvelB; - - imp0 = btScalar(0.); imp1 = btScalar(0.); @@ -148,42 +133,40 @@ void btSolve2LinearConstraint::resolveBilateralPairConstraint( btAssert(len < SIMD_EPSILON); - //this jacobian entry could be re-used for all iterations - btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA, - invInertiaBDiag,invMassB); - btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA, - invInertiaBDiag,invMassB); - + btJacobianEntry jacA(world2A, world2B, rel_posA1, rel_posA2, normalA, invInertiaADiag, invMassA, + invInertiaBDiag, invMassB); + btJacobianEntry jacB(world2A, world2B, rel_posB1, rel_posB2, normalB, invInertiaADiag, invMassA, + invInertiaBDiag, invMassB); + //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); - const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1)); - const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1)); + const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1) - body2->getVelocityInLocalPoint(rel_posA1)); + const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1) - body2->getVelocityInLocalPoint(rel_posB1)); // calculate rhs (or error) terms - const btScalar dv0 = depthA * m_tau - vel0 * m_damping; - const btScalar dv1 = depthB * m_tau - vel1 * m_damping; + const btScalar dv0 = depthA * m_tau - vel0 * m_damping; + const btScalar dv1 = depthB * m_tau - vel1 * m_damping; // dC/dv * dv = -C - + // jacobian * impulse = -error // //impulse = jacobianInverse * -error // inverting 2x2 symmetric system (offdiagonal are equal!) - // + // + btScalar nonDiag = jacA.getNonDiagonal(jacB, invMassA, invMassB); + btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag); - btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB); - btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag ); - //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; - imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; + imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * -nonDiag * invDet; //[a b] [d -c] //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc) @@ -191,9 +174,9 @@ void btSolve2LinearConstraint::resolveBilateralPairConstraint( //[jA nD] * [imp0] = [dv0] //[nD jB] [imp1] [dv1] - if ( imp0 > btScalar(0.0)) + if (imp0 > btScalar(0.0)) { - if ( imp1 > btScalar(0.0) ) + if (imp1 > btScalar(0.0)) { //both positive } @@ -203,9 +186,10 @@ void btSolve2LinearConstraint::resolveBilateralPairConstraint( // now imp0>0 imp1<0 imp0 = dv0 / jacA.getDiagonal(); - if ( imp0 > btScalar(0.0) ) + if (imp0 > btScalar(0.0)) { - } else + } + else { imp0 = btScalar(0.); } @@ -216,24 +200,25 @@ void btSolve2LinearConstraint::resolveBilateralPairConstraint( imp0 = btScalar(0.); imp1 = dv1 / jacB.getDiagonal(); - if ( imp1 <= btScalar(0.0) ) + if (imp1 <= btScalar(0.0)) { imp1 = btScalar(0.); // now imp0>0 imp1<0 imp0 = dv0 / jacA.getDiagonal(); - if ( imp0 > btScalar(0.0) ) + if (imp0 > btScalar(0.0)) { - } else + } + else { imp0 = btScalar(0.); } - } else + } + else { } } } - /* void btSolve2LinearConstraint::resolveAngularConstraint( const btMatrix3x3& invInertiaAWS, const btScalar invMassA, @@ -252,4 +237,3 @@ void btSolve2LinearConstraint::resolveAngularConstraint( const btMatrix3x3& invI } */ - diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h index e8bfabf864..fca8ecec81 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h @@ -19,20 +19,16 @@ subject to the following restrictions: #include "LinearMath/btMatrix3x3.h" #include "LinearMath/btVector3.h" - class btRigidBody; - - /// constraint class used for lateral tyre friction. -class btSolve2LinearConstraint +class btSolve2LinearConstraint { - btScalar m_tau; - btScalar m_damping; + btScalar m_tau; + btScalar m_damping; public: - - btSolve2LinearConstraint(btScalar tau,btScalar damping) + btSolve2LinearConstraint(btScalar tau, btScalar damping) { m_tau = tau; m_damping = damping; @@ -40,52 +36,51 @@ public: // // solve unilateral constraint (equality, direct method) // - void resolveUnilateralPairConstraint( - btRigidBody* body0, + void resolveUnilateralPairConstraint( + btRigidBody* body0, btRigidBody* body1, const btMatrix3x3& world2A, - const btMatrix3x3& world2B, - - const btVector3& invInertiaADiag, - const btScalar invMassA, - const btVector3& linvelA,const btVector3& angvelA, - const btVector3& rel_posA1, - const btVector3& invInertiaBDiag, - const btScalar invMassB, - const btVector3& linvelB,const btVector3& angvelB, - const btVector3& rel_posA2, - - btScalar depthA, const btVector3& normalA, - const btVector3& rel_posB1,const btVector3& rel_posB2, - btScalar depthB, const btVector3& normalB, - btScalar& imp0,btScalar& imp1); - + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA, const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB, const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1, const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0, btScalar& imp1); // // solving 2x2 lcp problem (inequality, direct solution ) // void resolveBilateralPairConstraint( - btRigidBody* body0, - btRigidBody* body1, + btRigidBody* body0, + btRigidBody* body1, const btMatrix3x3& world2A, - const btMatrix3x3& world2B, - - const btVector3& invInertiaADiag, - const btScalar invMassA, - const btVector3& linvelA,const btVector3& angvelA, - const btVector3& rel_posA1, - const btVector3& invInertiaBDiag, - const btScalar invMassB, - const btVector3& linvelB,const btVector3& angvelB, - const btVector3& rel_posA2, - - btScalar depthA, const btVector3& normalA, - const btVector3& rel_posB1,const btVector3& rel_posB2, - btScalar depthB, const btVector3& normalB, - btScalar& imp0,btScalar& imp1); - -/* + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA, const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB, const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1, const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0, btScalar& imp1); + + /* void resolveAngularConstraint( const btMatrix3x3& invInertiaAWS, const btScalar invMassA, const btVector3& linvelA,const btVector3& angvelA, @@ -101,7 +96,6 @@ public: btScalar& imp0,btScalar& imp1); */ - }; -#endif //BT_SOLVE_2LINEAR_CONSTRAINT_H +#endif //BT_SOLVE_2LINEAR_CONSTRAINT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h index 27ccefe416..409aa8a08c 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef BT_SOLVER_BODY_H #define BT_SOLVER_BODY_H -class btRigidBody; +class btRigidBody; #include "LinearMath/btVector3.h" #include "LinearMath/btMatrix3x3.h" @@ -26,103 +26,99 @@ class btRigidBody; ///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision #ifdef BT_USE_SSE #define USE_SIMD 1 -#endif // - +#endif // #ifdef USE_SIMD -struct btSimdScalar +struct btSimdScalar { - SIMD_FORCE_INLINE btSimdScalar() + SIMD_FORCE_INLINE btSimdScalar() { - } - SIMD_FORCE_INLINE btSimdScalar(float fl) - :m_vec128 (_mm_set1_ps(fl)) + SIMD_FORCE_INLINE btSimdScalar(float fl) + : m_vec128(_mm_set1_ps(fl)) { } - SIMD_FORCE_INLINE btSimdScalar(__m128 v128) - :m_vec128(v128) + SIMD_FORCE_INLINE btSimdScalar(__m128 v128) + : m_vec128(v128) { } - union - { - __m128 m_vec128; - float m_floats[4]; - int m_ints[4]; - btScalar m_unusedPadding; + union { + __m128 m_vec128; + float m_floats[4]; + int m_ints[4]; + btScalar m_unusedPadding; }; - SIMD_FORCE_INLINE __m128 get128() + SIMD_FORCE_INLINE __m128 get128() { return m_vec128; } - SIMD_FORCE_INLINE const __m128 get128() const + SIMD_FORCE_INLINE const __m128 get128() const { return m_vec128; } - SIMD_FORCE_INLINE void set128(__m128 v128) + SIMD_FORCE_INLINE void set128(__m128 v128) { m_vec128 = v128; } - SIMD_FORCE_INLINE operator __m128() - { - return m_vec128; - } - SIMD_FORCE_INLINE operator const __m128() const - { - return m_vec128; + SIMD_FORCE_INLINE operator __m128() + { + return m_vec128; } - - SIMD_FORCE_INLINE operator float() const - { - return m_floats[0]; + SIMD_FORCE_INLINE operator const __m128() const + { + return m_vec128; } + SIMD_FORCE_INLINE operator float() const + { + return m_floats[0]; + } }; ///@brief Return the elementwise product of two btSimdScalar -SIMD_FORCE_INLINE btSimdScalar -operator*(const btSimdScalar& v1, const btSimdScalar& v2) +SIMD_FORCE_INLINE btSimdScalar +operator*(const btSimdScalar& v1, const btSimdScalar& v2) { - return btSimdScalar(_mm_mul_ps(v1.get128(),v2.get128())); + return btSimdScalar(_mm_mul_ps(v1.get128(), v2.get128())); } ///@brief Return the elementwise product of two btSimdScalar -SIMD_FORCE_INLINE btSimdScalar -operator+(const btSimdScalar& v1, const btSimdScalar& v2) +SIMD_FORCE_INLINE btSimdScalar +operator+(const btSimdScalar& v1, const btSimdScalar& v2) { - return btSimdScalar(_mm_add_ps(v1.get128(),v2.get128())); + return btSimdScalar(_mm_add_ps(v1.get128(), v2.get128())); } - #else #define btSimdScalar btScalar #endif ///The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance. -ATTRIBUTE_ALIGNED16 (struct) btSolverBody +ATTRIBUTE_ALIGNED16(struct) +btSolverBody { BT_DECLARE_ALIGNED_ALLOCATOR(); - btTransform m_worldTransform; - btVector3 m_deltaLinearVelocity; - btVector3 m_deltaAngularVelocity; - btVector3 m_angularFactor; - btVector3 m_linearFactor; - btVector3 m_invMass; - btVector3 m_pushVelocity; - btVector3 m_turnVelocity; - btVector3 m_linearVelocity; - btVector3 m_angularVelocity; - btVector3 m_externalForceImpulse; - btVector3 m_externalTorqueImpulse; - - btRigidBody* m_originalBody; - void setWorldTransform(const btTransform& worldTransform) + btTransform m_worldTransform; + btVector3 m_deltaLinearVelocity; + btVector3 m_deltaAngularVelocity; + btVector3 m_angularFactor; + btVector3 m_linearFactor; + btVector3 m_invMass; + btVector3 m_pushVelocity; + btVector3 m_turnVelocity; + btVector3 m_linearVelocity; + btVector3 m_angularVelocity; + btVector3 m_externalForceImpulse; + btVector3 m_externalTorqueImpulse; + + btRigidBody* m_originalBody; + void setWorldTransform(const btTransform& worldTransform) { m_worldTransform = worldTransform; } @@ -131,56 +127,50 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody { return m_worldTransform; } - - - SIMD_FORCE_INLINE void getVelocityInLocalPointNoDelta(const btVector3& rel_pos, btVector3& velocity ) const + SIMD_FORCE_INLINE void getVelocityInLocalPointNoDelta(const btVector3& rel_pos, btVector3& velocity) const { if (m_originalBody) - velocity = m_linearVelocity + m_externalForceImpulse + (m_angularVelocity+m_externalTorqueImpulse).cross(rel_pos); + velocity = m_linearVelocity + m_externalForceImpulse + (m_angularVelocity + m_externalTorqueImpulse).cross(rel_pos); else - velocity.setValue(0,0,0); + velocity.setValue(0, 0, 0); } - - SIMD_FORCE_INLINE void getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const + SIMD_FORCE_INLINE void getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity) const { if (m_originalBody) - velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos); + velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos); else - velocity.setValue(0,0,0); + velocity.setValue(0, 0, 0); } - SIMD_FORCE_INLINE void getAngularVelocity(btVector3& angVel) const + SIMD_FORCE_INLINE void getAngularVelocity(btVector3 & angVel) const { if (m_originalBody) - angVel =m_angularVelocity+m_deltaAngularVelocity; + angVel = m_angularVelocity + m_deltaAngularVelocity; else - angVel.setValue(0,0,0); + angVel.setValue(0, 0, 0); } - //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position - SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude) + SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent, const btScalar impulseMagnitude) { if (m_originalBody) { - m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor; - m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor); + m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor; + m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor); } } - SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent, btScalar impulseMagnitude) { if (m_originalBody) { - m_pushVelocity += linearComponent*impulseMagnitude*m_linearFactor; - m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor); + m_pushVelocity += linearComponent * impulseMagnitude * m_linearFactor; + m_turnVelocity += angularComponent * (impulseMagnitude * m_angularFactor); } } - - const btVector3& getDeltaLinearVelocity() const { return m_deltaLinearVelocity; @@ -191,20 +181,19 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody return m_deltaAngularVelocity; } - const btVector3& getPushVelocity() const + const btVector3& getPushVelocity() const { return m_pushVelocity; } - const btVector3& getTurnVelocity() const + const btVector3& getTurnVelocity() const { return m_turnVelocity; } - //////////////////////////////////////////////// ///some internal methods, don't use them - + btVector3& internalGetDeltaLinearVelocity() { return m_deltaLinearVelocity; @@ -229,7 +218,7 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody { m_invMass = invMass; } - + btVector3& internalGetPushVelocity() { return m_pushVelocity; @@ -240,67 +229,57 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody return m_turnVelocity; } - SIMD_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const + SIMD_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity) const { - velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos); + velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos); } - SIMD_FORCE_INLINE void internalGetAngularVelocity(btVector3& angVel) const + SIMD_FORCE_INLINE void internalGetAngularVelocity(btVector3 & angVel) const { - angVel = m_angularVelocity+m_deltaAngularVelocity; + angVel = m_angularVelocity + m_deltaAngularVelocity; } - //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position - SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude) + SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent, const btScalar impulseMagnitude) { if (m_originalBody) { - m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor; - m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor); + m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor; + m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor); } } - - - - void writebackVelocity() + void writebackVelocity() { if (m_originalBody) { - m_linearVelocity +=m_deltaLinearVelocity; + m_linearVelocity += m_deltaLinearVelocity; m_angularVelocity += m_deltaAngularVelocity; - + //m_originalBody->setCompanionId(-1); } } - - void writebackVelocityAndTransform(btScalar timeStep, btScalar splitImpulseTurnErp) + void writebackVelocityAndTransform(btScalar timeStep, btScalar splitImpulseTurnErp) { - (void) timeStep; + (void)timeStep; if (m_originalBody) { m_linearVelocity += m_deltaLinearVelocity; m_angularVelocity += m_deltaAngularVelocity; - + //correct the position/orientation based on push/turn recovery btTransform newTransform; - if (m_pushVelocity[0]!=0.f || m_pushVelocity[1]!=0 || m_pushVelocity[2]!=0 || m_turnVelocity[0]!=0.f || m_turnVelocity[1]!=0 || m_turnVelocity[2]!=0) + if (m_pushVelocity[0] != 0.f || m_pushVelocity[1] != 0 || m_pushVelocity[2] != 0 || m_turnVelocity[0] != 0.f || m_turnVelocity[1] != 0 || m_turnVelocity[2] != 0) { - // btQuaternion orn = m_worldTransform.getRotation(); - btTransformUtil::integrateTransform(m_worldTransform,m_pushVelocity,m_turnVelocity*splitImpulseTurnErp,timeStep,newTransform); + // btQuaternion orn = m_worldTransform.getRotation(); + btTransformUtil::integrateTransform(m_worldTransform, m_pushVelocity, m_turnVelocity * splitImpulseTurnErp, timeStep, newTransform); m_worldTransform = newTransform; } //m_worldTransform.setRotation(orn); //m_originalBody->setCompanionId(-1); } } - - - }; -#endif //BT_SOLVER_BODY_H - - +#endif //BT_SOLVER_BODY_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h index 5515e6b311..c7938df867 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef BT_SOLVER_CONSTRAINT_H #define BT_SOLVER_CONSTRAINT_H -class btRigidBody; +class btRigidBody; #include "LinearMath/btVector3.h" #include "LinearMath/btMatrix3x3.h" #include "btJacobianEntry.h" @@ -25,56 +25,50 @@ class btRigidBody; //#define NO_FRICTION_TANGENTIALS 1 #include "btSolverBody.h" - ///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints. -ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint +ATTRIBUTE_ALIGNED16(struct) +btSolverConstraint { BT_DECLARE_ALIGNED_ALLOCATOR(); - btVector3 m_relpos1CrossNormal; - btVector3 m_contactNormal1; - - btVector3 m_relpos2CrossNormal; - btVector3 m_contactNormal2; //usually m_contactNormal2 == -m_contactNormal1, but not always - - btVector3 m_angularComponentA; - btVector3 m_angularComponentB; - - mutable btSimdScalar m_appliedPushImpulse; - mutable btSimdScalar m_appliedImpulse; - - btScalar m_friction; - btScalar m_jacDiagABInv; - btScalar m_rhs; - btScalar m_cfm; - - btScalar m_lowerLimit; - btScalar m_upperLimit; - btScalar m_rhsPenetration; - union - { - void* m_originalContactPoint; - btScalar m_unusedPadding4; - int m_numRowsForNonContactConstraint; + btVector3 m_relpos1CrossNormal; + btVector3 m_contactNormal1; + + btVector3 m_relpos2CrossNormal; + btVector3 m_contactNormal2; //usually m_contactNormal2 == -m_contactNormal1, but not always + + btVector3 m_angularComponentA; + btVector3 m_angularComponentB; + + mutable btSimdScalar m_appliedPushImpulse; + mutable btSimdScalar m_appliedImpulse; + + btScalar m_friction; + btScalar m_jacDiagABInv; + btScalar m_rhs; + btScalar m_cfm; + + btScalar m_lowerLimit; + btScalar m_upperLimit; + btScalar m_rhsPenetration; + union { + void* m_originalContactPoint; + btScalar m_unusedPadding4; + int m_numRowsForNonContactConstraint; }; - int m_overrideNumSolverIterations; - int m_frictionIndex; + int m_overrideNumSolverIterations; + int m_frictionIndex; int m_solverBodyIdA; int m_solverBodyIdB; - - enum btSolverConstraintType + enum btSolverConstraintType { BT_SOLVER_CONTACT_1D = 0, BT_SOLVER_FRICTION_1D }; }; -typedef btAlignedObjectArray<btSolverConstraint> btConstraintArray; - - -#endif //BT_SOLVER_CONSTRAINT_H - - +typedef btAlignedObjectArray<btSolverConstraint> btConstraintArray; +#endif //BT_SOLVER_CONSTRAINT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp index 9f04f28053..ebe679c449 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp @@ -13,69 +13,63 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ - #include "btTypedConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btSerializer.h" - #define DEFAULT_DEBUGDRAW_SIZE btScalar(0.05f) btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA) -:btTypedObject(type), -m_userConstraintType(-1), -m_userConstraintPtr((void*)-1), -m_breakingImpulseThreshold(SIMD_INFINITY), -m_isEnabled(true), -m_needsFeedback(false), -m_overrideNumSolverIterations(-1), -m_rbA(rbA), -m_rbB(getFixedBody()), -m_appliedImpulse(btScalar(0.)), -m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE), -m_jointFeedback(0) + : btTypedObject(type), + m_userConstraintType(-1), + m_userConstraintPtr((void*)-1), + m_breakingImpulseThreshold(SIMD_INFINITY), + m_isEnabled(true), + m_needsFeedback(false), + m_overrideNumSolverIterations(-1), + m_rbA(rbA), + m_rbB(getFixedBody()), + m_appliedImpulse(btScalar(0.)), + m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE), + m_jointFeedback(0) { } - -btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB) -:btTypedObject(type), -m_userConstraintType(-1), -m_userConstraintPtr((void*)-1), -m_breakingImpulseThreshold(SIMD_INFINITY), -m_isEnabled(true), -m_needsFeedback(false), -m_overrideNumSolverIterations(-1), -m_rbA(rbA), -m_rbB(rbB), -m_appliedImpulse(btScalar(0.)), -m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE), -m_jointFeedback(0) +btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA, btRigidBody& rbB) + : btTypedObject(type), + m_userConstraintType(-1), + m_userConstraintPtr((void*)-1), + m_breakingImpulseThreshold(SIMD_INFINITY), + m_isEnabled(true), + m_needsFeedback(false), + m_overrideNumSolverIterations(-1), + m_rbA(rbA), + m_rbB(rbB), + m_appliedImpulse(btScalar(0.)), + m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE), + m_jointFeedback(0) { } - - - btScalar btTypedConstraint::getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact) { - if(lowLim > uppLim) + if (lowLim > uppLim) { return btScalar(1.0f); } - else if(lowLim == uppLim) + else if (lowLim == uppLim) { return btScalar(0.0f); } btScalar lim_fact = btScalar(1.0f); btScalar delta_max = vel / timeFact; - if(delta_max < btScalar(0.0f)) + if (delta_max < btScalar(0.0f)) { - if((pos >= lowLim) && (pos < (lowLim - delta_max))) + if ((pos >= lowLim) && (pos < (lowLim - delta_max))) { lim_fact = (lowLim - pos) / delta_max; } - else if(pos < lowLim) + else if (pos < lowLim) { lim_fact = btScalar(0.0f); } @@ -84,13 +78,13 @@ btScalar btTypedConstraint::getMotorFactor(btScalar pos, btScalar lowLim, btScal lim_fact = btScalar(1.0f); } } - else if(delta_max > btScalar(0.0f)) + else if (delta_max > btScalar(0.0f)) { - if((pos <= uppLim) && (pos > (uppLim - delta_max))) + if ((pos <= uppLim) && (pos > (uppLim - delta_max))) { lim_fact = (uppLim - pos) / delta_max; } - else if(pos > uppLim) + else if (pos > uppLim) { lim_fact = btScalar(0.0f); } @@ -101,19 +95,19 @@ btScalar btTypedConstraint::getMotorFactor(btScalar pos, btScalar lowLim, btScal } else { - lim_fact = btScalar(0.0f); + lim_fact = btScalar(0.0f); } return lim_fact; } ///fills the dataBuffer and returns the struct name (and 0 on failure) -const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* serializer) const +const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* serializer) const { - btTypedConstraintData2* tcd = (btTypedConstraintData2*) dataBuffer; + btTypedConstraintData2* tcd = (btTypedConstraintData2*)dataBuffer; tcd->m_rbA = (btRigidBodyData*)serializer->getUniquePointer(&m_rbA); tcd->m_rbB = (btRigidBodyData*)serializer->getUniquePointer(&m_rbB); - char* name = (char*) serializer->findNameForPointer(this); + char* name = (char*)serializer->findNameForPointer(this); tcd->m_name = (char*)serializer->getUniquePointer(name); if (tcd->m_name) { @@ -124,10 +118,10 @@ const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* seriali tcd->m_needsFeedback = m_needsFeedback; tcd->m_overrideNumSolverIterations = m_overrideNumSolverIterations; tcd->m_breakingImpulseThreshold = m_breakingImpulseThreshold; - tcd->m_isEnabled = m_isEnabled? 1: 0; - - tcd->m_userConstraintId =m_userConstraintId; - tcd->m_userConstraintType =m_userConstraintType; + tcd->m_isEnabled = m_isEnabled ? 1 : 0; + + tcd->m_userConstraintId = m_userConstraintId; + tcd->m_userConstraintType = m_userConstraintType; tcd->m_appliedImpulse = m_appliedImpulse; tcd->m_dbgDrawSize = m_dbgDrawSize; @@ -135,10 +129,10 @@ const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* seriali tcd->m_disableCollisionsBetweenLinkedBodies = false; int i; - for (i=0;i<m_rbA.getNumConstraintRefs();i++) + for (i = 0; i < m_rbA.getNumConstraintRefs(); i++) if (m_rbA.getConstraintRef(i) == this) tcd->m_disableCollisionsBetweenLinkedBodies = true; - for (i=0;i<m_rbB.getNumConstraintRefs();i++) + for (i = 0; i < m_rbB.getNumConstraintRefs(); i++) if (m_rbB.getConstraintRef(i) == this) tcd->m_disableCollisionsBetweenLinkedBodies = true; @@ -147,17 +141,16 @@ const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* seriali btRigidBody& btTypedConstraint::getFixedBody() { - static btRigidBody s_fixed(0, 0,0); - s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); + static btRigidBody s_fixed(0, 0, 0); + s_fixed.setMassProps(btScalar(0.), btVector3(btScalar(0.), btScalar(0.), btScalar(0.))); return s_fixed; } - void btAngularLimit::set(btScalar low, btScalar high, btScalar _softness, btScalar _biasFactor, btScalar _relaxationFactor) { m_halfRange = (high - low) / 2.0f; m_center = btNormalizeAngle(low + m_halfRange); - m_softness = _softness; + m_softness = _softness; m_biasFactor = _biasFactor; m_relaxationFactor = _relaxationFactor; } @@ -174,7 +167,7 @@ void btAngularLimit::test(const btScalar angle) if (deviation < -m_halfRange) { m_solveLimit = true; - m_correction = - (deviation + m_halfRange); + m_correction = -(deviation + m_halfRange); m_sign = +1.0f; } else if (deviation > m_halfRange) @@ -186,7 +179,6 @@ void btAngularLimit::test(const btScalar angle) } } - btScalar btAngularLimit::getError() const { return m_correction * m_sign; diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h index 8a2a2d1ae7..d30f3dee5c 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h @@ -16,26 +16,24 @@ subject to the following restrictions: #ifndef BT_TYPED_CONSTRAINT_H #define BT_TYPED_CONSTRAINT_H - #include "LinearMath/btScalar.h" #include "btSolverConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #ifdef BT_USE_DOUBLE_PRECISION -#define btTypedConstraintData2 btTypedConstraintDoubleData -#define btTypedConstraintDataName "btTypedConstraintDoubleData" +#define btTypedConstraintData2 btTypedConstraintDoubleData +#define btTypedConstraintDataName "btTypedConstraintDoubleData" #else -#define btTypedConstraintData2 btTypedConstraintFloatData -#define btTypedConstraintDataName "btTypedConstraintFloatData" -#endif //BT_USE_DOUBLE_PRECISION - +#define btTypedConstraintData2 btTypedConstraintFloatData +#define btTypedConstraintDataName "btTypedConstraintFloatData" +#endif //BT_USE_DOUBLE_PRECISION class btSerializer; //Don't change any of the existing enum values, so add enum types at the end for serialization compatibility enum btTypedConstraintType { - POINT2POINT_CONSTRAINT_TYPE=3, + POINT2POINT_CONSTRAINT_TYPE = 3, HINGE_CONSTRAINT_TYPE, CONETWIST_CONSTRAINT_TYPE, D6_CONSTRAINT_TYPE, @@ -48,91 +46,88 @@ enum btTypedConstraintType MAX_CONSTRAINT_TYPE }; - enum btConstraintParams { - BT_CONSTRAINT_ERP=1, + BT_CONSTRAINT_ERP = 1, BT_CONSTRAINT_STOP_ERP, BT_CONSTRAINT_CFM, BT_CONSTRAINT_STOP_CFM }; #if 1 - #define btAssertConstrParams(_par) btAssert(_par) +#define btAssertConstrParams(_par) btAssert(_par) #else - #define btAssertConstrParams(_par) +#define btAssertConstrParams(_par) #endif - -ATTRIBUTE_ALIGNED16(struct) btJointFeedback +ATTRIBUTE_ALIGNED16(struct) +btJointFeedback { BT_DECLARE_ALIGNED_ALLOCATOR(); - btVector3 m_appliedForceBodyA; - btVector3 m_appliedTorqueBodyA; - btVector3 m_appliedForceBodyB; - btVector3 m_appliedTorqueBodyB; + btVector3 m_appliedForceBodyA; + btVector3 m_appliedTorqueBodyA; + btVector3 m_appliedForceBodyB; + btVector3 m_appliedTorqueBodyB; }; - ///TypedConstraint is the baseclass for Bullet constraints and vehicles -ATTRIBUTE_ALIGNED16(class) btTypedConstraint : public btTypedObject +ATTRIBUTE_ALIGNED16(class) +btTypedConstraint : public btTypedObject { - int m_userConstraintType; + int m_userConstraintType; - union - { - int m_userConstraintId; + union { + int m_userConstraintId; void* m_userConstraintPtr; }; - btScalar m_breakingImpulseThreshold; - bool m_isEnabled; - bool m_needsFeedback; - int m_overrideNumSolverIterations; + btScalar m_breakingImpulseThreshold; + bool m_isEnabled; + bool m_needsFeedback; + int m_overrideNumSolverIterations; - - btTypedConstraint& operator=(btTypedConstraint& other) + btTypedConstraint& operator=(btTypedConstraint& other) { btAssert(0); - (void) other; + (void)other; return *this; } protected: - btRigidBody& m_rbA; - btRigidBody& m_rbB; - btScalar m_appliedImpulse; - btScalar m_dbgDrawSize; - btJointFeedback* m_jointFeedback; + btRigidBody& m_rbA; + btRigidBody& m_rbB; + btScalar m_appliedImpulse; + btScalar m_dbgDrawSize; + btJointFeedback* m_jointFeedback; ///internal method used by the constraint solver, don't use them directly btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact); - public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - virtual ~btTypedConstraint() {}; - btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA); - btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB); + virtual ~btTypedConstraint(){}; + btTypedConstraint(btTypedConstraintType type, btRigidBody & rbA); + btTypedConstraint(btTypedConstraintType type, btRigidBody & rbA, btRigidBody & rbB); - struct btConstraintInfo1 { - int m_numConstraintRows,nub; + struct btConstraintInfo1 + { + int m_numConstraintRows, nub; }; static btRigidBody& getFixedBody(); - struct btConstraintInfo2 { + struct btConstraintInfo2 + { // integrator parameters: frames per second (1/stepsize), default error // reduction parameter (0..1). - btScalar fps,erp; + btScalar fps, erp; // for the first and second body, pointers to two (linear and angular) // n*3 jacobian sub matrices, stored by rows. these matrices will have // been initialized to 0 on entry. if the second body is zero then the // J2xx pointers may be 0. - btScalar *m_J1linearAxis,*m_J1angularAxis,*m_J2linearAxis,*m_J2angularAxis; + btScalar *m_J1linearAxis, *m_J1angularAxis, *m_J2linearAxis, *m_J2angularAxis; // elements to jump from one row to the next in J's int rowskip; @@ -140,19 +135,19 @@ public: // right hand sides of the equation J*v = c + cfm * lambda. cfm is the // "constraint force mixing" vector. c is set to zero on entry, cfm is // set to a constant value (typically very small or zero) value on entry. - btScalar *m_constraintError,*cfm; + btScalar *m_constraintError, *cfm; // lo and hi limits for variables (set to -/+ infinity on entry). - btScalar *m_lowerLimit,*m_upperLimit; + btScalar *m_lowerLimit, *m_upperLimit; // number of solver iterations int m_numIterations; //damping of the velocity - btScalar m_damping; + btScalar m_damping; }; - int getOverrideNumSolverIterations() const + int getOverrideNumSolverIterations() const { return m_overrideNumSolverIterations; } @@ -165,60 +160,57 @@ public: } ///internal method used by the constraint solver, don't use them directly - virtual void buildJacobian() {}; + virtual void buildJacobian(){}; ///internal method used by the constraint solver, don't use them directly - virtual void setupSolverConstraint(btConstraintArray& ca, int solverBodyA,int solverBodyB, btScalar timeStep) + virtual void setupSolverConstraint(btConstraintArray & ca, int solverBodyA, int solverBodyB, btScalar timeStep) { - (void)ca; - (void)solverBodyA; - (void)solverBodyB; - (void)timeStep; + (void)ca; + (void)solverBodyA; + (void)solverBodyB; + (void)timeStep; } - + ///internal method used by the constraint solver, don't use them directly - virtual void getInfo1 (btConstraintInfo1* info)=0; + virtual void getInfo1(btConstraintInfo1 * info) = 0; ///internal method used by the constraint solver, don't use them directly - virtual void getInfo2 (btConstraintInfo2* info)=0; + virtual void getInfo2(btConstraintInfo2 * info) = 0; ///internal method used by the constraint solver, don't use them directly - void internalSetAppliedImpulse(btScalar appliedImpulse) + void internalSetAppliedImpulse(btScalar appliedImpulse) { m_appliedImpulse = appliedImpulse; } ///internal method used by the constraint solver, don't use them directly - btScalar internalGetAppliedImpulse() + btScalar internalGetAppliedImpulse() { return m_appliedImpulse; } - - btScalar getBreakingImpulseThreshold() const + btScalar getBreakingImpulseThreshold() const { - return m_breakingImpulseThreshold; + return m_breakingImpulseThreshold; } - void setBreakingImpulseThreshold(btScalar threshold) + void setBreakingImpulseThreshold(btScalar threshold) { m_breakingImpulseThreshold = threshold; } - bool isEnabled() const + bool isEnabled() const { return m_isEnabled; } - void setEnabled(bool enabled) + void setEnabled(bool enabled) { - m_isEnabled=enabled; + m_isEnabled = enabled; } - ///internal method used by the constraint solver, don't use them directly - virtual void solveConstraintObsolete(btSolverBody& /*bodyA*/,btSolverBody& /*bodyB*/,btScalar /*timeStep*/) {}; + virtual void solveConstraintObsolete(btSolverBody& /*bodyA*/, btSolverBody& /*bodyB*/, btScalar /*timeStep*/){}; - const btRigidBody& getRigidBodyA() const { return m_rbA; @@ -228,7 +220,7 @@ public: return m_rbB; } - btRigidBody& getRigidBodyA() + btRigidBody& getRigidBodyA() { return m_rbA; } @@ -239,15 +231,15 @@ public: int getUserConstraintType() const { - return m_userConstraintType ; + return m_userConstraintType; } - void setUserConstraintType(int userConstraintType) + void setUserConstraintType(int userConstraintType) { m_userConstraintType = userConstraintType; }; - void setUserConstraintId(int uid) + void setUserConstraintId(int uid) { m_userConstraintId = uid; } @@ -257,17 +249,17 @@ public: return m_userConstraintId; } - void setUserConstraintPtr(void* ptr) + void setUserConstraintPtr(void* ptr) { m_userConstraintPtr = ptr; } - void* getUserConstraintPtr() + void* getUserConstraintPtr() { return m_userConstraintPtr; } - void setJointFeedback(btJointFeedback* jointFeedback) + void setJointFeedback(btJointFeedback * jointFeedback) { m_jointFeedback = jointFeedback; } @@ -282,37 +274,36 @@ public: return m_jointFeedback; } - int getUid() const { - return m_userConstraintId; - } + return m_userConstraintId; + } - bool needsFeedback() const + bool needsFeedback() const { return m_needsFeedback; } ///enableFeedback will allow to read the applied linear and angular impulse ///use getAppliedImpulse, getAppliedLinearImpulse and getAppliedAngularImpulse to read feedback information - void enableFeedback(bool needsFeedback) + void enableFeedback(bool needsFeedback) { m_needsFeedback = needsFeedback; } - ///getAppliedImpulse is an estimated total applied impulse. + ///getAppliedImpulse is an estimated total applied impulse. ///This feedback could be used to determine breaking constraints or playing sounds. - btScalar getAppliedImpulse() const + btScalar getAppliedImpulse() const { btAssert(m_needsFeedback); return m_appliedImpulse; } - btTypedConstraintType getConstraintType () const + btTypedConstraintType getConstraintType() const { return btTypedConstraintType(m_objectType); } - + void setDbgDrawSize(btScalar dbgDrawSize) { m_dbgDrawSize = dbgDrawSize; @@ -322,35 +313,34 @@ public: return m_dbgDrawSize; } - ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). + ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). ///If no axis is provided, it uses the default axis for this constraint. - virtual void setParam(int num, btScalar value, int axis = -1) = 0; + virtual void setParam(int num, btScalar value, int axis = -1) = 0; ///return the local value of parameter - virtual btScalar getParam(int num, int axis = -1) const = 0; - - virtual int calculateSerializeBufferSize() const; + virtual btScalar getParam(int num, int axis = -1) const = 0; - ///fills the dataBuffer and returns the struct name (and 0 on failure) - virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; + virtual int calculateSerializeBufferSize() const; + ///fills the dataBuffer and returns the struct name (and 0 on failure) + virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; }; -// returns angle in range [-SIMD_2_PI, SIMD_2_PI], closest to one of the limits +// returns angle in range [-SIMD_2_PI, SIMD_2_PI], closest to one of the limits // all arguments should be normalized angles (i.e. in range [-SIMD_PI, SIMD_PI]) SIMD_FORCE_INLINE btScalar btAdjustAngleToLimits(btScalar angleInRadians, btScalar angleLowerLimitInRadians, btScalar angleUpperLimitInRadians) { - if(angleLowerLimitInRadians >= angleUpperLimitInRadians) + if (angleLowerLimitInRadians >= angleUpperLimitInRadians) { return angleInRadians; } - else if(angleInRadians < angleLowerLimitInRadians) + else if (angleInRadians < angleLowerLimitInRadians) { btScalar diffLo = btFabs(btNormalizeAngle(angleLowerLimitInRadians - angleInRadians)); btScalar diffHi = btFabs(btNormalizeAngle(angleUpperLimitInRadians - angleInRadians)); return (diffLo < diffHi) ? angleInRadians : (angleInRadians + SIMD_2_PI); } - else if(angleInRadians > angleUpperLimitInRadians) + else if (angleInRadians > angleUpperLimitInRadians) { btScalar diffHi = btFabs(btNormalizeAngle(angleInRadians - angleUpperLimitInRadians)); btScalar diffLo = btFabs(btNormalizeAngle(angleInRadians - angleLowerLimitInRadians)); @@ -362,6 +352,8 @@ SIMD_FORCE_INLINE btScalar btAdjustAngleToLimits(btScalar angleInRadians, btScal } } +// clang-format off + ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 struct btTypedConstraintFloatData { @@ -385,6 +377,8 @@ struct btTypedConstraintFloatData }; + + ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 #define BT_BACKWARDS_COMPATIBLE_SERIALIZATION @@ -436,18 +430,17 @@ struct btTypedConstraintDoubleData }; +// clang-format on -SIMD_FORCE_INLINE int btTypedConstraint::calculateSerializeBufferSize() const +SIMD_FORCE_INLINE int btTypedConstraint::calculateSerializeBufferSize() const { return sizeof(btTypedConstraintData2); } - - class btAngularLimit { private: - btScalar + btScalar m_center, m_halfRange, m_softness, @@ -462,15 +455,16 @@ private: public: /// Default constructor initializes limit as inactive, allowing free constraint movement btAngularLimit() - :m_center(0.0f), - m_halfRange(-1.0f), - m_softness(0.9f), - m_biasFactor(0.3f), - m_relaxationFactor(1.0f), - m_correction(0.0f), - m_sign(0.0f), - m_solveLimit(false) - {} + : m_center(0.0f), + m_halfRange(-1.0f), + m_softness(0.9f), + m_biasFactor(0.3f), + m_relaxationFactor(1.0f), + m_correction(0.0f), + m_sign(0.0f), + m_solveLimit(false) + { + } /// Sets all limit's parameters. /// When low > high limit becomes inactive. @@ -499,13 +493,13 @@ public: return m_relaxationFactor; } - /// Returns correction value evaluated when test() was invoked + /// Returns correction value evaluated when test() was invoked inline btScalar getCorrection() const { return m_correction; } - /// Returns sign value evaluated when test() was invoked + /// Returns sign value evaluated when test() was invoked inline btScalar getSign() const { return m_sign; @@ -533,9 +527,6 @@ public: btScalar getLow() const; btScalar getHigh() const; - }; - - -#endif //BT_TYPED_CONSTRAINT_H +#endif //BT_TYPED_CONSTRAINT_H diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp index b009f41aec..42ed1fbb87 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp @@ -13,43 +13,38 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ - - #include "btUniversalConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" - - #define UNIV_EPS btScalar(0.01f) - // constructor // anchor, axis1 and axis2 are in world coordinate system // axis1 must be orthogonal to axis2 btUniversalConstraint::btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2) -: btGeneric6DofConstraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), true), - m_anchor(anchor), - m_axis1(axis1), - m_axis2(axis2) + : btGeneric6DofConstraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), true), + m_anchor(anchor), + m_axis1(axis1), + m_axis2(axis2) { // build frame basis // 6DOF constraint uses Euler angles and to define limits // it is assumed that rotational order is : // Z - first, allowed limits are (-PI,PI); - // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number + // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number // used to prevent constraint from instability on poles; // new position of X, allowed limits are (-PI,PI); // So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs // Build the frame in world coordinate system first btVector3 zAxis = m_axis1.normalize(); btVector3 yAxis = m_axis2.normalize(); - btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system + btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system btTransform frameInW; frameInW.setIdentity(); - frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], - xAxis[1], yAxis[1], zAxis[1], - xAxis[2], yAxis[2], zAxis[2]); + frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); frameInW.setOrigin(anchor); // now get constraint frame in local coordinate systems m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW; @@ -58,30 +53,28 @@ btUniversalConstraint::btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, setLinearLowerLimit(btVector3(0., 0., 0.)); setLinearUpperLimit(btVector3(0., 0., 0.)); setAngularLowerLimit(btVector3(0.f, -SIMD_HALF_PI + UNIV_EPS, -SIMD_PI + UNIV_EPS)); - setAngularUpperLimit(btVector3(0.f, SIMD_HALF_PI - UNIV_EPS, SIMD_PI - UNIV_EPS)); + setAngularUpperLimit(btVector3(0.f, SIMD_HALF_PI - UNIV_EPS, SIMD_PI - UNIV_EPS)); } -void btUniversalConstraint::setAxis(const btVector3& axis1,const btVector3& axis2) +void btUniversalConstraint::setAxis(const btVector3& axis1, const btVector3& axis2) { - m_axis1 = axis1; - m_axis2 = axis2; + m_axis1 = axis1; + m_axis2 = axis2; btVector3 zAxis = axis1.normalized(); btVector3 yAxis = axis2.normalized(); - btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system + btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system btTransform frameInW; frameInW.setIdentity(); - frameInW.getBasis().setValue( xAxis[0], yAxis[0], zAxis[0], - xAxis[1], yAxis[1], zAxis[1], - xAxis[2], yAxis[2], zAxis[2]); + frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0], + xAxis[1], yAxis[1], zAxis[1], + xAxis[2], yAxis[2], zAxis[2]); frameInW.setOrigin(m_anchor); // now get constraint frame in local coordinate systems m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW; m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW; - calculateTransforms(); + calculateTransforms(); } - - diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h index 9e70841043..8c24d93a64 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h @@ -16,35 +16,32 @@ subject to the following restrictions: #ifndef BT_UNIVERSAL_CONSTRAINT_H #define BT_UNIVERSAL_CONSTRAINT_H - - #include "LinearMath/btVector3.h" #include "btTypedConstraint.h" #include "btGeneric6DofConstraint.h" - - /// Constraint similar to ODE Universal Joint /// has 2 rotatioonal degrees of freedom, similar to Euler rotations around Z (axis 1) /// and Y (axis 2) -/// Description from ODE manual : -/// "Given axis 1 on body 1, and axis 2 on body 2 that is perpendicular to axis 1, it keeps them perpendicular. +/// Description from ODE manual : +/// "Given axis 1 on body 1, and axis 2 on body 2 that is perpendicular to axis 1, it keeps them perpendicular. /// In other words, rotation of the two bodies about the direction perpendicular to the two axes will be equal." -ATTRIBUTE_ALIGNED16(class) btUniversalConstraint : public btGeneric6DofConstraint +ATTRIBUTE_ALIGNED16(class) +btUniversalConstraint : public btGeneric6DofConstraint { protected: - btVector3 m_anchor; - btVector3 m_axis1; - btVector3 m_axis2; + btVector3 m_anchor; + btVector3 m_axis1; + btVector3 m_axis2; + public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - + // constructor // anchor, axis1 and axis2 are in world coordinate system // axis1 must be orthogonal to axis2 - btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2); + btUniversalConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2); // access const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); } const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); } @@ -56,10 +53,7 @@ public: void setUpperLimit(btScalar ang1max, btScalar ang2max) { setAngularUpperLimit(btVector3(0.f, ang1max, ang2max)); } void setLowerLimit(btScalar ang1min, btScalar ang2min) { setAngularLowerLimit(btVector3(0.f, ang1min, ang2min)); } - void setAxis( const btVector3& axis1, const btVector3& axis2); + void setAxis(const btVector3& axis1, const btVector3& axis2); }; - - -#endif // BT_UNIVERSAL_CONSTRAINT_H - +#endif // BT_UNIVERSAL_CONSTRAINT_H |