#ifndef B3_PGS_JACOBI_SOLVER #define B3_PGS_JACOBI_SOLVER struct b3Contact4; struct b3ContactPoint; class b3Dispatcher; #include "b3TypedConstraint.h" #include "b3ContactSolverInfo.h" #include "b3SolverBody.h" #include "b3SolverConstraint.h" struct b3RigidBodyData; struct b3InertiaData; class b3PgsJacobiSolver { protected: b3AlignedObjectArray m_tmpSolverBodyPool; b3ConstraintArray m_tmpSolverContactConstraintPool; b3ConstraintArray m_tmpSolverNonContactConstraintPool; b3ConstraintArray m_tmpSolverContactFrictionConstraintPool; b3ConstraintArray m_tmpSolverContactRollingFrictionConstraintPool; b3AlignedObjectArray m_orderTmpConstraintPool; b3AlignedObjectArray m_orderNonContactConstraintPool; b3AlignedObjectArray m_orderFrictionConstraintPool; b3AlignedObjectArray m_tmpConstraintSizesPool; b3AlignedObjectArray m_bodyCount; b3AlignedObjectArray m_bodyCountCheck; b3AlignedObjectArray m_deltaLinearVelocities; b3AlignedObjectArray m_deltaAngularVelocities; bool m_usePgs; void averageVelocities(); int m_maxOverrideNumSolverIterations; int m_numSplitImpulseRecoveries; b3Scalar getContactProcessingThreshold(b3Contact4* contact) { return 0.02f; } void setupFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity = 0., b3Scalar cfmSlip = 0.); void setupRollingFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity = 0., b3Scalar cfmSlip = 0.); b3SolverConstraint& addFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity = 0., b3Scalar cfmSlip = 0.); b3SolverConstraint& addRollingFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity = 0, b3Scalar cfmSlip = 0.f); void setupContactConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal, b3Vector3& vel, b3Scalar& rel_vel, b3Scalar& relaxation, b3Vector3& rel_pos1, b3Vector3& rel_pos2); void setFrictionConstraintImpulse(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal); ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction unsigned long m_btSeed2; b3Scalar restitutionCurve(b3Scalar rel_vel, b3Scalar restitution); void convertContact(b3RigidBodyData* bodies, b3InertiaData* inertias, b3Contact4* manifold, const b3ContactSolverInfo& infoGlobal); void resolveSplitPenetrationSIMD( b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint); void resolveSplitPenetrationImpulseCacheFriendly( b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint); //internal method int getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies, b3InertiaData* inertias); void initSolverBody(int bodyIndex, b3SolverBody* solverBody, b3RigidBodyData* collisionObject); void resolveSingleConstraintRowGeneric(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint); void resolveSingleConstraintRowGenericSIMD(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint); void resolveSingleConstraintRowLowerLimit(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint); void resolveSingleConstraintRowLowerLimitSIMD(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint); protected: virtual b3Scalar solveGroupCacheFriendlySetup(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal); virtual b3Scalar solveGroupCacheFriendlyIterations(b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal); virtual void solveGroupCacheFriendlySplitImpulseIterations(b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal); b3Scalar solveSingleIteration(int iteration, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal); virtual b3Scalar solveGroupCacheFriendlyFinish(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, const b3ContactSolverInfo& infoGlobal); public: B3_DECLARE_ALIGNED_ALLOCATOR(); b3PgsJacobiSolver(bool usePgs); virtual ~b3PgsJacobiSolver(); // void solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts); void solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts, int numConstraints, b3TypedConstraint** constraints); b3Scalar solveGroup(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal); ///clear internal cached data and reset random seed virtual void reset(); unsigned long b3Rand2(); int b3RandInt2(int n); void setRandSeed(unsigned long seed) { m_btSeed2 = seed; } unsigned long getRandSeed() const { return m_btSeed2; } }; #endif //B3_PGS_JACOBI_SOLVER