Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //The simulation loop:
- m_cmContactManager.UpdateContacts();
- for ( unsigned int I = 0UL; I < P_TOTAL_POLYGONS; ++I ) {
- CRigidBody* prbBody0 = &m_rbRigidBodies[I];
- for (unsigned int J = I + 1UL; J < P_TOTAL_POLYGONS; ++J) {
- CRigidBody* prbBody1 = &m_rbRigidBodies[J];
- if ( prbBody0->IsStatic() && prbBody1->IsStatic() ) { continue; }
- CDiscreteIntersect::DI_CONTACT_OUTPUT coContactOutput;
- if ( m_geGjkEpa.Intersect(prbBody0, prbBody1, &coContactOutput) ) {
- CContactManifold::CM_MANIFOLD_CONTACT cContact;
- cContact.vWorldPointOnA = coContactOutput.vPointOnA;
- cContact.vWorldPointOnB = coContactOutput.vPointOnB;
- cContact.vWorldNormalOnB = -coContactOutput.vNormalB;
- cContact.fDistance = coContactOutput.fDistance;
- CMatrix4x4 mInv0 = prbBody0->GetTransform();
- mInv0.Transpose();
- mInv0._41 = -mInv0._14;
- mInv0._42 = -mInv0._24;
- mInv0._43 = -mInv0._34;
- mInv0._14 = mInv0._24 = mInv0._34 = ML_ZERO;
- CMatrix4x4 mInv1 = prbBody1->GetTransform();
- mInv1.Transpose();
- mInv1._41 = -mInv1._14;
- mInv1._42 = -mInv1._24;
- mInv1._43 = -mInv1._34;
- mInv1._14 = mInv1._24 = mInv1._34 = ML_ZERO;
- cContact.vLocalPointOnA = mInv0 * cContact.vWorldPointOnA;
- cContact.vLocalPointOnB = mInv1 * cContact.vWorldPointOnB;
- CVector3 vR0 = cContact.vWorldPointOnA - prbBody0->m_vPos;
- CVector3 vR1 = cContact.vWorldPointOnB - prbBody1->m_vPos;
- CVector3 vVR0 = prbBody0->m_vLinVel + prbBody0->m_vAngVel.Cross(vR0);
- CVector3 vVR1 = prbBody1->m_vLinVel + prbBody1->m_vAngVel.Cross(vR1);
- CVector3 vDV = vVR1 - vVR0;
- cContact.vWorldTangents[0] = vDV - (cContact.vWorldNormalOnB * vDV.Dot(cContact.vWorldNormalOnB));
- float fTanLen = cContact.vWorldTangents[0].LenSq();
- if ( fTanLen > FLT_EPSILON ) {
- cContact.vWorldTangents[0] /= CMathLib::Sqrt(fTanLen);
- cContact.vWorldTangents[1] = cContact.vWorldTangents[0].Cross(cContact.vWorldNormalOnB);
- }
- else {
- CVector3::ComputeBasis(cContact.vWorldNormalOnB, cContact.vWorldTangents[0], cContact.vWorldTangents[1]);
- }
- m_cmContactManager.AddContact(prbBody0, prbBody1, cContact);
- }
- }
- }
- ///*
- for (unsigned int I = 0UL; I < P_TOTAL_POLYGONS; ++I) {
- m_rbRigidBodies[I].ApplyForces(CVector3(ML_ZERO, -10.0f, ML_ZERO), CVector3(ML_ZERO, ML_ZERO, ML_ZERO), fDeltaTime);
- }
- m_cmContactManager.PreStep(ML_ONE / fDeltaTime);
- m_cmContactManager.WarmStart();
- m_cmContactManager.ApplyImpulses();
- //*/
- for (unsigned int I = 0UL; I < P_TOTAL_POLYGONS; ++I) {
- m_rbRigidBodies[I].ApplyVelocities(fDeltaTime);
- }
- //How I'm integrating the bodies:
- void CRigidBody::ApplyForces(const CVector3& _vForce, const CVector3& _vTorque, float _fDeltaTime) {
- if (m_ui32CollFlags & SIF_STATIC_OBJECT) { return; }
- m_vLinVel += _vForce * (m_fInvMass * _fDeltaTime);
- m_vAngVel += (m_mWorldInvInertia * _vTorque) * _fDeltaTime;
- }
- void CRigidBody::ApplyVelocities(float _fDeltaTime) {
- if (m_ui32CollFlags & SIF_STATIC_OBJECT) { return; }
- CVector3 vTotalLinVel = m_vLinVel + m_vBiasLinVel;
- CVector3 vTotalAngVel = m_vAngVel + m_vBiasAngVel;
- m_vBiasLinVel.Clear();
- m_vBiasAngVel.Clear();
- m_vPos += vTotalLinVel * _fDeltaTime;
- CQuaternion qDtOrient = CQuaternion(vTotalAngVel.x, vTotalAngVel.y, vTotalAngVel.z, ML_ZERO) * m_qOrient * ML_HALF;
- m_qOrient += qDtOrient * _fDeltaTime;
- m_qOrient.Normalize();
- m_qOrient.ToRotationMatrix(m_mOrient);
- CMatrix4x4 mInvOrient = m_mOrient;
- mInvOrient.Transpose();
- m_mWorldInvInertia = m_mOrient * m_mLocalInvInertia * mInvOrient;
- m_mTransform = m_mOrient;
- reinterpret_cast<CVector3&>(m_mTransform._41) = m_vPos;
- //Compute this object AABB.
- if (m_psShape) {
- Parent::m_aAabb.ComputeAabbFromAabbAndMatrix(m_psShape->Aabb(), m_mTransform);
- if (m_pboBroadphaseObject) {
- m_pboBroadphaseObject->m_aAabb.ComputeAabbFromAabbAndMatrix(m_aAabb, m_mTransform);
- }
- }
- }
- //Here's how I'm solving the constraint (10 iterations):
- #ifndef __CONTACT_CONSTRAINT_H__
- #define __CONTACT_CONSTRAINT_H__
- #include "CRigidBody.h"
- #include "CContactManifold.h"
- #define IRPL_BAUMGARTE 0.2f
- #define IRPL_ALLOWED_PENETRATION 0.05f
- class CContactConstraint {
- friend class CContactManager;
- public:
- inline void PreStep(float _fInvDt) {
- for (unsigned int I = 0U; I < m_cmContactManifold.m_ui32TotalContacts; ++I) {
- CContactManifold::CM_MANIFOLD_CONTACT& cContact = m_cmContactManifold.m_cContacts[I];
- CVector3 vR0 = cContact.vWorldPointOnA - m_prbRigidBody0->m_vPos;
- CVector3 vR1 = cContact.vWorldPointOnB - m_prbRigidBody1->m_vPos;
- //Normal:
- {
- float fMassSum = m_prbRigidBody0->InvMass() + m_prbRigidBody1->InvMass();
- if (!m_prbRigidBody0->IsStatic()) {
- fMassSum += (m_prbRigidBody0->m_mWorldInvInertia * vR0.Cross(cContact.vWorldNormalOnB)).Cross(vR0).Dot(cContact.vWorldNormalOnB);
- }
- if (!m_prbRigidBody1->IsStatic()) {
- fMassSum += (m_prbRigidBody1->m_mWorldInvInertia * vR1.Cross(cContact.vWorldNormalOnB)).Cross(vR1).Dot(cContact.vWorldNormalOnB);
- }
- cContact.fNormalMass = ML_ONE / fMassSum;
- }
- for (unsigned int J = 0U; J < 2U; ++J) {
- //Tangent:
- const CVector3& vWorldTangent = cContact.vWorldTangents[J];
- float fMassSum = m_prbRigidBody0->InvMass() + m_prbRigidBody1->InvMass();
- if (!m_prbRigidBody0->IsStatic()) {
- fMassSum += (m_prbRigidBody0->m_mWorldInvInertia * vR0.Cross(vWorldTangent)).Cross(vR0).Dot(vWorldTangent);
- }
- if (!m_prbRigidBody1->IsStatic()) {
- fMassSum += (m_prbRigidBody1->m_mWorldInvInertia * vR1.Cross(vWorldTangent)).Cross(vR1).Dot(vWorldTangent);
- }
- cContact.fTangentMasses[J] = ML_ONE / fMassSum;
- }
- cContact.fBias = IRPL_BAUMGARTE * _fInvDt * CMathLib::Max(cContact.fDistance - IRPL_ALLOWED_PENETRATION, ML_ZERO);
- cContact.fPNB = ML_ZERO;
- }
- }
- inline void WarmStart() {
- for (unsigned int I = 0U; I < m_cmContactManifold.m_ui32TotalContacts; ++I) {
- CContactManifold::CM_MANIFOLD_CONTACT& cContact = m_cmContactManifold.m_cContacts[I];
- CVector3 vR0 = cContact.vWorldPointOnA - m_prbRigidBody0->m_vPos;
- CVector3 vR1 = cContact.vWorldPointOnB - m_prbRigidBody1->m_vPos;
- CVector3 vP = cContact.vWorldNormalOnB * cContact.fPN;
- for (unsigned int J = 0U; J < 2U; ++J) {
- vP += cContact.vWorldTangents[J] * cContact.fPT[J];
- }
- if (!m_prbRigidBody0->IsStatic()) {
- m_prbRigidBody0->m_vLinVel -= vP * m_prbRigidBody0->InvMass();
- m_prbRigidBody0->m_vAngVel -= m_prbRigidBody0->m_mWorldInvInertia * vR0.Cross(vP);
- }
- if (!m_prbRigidBody1->IsStatic()) {
- m_prbRigidBody1->m_vLinVel += vP * m_prbRigidBody1->InvMass();
- m_prbRigidBody1->m_vAngVel += m_prbRigidBody1->m_mWorldInvInertia * vR1.Cross(vP);
- }
- }
- }
- inline void ApplyImpulse() {
- for (unsigned int I = 0U; I < m_cmContactManifold.m_ui32TotalContacts; ++I) {
- CContactManifold::CM_MANIFOLD_CONTACT& cContact = m_cmContactManifold.m_cContacts[I];
- CVector3 vR0 = cContact.vWorldPointOnA - m_prbRigidBody0->m_vPos;
- CVector3 vR1 = cContact.vWorldPointOnB - m_prbRigidBody1->m_vPos;
- //Tangent:
- {
- for (unsigned int J = 0U; J < 2U; ++J) {
- const CVector3& vTangent = cContact.vWorldTangents[J];
- CVector3 vVR0 = m_prbRigidBody0->m_vLinVel + m_prbRigidBody0->m_vAngVel.Cross(vR0);
- CVector3 vVR1 = m_prbRigidBody1->m_vLinVel + m_prbRigidBody1->m_vAngVel.Cross(vR1);
- CVector3 vDV = vVR1 - vVR0;
- float fLambda = cContact.fTangentMasses[J] * -vDV.Dot(vTangent);
- float fMaxLambda = 0.5f * cContact.fPN;
- float fPT0 = cContact.fPT[J];
- cContact.fPT[J] = CMathLib::Clamp(fPT0 + fLambda, -fMaxLambda, fMaxLambda);
- fLambda = cContact.fPT[J] - fPT0;
- CVector3 vPT = vTangent * fLambda;
- if (!m_prbRigidBody0->IsStatic()) {
- m_prbRigidBody0->m_vLinVel -= vPT * m_prbRigidBody0->InvMass();
- m_prbRigidBody0->m_vAngVel -= m_prbRigidBody0->m_mWorldInvInertia * vR0.Cross(vPT);
- }
- if (!m_prbRigidBody1->IsStatic()) {
- m_prbRigidBody1->m_vLinVel += vPT * m_prbRigidBody1->InvMass();
- m_prbRigidBody1->m_vAngVel += m_prbRigidBody1->m_mWorldInvInertia * vR1.Cross(vPT);
- }
- }
- }
- //Normal:
- {
- CVector3 vVR0 = m_prbRigidBody0->m_vLinVel + m_prbRigidBody0->m_vAngVel.Cross(vR0);
- CVector3 vVR1 = m_prbRigidBody1->m_vLinVel + m_prbRigidBody1->m_vAngVel.Cross(vR1);
- CVector3 vDV = vVR1 - vVR0;
- float fLambda = cContact.fNormalMass * -vDV.Dot(cContact.vWorldNormalOnB);
- float fPN0 = cContact.fPN;
- cContact.fPN = CMathLib::Max(fPN0 + fLambda, ML_ZERO);
- fLambda = cContact.fPN - fPN0;
- CVector3 vPN = cContact.vWorldNormalOnB * fLambda;
- if (!m_prbRigidBody0->IsStatic()) {
- m_prbRigidBody0->m_vLinVel -= vPN * m_prbRigidBody0->InvMass();
- m_prbRigidBody0->m_vAngVel -= m_prbRigidBody0->m_mWorldInvInertia * vR0.Cross(vPN);
- }
- if (!m_prbRigidBody1->IsStatic()) {
- m_prbRigidBody1->m_vLinVel += vPN * m_prbRigidBody1->InvMass();
- m_prbRigidBody1->m_vAngVel += m_prbRigidBody1->m_mWorldInvInertia * vR1.Cross(vPN);
- }
- }
- //Biased Normal:
- {
- CVector3 vVR0 = m_prbRigidBody0->m_vBiasLinVel + m_prbRigidBody0->m_vBiasAngVel.Cross(vR0);
- CVector3 vVR1 = m_prbRigidBody1->m_vBiasLinVel + m_prbRigidBody1->m_vBiasAngVel.Cross(vR1);
- CVector3 vDV = vVR1 - vVR0;
- float fLambda = cContact.fNormalMass * (-vDV.Dot(cContact.vWorldNormalOnB) + cContact.fBias);
- float fPNB0 = cContact.fPNB;
- cContact.fPNB = CMathLib::Max(fPNB0 + fLambda, ML_ZERO);
- fLambda = cContact.fPNB - fPNB0;
- CVector3 vPN = cContact.vWorldNormalOnB * fLambda;
- if (!m_prbRigidBody0->IsStatic()) {
- m_prbRigidBody0->m_vBiasLinVel -= vPN * m_prbRigidBody0->InvMass();
- m_prbRigidBody0->m_vBiasAngVel -= m_prbRigidBody0->m_mWorldInvInertia * vR0.Cross(vPN);
- }
- if (!m_prbRigidBody1->IsStatic()) {
- m_prbRigidBody1->m_vBiasLinVel += vPN * m_prbRigidBody1->InvMass();
- m_prbRigidBody1->m_vBiasAngVel += m_prbRigidBody1->m_mWorldInvInertia * vR1.Cross(vPN);
- }
- }
- }
- }
- //protected :
- CRigidBody* m_prbRigidBody0;
- CRigidBody* m_prbRigidBody1;
- CContactManifold m_cmContactManifold;
- };
- #endif //#ifndef __CONTACT_CONSTRAINT_H__
- //The inertia tensor of the cubes:
- float fInvDensity = 0.5f;
- float fVolume = vHalfSize.Len() * ML_TWO;
- float fMass = fVolume * fInvDensity;
- rbBody.SetMass(fMass);
- fMass *= 0.333f;
- CMatrix4x4 mLocalInertia;
- mLocalInertia._11 = fMass * vHalfSize.y * vHalfSize.y + vHalfSize.z * vHalfSize.z;
- mLocalInertia._22 = fMass * vHalfSize.y * vHalfSize.x + vHalfSize.z * vHalfSize.z;
- mLocalInertia._33 = fMass * vHalfSize.y * vHalfSize.x + vHalfSize.z * vHalfSize.y;
- rbBody.m_mLocalInvInertia = mLocalInertia.Inverse();
Advertisement
Add Comment
Please, Sign In to add comment