void btMultiBodyJointMotor::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
		btMultiBodyJacobianData& data,
		const btContactSolverInfo& infoGlobal)
{
    // only positions need to be updated -- data.m_jacobians and force
    // directions were set in the ctor and never change.

	if (m_numDofsFinalized != m_jacSizeBoth)
	{
        finalizeMultiDof();
	}

	//don't crash
	if (m_numDofsFinalized != m_jacSizeBoth)
		return;

	const btScalar posError = 0;
	const btVector3 dummy(0, 0, 0);

	for (int row=0;row<getNumRows();row++)
	{
		btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();


		fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,posError,infoGlobal,-m_maxAppliedImpulse,m_maxAppliedImpulse,1,false,m_desiredVelocity);
	}

}
void btMultiBodyJointLimitConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
		btMultiBodyJacobianData& data,
		const btContactSolverInfo& infoGlobal)
{
    // only positions need to be updated -- data.m_jacobians and force
    // directions were set in the ctor and never change.
    
    // row 0: the lower bound
    setPosition(0, m_bodyA->getJointPos(m_linkA) - m_lowerBound);			//multidof: this is joint-type dependent

    // row 1: the upper bound
    setPosition(1, m_upperBound - m_bodyA->getJointPos(m_linkA));

	for (int row=0;row<getNumRows();row++)
	{
		btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
		constraintRow.m_multiBodyA = m_bodyA;
		constraintRow.m_multiBodyB = m_bodyB;
		const btScalar posError = 0;						//why assume it's zero?
		const btVector3 dummy(0, 0, 0);
		
		btScalar rel_vel = fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,posError,infoGlobal,0,m_maxAppliedImpulse);
		{
			btScalar penetration = getPosition(row);
			btScalar positionalError = 0.f;
			btScalar	velocityError =  - rel_vel;// * damping;
			btScalar erp = infoGlobal.m_erp2;
			if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
			{
				erp = infoGlobal.m_erp;
			}
			if (penetration>0)
			{
				positionalError = 0;
				velocityError = -penetration / infoGlobal.m_timeStep;
			} else
			{
				positionalError = -penetration * erp/infoGlobal.m_timeStep;
			}

			btScalar  penetrationImpulse = positionalError*constraintRow.m_jacDiagABInv;
			btScalar velocityImpulse = velocityError *constraintRow.m_jacDiagABInv;
			if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
			{
				//combine position and velocity into rhs
				constraintRow.m_rhs = penetrationImpulse+velocityImpulse;
				constraintRow.m_rhsPenetration = 0.f;

			} else
			{
				//split position and velocity into rhs and m_rhsPenetration
				constraintRow.m_rhs = velocityImpulse;
				constraintRow.m_rhsPenetration = penetrationImpulse;
			}
		}
	}

}
void btMultiBodyJointMotor::finalizeMultiDof()
{
	allocateJacobiansMultiDof();
	// note: we rely on the fact that data.m_jacobians are
	// always initialized to zero by the Constraint ctor
	int linkDoF = 0;
	unsigned int offset = 6 + (m_bodyA->isMultiDof() ? m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF : m_linkA);

	// row 0: the lower bound
	// row 0: the lower bound
	jacobianA(0)[offset] = 1;

	m_numDofsFinalized = m_jacSizeBoth;
}
btMultiBodyJointMotor::btMultiBodyJointMotor(btMultiBody* body, int link, btScalar desiredVelocity, btScalar maxMotorImpulse)
	:btMultiBodyConstraint(body,body,link,link,1,true),
	m_desiredVelocity(desiredVelocity)	
{
	m_maxAppliedImpulse = maxMotorImpulse;
	// the data.m_jacobians never change, so may as well
    // initialize them here
        
    // note: we rely on the fact that data.m_jacobians are
    // always initialized to zero by the Constraint ctor

    // row 0: the lower bound
    jacobianA(0)[6 + link] = 1;
}
void btMultiBodyJointLimitConstraint::finalizeMultiDof()
{
	// the data.m_jacobians never change, so may as well
    // initialize them here

	allocateJacobiansMultiDof();

	unsigned int offset = 6 + m_bodyA->getLink(m_linkA).m_dofOffset;

	// row 0: the lower bound
	jacobianA(0)[offset] = 1;
	// row 1: the upper bound
	//jacobianA(1)[offset] = -1;
	jacobianB(1)[offset] = -1;

	m_numDofsFinalized = m_jacSizeBoth;
}
void btMultiBodyJointMotor::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
		btMultiBodyJacobianData& data,
		const btContactSolverInfo& infoGlobal)
{
    // only positions need to be updated -- data.m_jacobians and force
    // directions were set in the ctor and never change.
    
  

	for (int row=0;row<getNumRows();row++)
	{
		btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
		
		btScalar penetration = 0;
		fillConstraintRowMultiBodyMultiBody(constraintRow,data,jacobianA(row),jacobianB(row),infoGlobal,m_desiredVelocity,-m_maxAppliedImpulse,m_maxAppliedImpulse);
	}

}
btMultiBodyJointMotor::btMultiBodyJointMotor(btMultiBody* body, int link, btScalar desiredVelocity, btScalar maxMotorImpulse)
	:btMultiBodyConstraint(body,body,link,link,1,true),
	m_desiredVelocity(desiredVelocity)	
{
	int linkDoF = 0;

	m_maxAppliedImpulse = maxMotorImpulse;
	// the data.m_jacobians never change, so may as well
    // initialize them here
        
    // note: we rely on the fact that data.m_jacobians are
    // always initialized to zero by the Constraint ctor

    unsigned int offset = 6 + (body->isMultiDof() ? body->getLink(link).m_dofOffset + linkDoF : link);

	// row 0: the lower bound
	// row 0: the lower bound
    jacobianA(0)[offset] = 1;
}
btMultiBodyJointLimitConstraint::btMultiBodyJointLimitConstraint(btMultiBody* body, int link, btScalar lower, btScalar upper)
	//:btMultiBodyConstraint(body,0,link,-1,2,true),
	:btMultiBodyConstraint(body,body,link,link,2,true),
	m_lowerBound(lower),
	m_upperBound(upper)
{
	// the data.m_jacobians never change, so may as well
    // initialize them here
        
    // note: we rely on the fact that data.m_jacobians are
    // always initialized to zero by the Constraint ctor

	unsigned int offset = 6 + (body->isMultiDof() ? body->getLink(link).m_dofOffset : link);

	// row 0: the lower bound
	jacobianA(0)[offset] = 1;
	// row 1: the upper bound
	//jacobianA(1)[offset] = -1;

	jacobianB(1)[offset] = -1;
}
void btMultiBodyJointMotor::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
		btMultiBodyJacobianData& data,
		const btContactSolverInfo& infoGlobal)
{
    // only positions need to be updated -- data.m_jacobians and force
    // directions were set in the ctor and never change.
	
	if (m_numDofsFinalized != m_jacSizeBoth)
	{
        finalizeMultiDof();
	}

	//don't crash
	if (m_numDofsFinalized != m_jacSizeBoth)
		return;

	const btScalar posError = 0;
	const btVector3 dummy(0, 0, 0);

	for (int row=0;row<getNumRows();row++)
	{
		btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();


		fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,posError,infoGlobal,-m_maxAppliedImpulse,m_maxAppliedImpulse,1,false,m_desiredVelocity);
		constraintRow.m_orgConstraint = this;
		constraintRow.m_orgDofIndex = row;
		if (m_bodyA->isMultiDof())
		{
			//expect either prismatic or revolute joint type for now
			btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute)||(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
			switch (m_bodyA->getLink(m_linkA).m_jointType)
			{
				case btMultibodyLink::eRevolute:
				{
					constraintRow.m_contactNormal1.setZero();
					constraintRow.m_contactNormal2.setZero();
					btVector3 revoluteAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
					constraintRow.m_relpos1CrossNormal=revoluteAxisInWorld;
					constraintRow.m_relpos2CrossNormal=-revoluteAxisInWorld;
					
					break;
				}
				case btMultibodyLink::ePrismatic:
				{
					btVector3 prismaticAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
					constraintRow.m_contactNormal1=prismaticAxisInWorld;
					constraintRow.m_contactNormal2=-prismaticAxisInWorld;
					constraintRow.m_relpos1CrossNormal.setZero();
					constraintRow.m_relpos2CrossNormal.setZero();
					
					break;
				}
				default:
				{
					btAssert(0);
				}
			};
			
		}

	}

}
void btMultiBodyPoint2Point::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
		btMultiBodyJacobianData& data,
		const btContactSolverInfo& infoGlobal)
{

//	int i=1;
int numDim = BTMBP2PCONSTRAINT_DIM;
	for (int i=0;i<numDim;i++)
	{

		btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
        //memset(&constraintRow,0xffffffff,sizeof(btMultiBodySolverConstraint));
        constraintRow.m_relpos1CrossNormal.setValue(0,0,0);
        constraintRow.m_contactNormal1.setValue(0,0,0);
        constraintRow.m_relpos2CrossNormal.setValue(0,0,0);
        constraintRow.m_contactNormal2.setValue(0,0,0);
        constraintRow.m_angularComponentA.setValue(0,0,0);
        constraintRow.m_angularComponentB.setValue(0,0,0);

		constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
		constraintRow.m_solverBodyIdB = data.m_fixedBodyId;

		btVector3 contactNormalOnB(0,0,0);
#ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
		contactNormalOnB[i] = -1;
#else
		contactNormalOnB[i%3] = -1;
#endif


		 // Convert local points back to world
		btVector3 pivotAworld = m_pivotInA;
		if (m_rigidBodyA)
		{

			constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
			pivotAworld = m_rigidBodyA->getCenterOfMassTransform()*m_pivotInA;
		} else
		{
			if (m_bodyA)
				pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
		}
		btVector3 pivotBworld = m_pivotInB;
		if (m_rigidBodyB)
		{
			constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
			pivotBworld = m_rigidBodyB->getCenterOfMassTransform()*m_pivotInB;
		} else
		{
			if (m_bodyB)
				pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);

		}

		btScalar posError = i < 3 ? (pivotAworld-pivotBworld).dot(contactNormalOnB) : 0;

#ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST


		fillMultiBodyConstraint(constraintRow, data, 0, 0,
															contactNormalOnB, pivotAworld, pivotBworld,						//sucks but let it be this way "for the time being"
															posError,
															infoGlobal,
															-m_maxAppliedImpulse, m_maxAppliedImpulse
															);
    //@todo: support the case of btMultiBody versus btRigidBody,
    //see btPoint2PointConstraint::getInfo2NonVirtual
#else
		const btVector3 dummy(0, 0, 0);

		btAssert(m_bodyA->isMultiDof());

		btScalar* jac1 = jacobianA(i);
		const btVector3 &normalAng = i >= 3 ? contactNormalOnB : dummy;
		const btVector3 &normalLin = i < 3 ? contactNormalOnB : dummy;

		m_bodyA->filConstraintJacobianMultiDof(m_linkA, pivotAworld, normalAng, normalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);

		fillMultiBodyConstraint(constraintRow, data, jac1, 0,
													dummy, dummy, dummy,						//sucks but let it be this way "for the time being"
													posError,
													infoGlobal,
													-m_maxAppliedImpulse, m_maxAppliedImpulse
													);
#endif
	}
}
void btMultiBodyJointLimitConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
		btMultiBodyJacobianData& data,
		const btContactSolverInfo& infoGlobal)
{
	
    // only positions need to be updated -- data.m_jacobians and force
    // directions were set in the ctor and never change.

	if (m_numDofsFinalized != m_jacSizeBoth)
	{
        finalizeMultiDof();
	}


    // row 0: the lower bound
    setPosition(0, m_bodyA->getJointPos(m_linkA) - m_lowerBound);			//multidof: this is joint-type dependent

    // row 1: the upper bound
    setPosition(1, m_upperBound - m_bodyA->getJointPos(m_linkA));
	
	for (int row=0;row<getNumRows();row++)
	{
		btScalar penetration = getPosition(row);

		//todo: consider adding some safety threshold here
		if (penetration>0)
		{
			continue;
		}
		btScalar direction = row? -1 : 1;

		btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
        constraintRow.m_orgConstraint = this;
        constraintRow.m_orgDofIndex = row;
        
		constraintRow.m_multiBodyA = m_bodyA;
		constraintRow.m_multiBodyB = m_bodyB;
		const btScalar posError = 0;						//why assume it's zero?
		const btVector3 dummy(0, 0, 0);

		btScalar rel_vel = fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,dummy,posError,infoGlobal,0,m_maxAppliedImpulse);

		{
			//expect either prismatic or revolute joint type for now
			btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute)||(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
			switch (m_bodyA->getLink(m_linkA).m_jointType)
			{
				case btMultibodyLink::eRevolute:
				{
					constraintRow.m_contactNormal1.setZero();
					constraintRow.m_contactNormal2.setZero();
					btVector3 revoluteAxisInWorld = direction*quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
					constraintRow.m_relpos1CrossNormal=revoluteAxisInWorld;
					constraintRow.m_relpos2CrossNormal=-revoluteAxisInWorld;
					
					break;
				}
				case btMultibodyLink::ePrismatic:
				{
					btVector3 prismaticAxisInWorld = direction* quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
					constraintRow.m_contactNormal1=prismaticAxisInWorld;
					constraintRow.m_contactNormal2=-prismaticAxisInWorld;
					constraintRow.m_relpos1CrossNormal.setZero();
					constraintRow.m_relpos2CrossNormal.setZero();
					
					break;
				}
				default:
				{
					btAssert(0);
				}
			};
			
		}

		{
			
			btScalar positionalError = 0.f;
			btScalar	velocityError =  - rel_vel;// * damping;
			btScalar erp = infoGlobal.m_erp2;
			if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
			{
				erp = infoGlobal.m_erp;
			}
			if (penetration>0)
			{
				positionalError = 0;
				velocityError = -penetration / infoGlobal.m_timeStep;
			} else
			{
				positionalError = -penetration * erp/infoGlobal.m_timeStep;
			}

			btScalar  penetrationImpulse = positionalError*constraintRow.m_jacDiagABInv;
			btScalar velocityImpulse = velocityError *constraintRow.m_jacDiagABInv;
			if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
			{
				//combine position and velocity into rhs
				constraintRow.m_rhs = penetrationImpulse+velocityImpulse;
				constraintRow.m_rhsPenetration = 0.f;

			} else
			{
				//split position and velocity into rhs and m_rhsPenetration
				constraintRow.m_rhs = velocityImpulse;
				constraintRow.m_rhsPenetration = penetrationImpulse;
			}
		}
	}

}
void btMultiBodyGearConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
		btMultiBodyJacobianData& data,
		const btContactSolverInfo& infoGlobal)
{
    // only positions need to be updated -- data.m_jacobians and force
    // directions were set in the ctor and never change.
	
	if (m_numDofsFinalized != m_jacSizeBoth)
	{
        finalizeMultiDof();
	}

	//don't crash
	if (m_numDofsFinalized != m_jacSizeBoth)
		return;

	
	if (m_maxAppliedImpulse==0.f)
		return;
	
	// note: we rely on the fact that data.m_jacobians are
	// always initialized to zero by the Constraint ctor
	int linkDoF = 0;
	unsigned int offsetA = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF);
	unsigned int offsetB = 6 + (m_bodyB->getLink(m_linkB).m_dofOffset + linkDoF);

	// row 0: the lower bound
	jacobianA(0)[offsetA] = 1;
	jacobianB(0)[offsetB] = m_gearRatio;

	const btScalar posError = 0;
	const btVector3 dummy(0, 0, 0);
	btScalar erp = infoGlobal.m_erp;
	btScalar kp = 1;
	btScalar kd = 1;
	int numRows = getNumRows();

	for (int row=0;row<numRows;row++)
	{
		btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();


        int dof = 0;
        btScalar currentPosition = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
        btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
		btScalar auxVel = 0;
		
		if (m_gearAuxLink>=0)
		{
			auxVel = m_bodyA->getJointVelMultiDof(m_gearAuxLink)[dof];
		}
		currentVelocity += auxVel;
			
		//btScalar positionStabiliationTerm = erp*(m_desiredPosition-currentPosition)/infoGlobal.m_timeStep;
        //btScalar velocityError = (m_desiredVelocity - currentVelocity);

        btScalar desiredRelativeVelocity =   auxVel;
    
		fillMultiBodyConstraint(constraintRow,data,jacobianA(row),jacobianB(row),dummy,dummy,dummy,dummy,posError,infoGlobal,-m_maxAppliedImpulse,m_maxAppliedImpulse,false,1,false,desiredRelativeVelocity);

		constraintRow.m_orgConstraint = this;
		constraintRow.m_orgDofIndex = row;
		{
			//expect either prismatic or revolute joint type for now
			btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute)||(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
			switch (m_bodyA->getLink(m_linkA).m_jointType)
			{
				case btMultibodyLink::eRevolute:
				{
					constraintRow.m_contactNormal1.setZero();
					constraintRow.m_contactNormal2.setZero();
					btVector3 revoluteAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
					constraintRow.m_relpos1CrossNormal=revoluteAxisInWorld;
					constraintRow.m_relpos2CrossNormal=-revoluteAxisInWorld;
					
					break;
				}
				case btMultibodyLink::ePrismatic:
				{
					btVector3 prismaticAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(),m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
					constraintRow.m_contactNormal1=prismaticAxisInWorld;
					constraintRow.m_contactNormal2=-prismaticAxisInWorld;
					constraintRow.m_relpos1CrossNormal.setZero();
					constraintRow.m_relpos2CrossNormal.setZero();					
					break;
				}
				default:
				{
					btAssert(0);
				}
			};
			
		}

	}

}