2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
16 ///This file was written by Erwin Coumans
18 #include "btMultiBodyFixedConstraint.h"
19 #include "btMultiBodyLinkCollider.h"
20 #include "BulletDynamics/Dynamics/btRigidBody.h"
21 #include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
22 #include "LinearMath/btIDebugDraw.h"
24 #define BTMBFIXEDCONSTRAINT_DIM 6
26 btMultiBodyFixedConstraint::btMultiBodyFixedConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
27 : btMultiBodyConstraint(body, 0, link, -1, BTMBFIXEDCONSTRAINT_DIM, false, MULTIBODY_CONSTRAINT_FIXED),
35 m_data.resize(BTMBFIXEDCONSTRAINT_DIM); //at least store the applied impulses
38 btMultiBodyFixedConstraint::btMultiBodyFixedConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
39 : btMultiBodyConstraint(bodyA, bodyB, linkA, linkB, BTMBFIXEDCONSTRAINT_DIM, false, MULTIBODY_CONSTRAINT_FIXED),
47 m_data.resize(BTMBFIXEDCONSTRAINT_DIM); //at least store the applied impulses
50 void btMultiBodyFixedConstraint::finalizeMultiDof()
56 btMultiBodyFixedConstraint::~btMultiBodyFixedConstraint()
60 int btMultiBodyFixedConstraint::getIslandIdA() const
63 return m_rigidBodyA->getIslandTag();
69 btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
71 return col->getIslandTag();
75 if (m_bodyA->getLink(m_linkA).m_collider)
76 return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
82 int btMultiBodyFixedConstraint::getIslandIdB() const
85 return m_rigidBodyB->getIslandTag();
90 btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
92 return col->getIslandTag();
96 if (m_bodyB->getLink(m_linkB).m_collider)
97 return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
103 void btMultiBodyFixedConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows, btMultiBodyJacobianData& data, const btContactSolverInfo& infoGlobal)
105 int numDim = BTMBFIXEDCONSTRAINT_DIM;
106 for (int i = 0; i < numDim; i++)
108 btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
109 constraintRow.m_orgConstraint = this;
110 constraintRow.m_orgDofIndex = i;
111 constraintRow.m_relpos1CrossNormal.setValue(0, 0, 0);
112 constraintRow.m_contactNormal1.setValue(0, 0, 0);
113 constraintRow.m_relpos2CrossNormal.setValue(0, 0, 0);
114 constraintRow.m_contactNormal2.setValue(0, 0, 0);
115 constraintRow.m_angularComponentA.setValue(0, 0, 0);
116 constraintRow.m_angularComponentB.setValue(0, 0, 0);
118 constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
119 constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
121 // Convert local points back to world
122 btVector3 pivotAworld = m_pivotInA;
123 btMatrix3x3 frameAworld = m_frameInA;
126 constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
127 pivotAworld = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
128 frameAworld = frameAworld.transpose() * btMatrix3x3(m_rigidBodyA->getOrientation());
134 pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
135 frameAworld = m_bodyA->localFrameToWorld(m_linkA, frameAworld);
138 btVector3 pivotBworld = m_pivotInB;
139 btMatrix3x3 frameBworld = m_frameInB;
142 constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
143 pivotBworld = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
144 frameBworld = frameBworld.transpose() * btMatrix3x3(m_rigidBodyB->getOrientation());
150 pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
151 frameBworld = m_bodyB->localFrameToWorld(m_linkB, frameBworld);
155 btMatrix3x3 relRot = frameAworld.inverse() * frameBworld;
157 btGeneric6DofSpring2Constraint::matrixToEulerXYZ(relRot, angleDiff);
159 btVector3 constraintNormalLin(0, 0, 0);
160 btVector3 constraintNormalAng(0, 0, 0);
161 btScalar posError = 0.0;
164 constraintNormalLin[i] = 1;
165 posError = (pivotAworld - pivotBworld).dot(constraintNormalLin);
166 fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
167 constraintNormalLin, pivotAworld, pivotBworld,
170 -m_maxAppliedImpulse, m_maxAppliedImpulse);
174 constraintNormalAng = frameAworld.getColumn(i % 3);
175 posError = angleDiff[i % 3];
176 fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
177 constraintNormalLin, pivotAworld, pivotBworld,
180 -m_maxAppliedImpulse, m_maxAppliedImpulse, true);
185 void btMultiBodyFixedConstraint::debugDraw(class btIDebugDraw* drawer)
192 btVector3 pivot = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
194 drawer->drawTransform(tr, 0.1);
198 btVector3 pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
199 tr.setOrigin(pivotAworld);
200 drawer->drawTransform(tr, 0.1);
204 // that ideally should draw the same frame
205 btVector3 pivot = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
207 drawer->drawTransform(tr, 0.1);
211 btVector3 pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
212 tr.setOrigin(pivotBworld);
213 drawer->drawTransform(tr, 0.1);