void pfxSetupBallJoint( PfxJoint &joint, const PfxRigidState &stateA, const PfxRigidState &stateB, PfxSolverBody &solverBodyA, PfxSolverBody &solverBodyB, PfxFloat timeStep ) { PfxVector3 rA = rotate(solverBodyA.m_orientation,joint.m_anchorA); PfxVector3 rB = rotate(solverBodyB.m_orientation,joint.m_anchorB); PfxVector3 vA = stateA.getLinearVelocity() + cross(stateA.getAngularVelocity(),rA); PfxVector3 vB = stateB.getLinearVelocity() + cross(stateB.getAngularVelocity(),rB); PfxVector3 vAB = vA-vB; PfxVector3 distance = (stateA.getPosition() + rA) - (stateB.getPosition() + rB); PfxMatrix3 worldFrameA,worldFrameB; worldFrameA = PfxMatrix3(solverBodyA.m_orientation) * joint.m_frameA; worldFrameB = PfxMatrix3(solverBodyB.m_orientation) * joint.m_frameB; // Linear Constraint PfxMatrix3 K = PfxMatrix3::scale(PfxVector3(solverBodyA.m_massInv + solverBodyB.m_massInv)) - crossMatrix(rA) * solverBodyA.m_inertiaInv * crossMatrix(rA) - crossMatrix(rB) * solverBodyB.m_inertiaInv * crossMatrix(rB); for(int c=0;c<3;c++) { PfxJointConstraint &jointConstraint = joint.m_constraints[c]; PfxConstraintRow &constraint = jointConstraint.m_constraintRow; PfxVector3 normal = worldFrameA[c]; PfxFloat posErr = dot(distance,-normal); PfxFloat lowerLimit = -jointConstraint.m_maxImpulse; PfxFloat upperLimit = jointConstraint.m_maxImpulse; PfxFloat velocityAmp = 1.0f; pfxCalcLinearLimit(jointConstraint,posErr,velocityAmp,lowerLimit,upperLimit); PfxFloat denom = dot(K*normal,normal); constraint.m_rhs = -velocityAmp*dot(vAB,normal); constraint.m_rhs -= (jointConstraint.m_bias * (-posErr)) / timeStep; constraint.m_rhs *= jointConstraint.m_weight/denom; constraint.m_jacDiagInv = jointConstraint.m_weight*velocityAmp/denom; constraint.m_lowerLimit = lowerLimit; constraint.m_upperLimit = upperLimit; pfxStoreVector3(normal,constraint.m_normal); } }
void pfxSetupContactConstraint( PfxConstraintRow &constraintResponse, PfxConstraintRow &constraintFriction1, PfxConstraintRow &constraintFriction2, PfxFloat penetrationDepth, PfxFloat restitution, PfxFloat friction, const PfxVector3 &contactNormal, const PfxVector3 &contactPointA, const PfxVector3 &contactPointB, const PfxRigidState &stateA, const PfxRigidState &stateB, PfxSolverBody &solverBodyA, PfxSolverBody &solverBodyB, PfxFloat separateBias, PfxFloat timeStep ) { (void)friction; PfxVector3 rA = rotate(solverBodyA.m_orientation,contactPointA); PfxVector3 rB = rotate(solverBodyB.m_orientation,contactPointB); PfxFloat massInvA = solverBodyA.m_massInv; PfxFloat massInvB = solverBodyB.m_massInv; PfxMatrix3 inertiaInvA = solverBodyA.m_inertiaInv; PfxMatrix3 inertiaInvB = solverBodyB.m_inertiaInv; if(solverBodyA.m_motionType == kPfxMotionTypeOneWay) { massInvB = 0.0f; inertiaInvB = PfxMatrix3(0.0f); } if(solverBodyB.m_motionType == kPfxMotionTypeOneWay) { massInvA = 0.0f; inertiaInvA = PfxMatrix3(0.0f); } PfxMatrix3 K = PfxMatrix3::scale(PfxVector3(massInvA + massInvB)) - crossMatrix(rA) * inertiaInvA * crossMatrix(rA) - crossMatrix(rB) * inertiaInvB * crossMatrix(rB); PfxVector3 vA = stateA.getLinearVelocity() + cross(stateA.getAngularVelocity(),rA); PfxVector3 vB = stateB.getLinearVelocity() + cross(stateB.getAngularVelocity(),rB); PfxVector3 vAB = vA-vB; PfxVector3 tangent1,tangent2; pfxGetPlaneSpace(contactNormal,tangent1,tangent2); // Contact Constraint { PfxVector3 normal = contactNormal; PfxFloat denom = dot(K*normal,normal); constraintResponse.m_rhs = -(1.0f+restitution)*dot(vAB,normal); // velocity error constraintResponse.m_rhs -= (separateBias * SCE_PFX_MIN(0.0f,penetrationDepth+SCE_PFX_CONTACT_SLOP)) / timeStep; // position error constraintResponse.m_rhs /= denom; constraintResponse.m_jacDiagInv = 1.0f/denom; constraintResponse.m_lowerLimit = 0.0f; constraintResponse.m_upperLimit = SCE_PFX_FLT_MAX; pfxStoreVector3(normal,constraintResponse.m_normal); } // Friction Constraint 1 { PfxVector3 normal = tangent1; PfxFloat denom = dot(K*normal,normal); constraintFriction1.m_jacDiagInv = 1.0f/denom; constraintFriction1.m_rhs = -dot(vAB,normal); constraintFriction1.m_rhs *= constraintFriction1.m_jacDiagInv; constraintFriction1.m_lowerLimit = 0.0f; constraintFriction1.m_upperLimit = SCE_PFX_FLT_MAX; pfxStoreVector3(normal,constraintFriction1.m_normal); } // Friction Constraint 2 { PfxVector3 normal = tangent2; PfxFloat denom = dot(K*normal,normal); constraintFriction2.m_jacDiagInv = 1.0f/denom; constraintFriction2.m_rhs = -dot(vAB,normal); constraintFriction2.m_rhs *= constraintFriction2.m_jacDiagInv; constraintFriction2.m_lowerLimit = 0.0f; constraintFriction2.m_upperLimit = SCE_PFX_FLT_MAX; pfxStoreVector3(normal,constraintFriction2.m_normal); } }