How to manually change position of dynamic object

Post Reply
peanutandchestnut
Posts: 8
Joined: Mon Feb 02, 2015 8:40 am

How to manually change position of dynamic object

Post by peanutandchestnut »

I want to change position of dynamic object manually, this is my code.

Code: Select all

body->activate(true);
btMotionState* ms = body->getMotionState();
btTransform tf;
ms->getWorldTransform(tf);
tf.setOrigin(btVector3(x, y, z));
ms->setWorldTransform(tf);
It doesn't work, the object will flash back to it's original position :(
How to manually change position of dynamic object :?:
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: How to manually change position of dynamic object

Post by drleviathan »

I assume your MotionState is actually a btDefaultMotionState instance, since that is the only non-virtual flavor of btMotionState implemented in the official Bullet code. If you examine the implementation of btDefaultMotionState you'll see that it doesn't actually apply the transform in setWorldTransform() -- it just stores it in an internal data member.

There are two ways to do what you want:

(1) Since you already have a pointer to the btRigidBody you can just use body->getWorldTransform() and body->setWorldTransform().

(2) If you want to use the MotionState system you can implement a derived MyMotionState class that does the work in (1) for you. The only advantage of using the MotionState API that I can think of is that Bullet will call MyMotionState::setWorldTransform() once a frame for kinematic objects that have a MotionSate. So if your game engine will support with such content it is possible to organize a cleaner boundary between GameEngine and PhysicsEngine code, with MotionStates as the intermediaries between the two.
peanutandchestnut
Posts: 8
Joined: Mon Feb 02, 2015 8:40 am

Re: How to manually change position of dynamic object

Post by peanutandchestnut »

Hi drleviathan.

I use ogre with bullet, this is my motion state:

Code: Select all

virtual void getWorldTransform(btTransform &worldTrans) const
		{
			worldTrans.setRotation(toBt(mSceneNode->_getDerivedOrientation()));
			worldTrans.setOrigin(toBt(mSceneNode->_getDerivedPosition()));
		}

		virtual void setWorldTransform(const btTransform &worldTrans)
		{
			const btQuaternion &rot = worldTrans.getRotation();
			mSceneNode ->setOrientation(rot.w(), rot.x(), rot.y(), rot.z());
			const btVector3 &pos = worldTrans.getOrigin();
			mSceneNode ->setPosition(pos.x(), pos.y(), pos.z());
		}
If i debug frame by frame and toggle draw wireframe, i can see my entity moved to the position, but the collision shape
wireframe didn't, after i step 1 frame forward, my entity get back to it's original position.
Image
marios
Posts: 52
Joined: Mon Jul 19, 2010 3:11 am
Contact:

Re: How to manually change position of dynamic object

Post by marios »

just use body->setWorldTransform() not motionstate->setWorldTransform(tf);
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: How to manually change position of dynamic object

Post by drleviathan »

I think you also need to set the body's transform inside YourMotionState::setWorldTransform(). It should look something like this:

Code: Select all

    virtual void YourMotionState::setWorldTransform(const btTransform &worldTrans)
    {
         const btQuaternion &rot = worldTrans.getRotation();
         mSceneNode ->setOrientation(rot.w(), rot.x(), rot.y(), rot.z());
         const btVector3 &pos = worldTrans.getOrigin();
         mSceneNode ->setPosition(pos.x(), pos.y(), pos.z());
         mBody->setWorldTransform(worldTrans);
    }
Note: an advantage of using a MotionState system here is that YourMotionState::setWorldTransform() can set the transform of both the mSceneNode and mBody together. If that is not useful (i.e. the mSceneNode is already in the right spot and you want to just make mBody's transform agree) then you can just call body->setWorldTransform() in that context, which is what I think marios is suggesting above but in not so many words.
peanutandchestnut
Posts: 8
Joined: Mon Feb 02, 2015 8:40 am

Re: How to manually change position of dynamic object

Post by peanutandchestnut »

marios wrote:just use body->setWorldTransform() not motionstate->setWorldTransform(tf);
Thanks marios. It shoud be done as you said. Not via motionstate.

And to drleviathan:

I don't think it's a good idea to write this code in motion state.

Code: Select all

mBody->setWorldTransform(worldTrans);
I think for dynamic object, MotionState is interpolated for render, world transform of rigid body is the actual transform, they are different.
Post Reply