Page 1 of 1

How to manually change position of dynamic object

Posted: Mon Feb 02, 2015 1:58 pm
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 :?:

Re: How to manually change position of dynamic object

Posted: Wed Feb 04, 2015 3:56 pm
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.

Re: How to manually change position of dynamic object

Posted: Sun Feb 08, 2015 2:52 am
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

Re: How to manually change position of dynamic object

Posted: Sun Feb 08, 2015 3:00 pm
by marios
just use body->setWorldTransform() not motionstate->setWorldTransform(tf);

Re: How to manually change position of dynamic object

Posted: Sun Feb 08, 2015 3:27 pm
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.

Re: How to manually change position of dynamic object

Posted: Mon Feb 09, 2015 7:56 am
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.