rotate a crate around me when i Turn

Post Reply
Furya
Posts: 24
Joined: Tue Sep 22, 2015 1:34 pm

rotate a crate around me when i Turn

Post by Furya »

Hi,

I make an adventure game like tomb raider with bullet and Ogre 3d. And I have a problem to displace crates or boxes.

I use a btGeneric6DofConstraint in order to push/pull some crates with my character. It works, the crate move with my hero.

But i want also that when my hero turn around himself in 360°, I want that my crate around my hero but i don't know how to do that. When I turn, the crate doesn't move.

here my code:

Code: Select all

btVector3 localpivot = pDeplacable->mRigidBody->getWorldTransform().inverse()*mPJ->mCharacter->getGhostObject()->getWorldTransform().getOrigin();
		btQuaternion btQuat = mPJ->mCharacter->getGhostObject()->getWorldTransform().getRotation();

		btTransform btT(btQuat, localpivot);



		dof6 = new btGeneric6DofConstraint(*pDeplacable->mRigidBody, btT, true);
		dof6->setAngularLowerLimit(btVector3(0, 0, 0));
		dof6->setAngularUpperLimit(btVector3(0, 0, 0));
		mPJ->mWorld->getBulletDynamicsWorld()->addConstraint(dof6,true);


		float cfm = 0.5f;
		dof6->setParam(BT_CONSTRAINT_STOP_CFM, cfm, 0);
		dof6->setParam(BT_CONSTRAINT_STOP_CFM, cfm, 1);
		dof6->setParam(BT_CONSTRAINT_STOP_CFM, cfm, 2);
		dof6->setParam(BT_CONSTRAINT_STOP_CFM, cfm, 3);
		dof6->setParam(BT_CONSTRAINT_STOP_CFM, cfm, 4);
		dof6->setParam(BT_CONSTRAINT_STOP_CFM, cfm, 5);


		float erp = 0.5f;
		dof6->setParam(BT_CONSTRAINT_STOP_ERP, erp, 0);
		dof6->setParam(BT_CONSTRAINT_STOP_ERP, erp, 1);
		dof6->setParam(BT_CONSTRAINT_STOP_ERP, erp, 2);
		dof6->setParam(BT_CONSTRAINT_STOP_ERP, erp, 3);
		dof6->setParam(BT_CONSTRAINT_STOP_ERP, erp, 4);
		dof6->setParam(BT_CONSTRAINT_STOP_ERP, erp, 5);
in my loop:

Code: Select all

if (dof6 != NULL && mPJ->interaction == 2){
			
			btVector3 dir = btVector3(myHero->mNode->getOrientation().zAxis().x, myHero->mNode->getOrientation().zAxis().y, myHero>mNode->getOrientation().zAxis().z);
			//dir.normalize();
			btVector3 newPivot =myHero->mCharacter->getGhostObject()->getWorldTransform().getOrigin()*dir;

			dof6->getFrameOffsetA().setOrigin(newPivot);
			
			
		}
Could you help me please ?
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: rotate a crate around me when i Turn

Post by drleviathan »

The btGeneric6DofConstraint class has two CTORs:

Code: Select all

    btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
    btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB); 
You're using the second variety, which uses the World as "bodyA". I assume you're doing this because your character doesn't have a RigidBody only a GhostObject. That is fine, but that is why you have to continually update the Constraint's frameInA every Game Loop. If your Character had a kinematic RigidBody you could use the first variety which sets the relative transforms, and then when your Character moves around the Box would just follow, no Game Loop update necessary.

I would do it this way:

(1) At initial grab: compute boxToCharacter. This is the relative transform you want to be invariant over time.

Code: Select all

btTransform worldToBox = pDeplacable->mRigidBody->getWorldTransform();
btTransform worldToCharacter = mPJ->mCharacter->getGhostObject->getWorldTransform();
btTransform boxToCharacter = worldToCharacter() * worldToBox.inverse(); 
But, it looks like you want the rotation of the Box to be the same as the Character. Or put another way, the relative rotation from Box to Character is the Identity rotation. So you would add this line:

Code: Select all

 boxToCharacter.setRotation(btQuaternion::getIdentity()); 
(2) Now that you have boxToCharacter, you will have to update one of the transforms of the Constraint every Game Loop in order to keep boxToCharacter invariant. You were updating frameInA every Game Loop which is the Constraint's frameInWorld. Another way to do it is to leave frameInA constant (Identity) and instead to update frameInB. I prefer to think of it this way, so I would modify your Game Loop logic as follows:

Code: Select all

if (dof6 != NULL && mPJ->interaction == 2){
    btTransform worldToCharacter = myHero->mCharacter->getGhostObject()->getWorldTransform();
    btTransform boxToWorld = characterToWorld * boxToCharacter;
    btTransform& frameInB = dof6->getFrameOffsetB();
    frameInB = boxToWorld;
}
Hopefully that works. I wrote from scratch and did not test.
Furya
Posts: 24
Joined: Tue Sep 22, 2015 1:34 pm

Re: rotate a crate around me when i Turn

Post by Furya »

hi,

thank for your help.

Unfortunately it doesn't work. Just with the first part, my crate is projected far far away...


++
Furya
Posts: 24
Joined: Tue Sep 22, 2015 1:34 pm

Re: rotate a crate around me when i Turn

Post by Furya »

Just a question

How did you get characterToWorld ? It is worldToCharacter.inverse() ?

++
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: rotate a crate around me when i Turn

Post by drleviathan »

Sorry that code doesn't work. I haven't had time to actually setup a bt6dofConstraint to test, debug, and fix.

Yes, characterToWorld would be worldToCharacter.inverse().

Order matters for transforms because they don't commute, so what is the right order? A useful trick I use is to imagine the transforms operating from the left on some vector on the right. With that in mind you can usually figure out which transform should apply first (right-most) and which would apply last (left-most).

I hope that helps. Good luck.
Post Reply