Switching Rigid Body to a Kinematic At Runtime user control

User avatar
Garibalde
Posts: 44
Joined: Fri Dec 18, 2009 6:06 pm
Location: Montreal

Switching Rigid Body to a Kinematic At Runtime user control

Post by Garibalde »

Hi

I am new to bullet. Have a bunch of objects in the simulation (using Ogre) that needs to collide with each other.
I will take control of one of these objects and drive it via Mouse and keyboard and make them collide with other
objects in the simulation. I can then change the selected object to another one in the scene at runtime by pressing
a keyboard key ("space").

I ahve all the objects loaded in the simulation the start in the air and fall to the ground. I see the effect of collision between the floor and the objects. Also between two objects on the fall (There is no user control activated here yet). Below is the code i use to setup the rigid body objects.

Code: Select all

_cprintf("-> Creating Physics model %s.\n",(*p)->ObjectName.c_str());
BtOgre::StaticMeshToShapeConverter converter(MyEntity);
(*p)->mObjShape = converter.createBox();
(*p)->mObjShape->setLocalScaling(btVector3((*p)->AxisScaling[0],(*p)->AxisScaling[1],(*p)->AxisScaling[2]));

//Calculate inertia.
btScalar mass = 2;
btVector3 inertia;
(*p)->mObjShape->calculateLocalInertia(mass, inertia);

//Create BtOgre MotionState (connects Ogre and Bullet).
(*p)->mObjState = new BtOgre::RigidBodyState((*p)->mObjNode);
The at runtime when the object is switched i dot he following. I get the object RigidBodyState and apply the following:

Code: Select all

ActiveToolName = ObjArray.GetObjectFromList(ActiveToolToggle);
ObjectPtr ObjData = ObjArray.GetObjectPtrGivenIndx(ActiveToolToggle);
ObjData->mObjBody->setCollisionFlags(ObjData->mObjBody->getCollisionFlags() | CollisionObject::CF_KINEMATIC_OBJECT);
When i move the keyboard and Mouse i collect the information and set the following Where cpos and Ori are the current position and orientation of the object controlled by the user.

Code: Select all

ObjData->mObjBody->setWorldTransform(btTransform(btQuaternion(Ori.x,Ori.y,Ori.z,Ori.w),btVector3(cPos.x,cPos.y,cPos.z)));
Therefore here is the QUESTION:
It seems that the controlled pobject does not collide with the other objects in the scene and cause any physic effects. They just passthrough them!!! What am i doing wrong to enable a CONTROLLED object that can create physics effects at runtime with other righidbodies in the Simulation.

Here are two pictures i captures from the debugdrawer in bullet/Ogre.

The first picture shows the initial configuration of the sim.
image2.jpg
The second picture shows after i have moved the selected objects they are now in collision with each other there should be physics motion of the other objects the ball and the pick.
image1.jpg
Any help you can provide woult be greatful. am lost i just need a hint of sorts to proceed. A example code would be great.

Garibalde
You do not have the required permissions to view the files attached to this post.
User avatar
Garibalde
Posts: 44
Joined: Fri Dec 18, 2009 6:06 pm
Location: Montreal

[Solved] Switch Rigid Body to Kinematics At Runtime

Post by Garibalde »

From what i have read on the news groups etc. it seems that switching an object to kinematics will provide
collision with other rigid bodies in the simulation. However you will have to manually calculate the effect of
the collision on the kinematic body. This is what i am interested in.

However i just tried to activate the motion of the user controlled body with the use of forces and torques
This seems to work fine. But i dont want the dynamic side effects of damping, friction, interia and etc for
the controlled body. Please post it.

Here is the working code for the force/torque application. It maybe usefull for someone else looking at this
type of solution. If anyone have example code for switching an object to Kinematics and still having collision
on other rigid bodies in the simulation.

Code: Select all

Ogre::Vector3 UserForce = mDirection * 2;
Ogre::Vector3 UserTorque = mRotateval * 15;
mToolBody->setActivationState(DISABLE_DEACTIVATION);
mToolBody->applyForce(btVector3(UserForce.x,UserForce.y,UserForce.z),btVector3(0,0,0));
mToolBody->applyTorque(btVector3(UserTorque.x,UserTorque.y,UserTorque.z));
mToolState->setWorldTransform(mToolBody->getWorldTransform());
Thanks
Garibalde
Last edited by Garibalde on Sat Feb 06, 2010 5:23 pm, edited 1 time in total.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Switching Rigid Body to a Kinematic At Runtime user control

Post by Erwin Coumans »

The at runtime when the object is switched i dot he following
If you want to change important data from objects, you have to remove them from the world first, then make the change, and re-add them to the world.

Hope this helps,
Erwin
User avatar
Garibalde
Posts: 44
Joined: Fri Dec 18, 2009 6:06 pm
Location: Montreal

Re: Switching Rigid Body to a Kinematic At Runtime user control

Post by Garibalde »

I have tried it i cant seem to get the bounding box to follow the motion of the object.
I am trying to convert the object into a kinematic object and then move it via user
input. I still what collisions to occur between the kinematic object and other rigid objects.

Can you possibly post some source code how its done.. I have tried many variations and
nothing so far moves the BBox and the Object in sync.

Thanks
Garibalde
User avatar
Garibalde
Posts: 44
Joined: Fri Dec 18, 2009 6:06 pm
Location: Montreal

Re: Switching Rigid Body to a Kinematic At Runtime user control

Post by Garibalde »

Ok i experimented a bit, I am completely lost.... Help!!

I have the following code:

Code: Select all

mToolBody->setCollisionFlags(mToolBody->getCollisionFlags()|btCollisionObject::CF_KINEMATIC_OBJECT);
mToolBody->setActivationState(DISABLE_DEACTIVATION);
Ogre::Vector3 cPos = mToolNode->getPosition() + (mDirection * 0.1);
Ogre::Vector3 tmp = mRotateval * 0.05;
Ogre::Quaternion dOri(tmp.x,tmp.y,tmp.z);
Ogre::Quaternion cOri = mToolNode->getOrientation() + dOri;
Globals::phyWorld->removeRigidBody(mToolBody);
btTransform btt;
mToolBody->getMotionState()->getWorldTransform(btt);
btt.setOrigin(BtOgre::Convert::toBullet(cPos));
btt.setRotation(BtOgre::Convert::toBullet(cOri));
mToolBody->getMotionState()->setWorldTransform(btt);
mToolBody->setCenterOfMassTransform(btt);
Globals::phyWorld->addRigidBody(mToolBody);
mToolBody->activate(true);
The above works (partially) to what i want. The user controlled Object (mToolBody) is kinematic and follows the users inputs. However i do not have an Dynamics collision between
other rigid bodies in the scene.

if i comment out this line in the code above.

Code: Select all

//mToolBody->setCollisionFlags(mToolBody->getCollisionFlags()|btCollisionObject::CF_KINEMATIC_OBJECT);
The user controlled object is tracked, however i get all the dynamics effects such as inertia, damping and collision reaction on the object which makes control of the object difficult.

It seems that when i use kinematics there is no way to have collision between other rigid bodies in the scene. Is this a Limitation of Bullet? or am i missing something. I remember reading in a another thread that it was possible for Kinematic objects to collide with other
rigid bodies in the scene, but there will be no effect of the reaction, gravity etc on the kinematic object. This is exactly what i want.

Is there another way to achieve what i am looking for??

Can someone help me please...
Garibalde.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Switching Rigid Body to a Kinematic At Runtime user control

Post by Erwin Coumans »

Make sure the (inverse) mass is zero, if the object is static or kinematic, and mass is positive for dynamic objects. Change the mass (inverse mass) and collision flags (etc) while the object is not in the world.

Note that removing and re-adding to the world can be slow, if it happens many times per frame. Use the btDbvtBroadphase instead of btAxisSweep3 to increase performance of adding/removing to the world.

Hope this helps,
Erwin
User avatar
Garibalde
Posts: 44
Joined: Fri Dec 18, 2009 6:06 pm
Location: Montreal

Re: Switching Rigid Body to a Kinematic At Runtime user control

Post by Garibalde »

Can you possibly post a small sample code on how to achieve this, please. How do you set the inverse mass to zero? using the setmassProps()? All objects currently in the scene have a mass of 2.0 by default including the element i am switching to kinematics. I moved the setcollisonflags() and also used SetMassProps(0.0, btVector3(0,0,0)) after i have done removeRigidBody and before i added it back into the Environment. There was no effect still!! :(

Edit: I just checked via debug that the m_inversemass member is 0.0 at runtime when i am in the loop for the updating the kinematic object position/orientation.

The code below returns a value of 3 which is not one of the defined values in enum CollisionFlags??

Code: Select all

mToolBody->getCollisionFlags();
The BBox still does not follow the motion of the kinematic object when i use debugdrawer to view it.

Here is the current code:

Code: Select all

Ogre::Vector3 cPos = mToolNode->getPosition() + (mDirection * 0.1);
Ogre::Vector3 tmp = mRotateval * 0.05;
Ogre::Quaternion dOri(tmp.x,tmp.y,tmp.z);
Ogre::Quaternion cOri = mToolNode->getOrientation() + dOri;
Globals::phyWorld->removeRigidBody(mToolBody);
mToolBody->setCollisionFlags(mToolBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
mToolBody->setActivationState(DISABLE_DEACTIVATION);
btTransform btt;
mToolBody->getMotionState()->getWorldTransform(btt);
btt.setOrigin(BtOgre::Convert::toBullet(cPos));
btt.setRotation(BtOgre::Convert::toBullet(cOri));
mToolBody->getMotionState()->setWorldTransform(btt);
mToolBody->setCenterOfMassTransform(btt);
Globals::phyWorld->addRigidBody(mToolBody);
mToolBody->activate(true);
Here is the screenshot of the BBox and the object offset after a user input motion.
test1.jpg
Thanks
Garibalde
You do not have the required permissions to view the files attached to this post.
User avatar
Garibalde
Posts: 44
Joined: Fri Dec 18, 2009 6:06 pm
Location: Montreal

Re: Switching Rigid Body to a Kinematic At Runtime user control

Post by Garibalde »

anyone help? please.
User avatar
Garibalde
Posts: 44
Joined: Fri Dec 18, 2009 6:06 pm
Location: Montreal

[Solved] Switch Rigid Body to a Kinematic At Runtime user cn

Post by Garibalde »

I solved the problem.. i am not sure how.. but the following code works.

Code: Select all

btTransform btt;
Globals::phyWorld->removeRigidBody(mToolBody);
mToolBody->setMassProps(0, btVector3(0,0,0));
mToolBody->setCollisionFlags(mToolBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
btt.setIdentity();
btt.setOrigin(BtOgre::Convert::toBullet(cPos));
btt.setRotation(BtOgre::Convert::toBullet(Ori));
mToolBody->getMotionState()->setWorldTransform(btt);
mToolBody->setActivationState(DISABLE_DEACTIVATION);
Globals::phyWorld->addRigidBody(mToolBody);
Garibalde
User avatar
Garibalde
Posts: 44
Joined: Fri Dec 18, 2009 6:06 pm
Location: Montreal

Re: Switching Rigid Body to a Kinematic At Runtime user cont

Post by Garibalde »

Hi

I am adding to this thread to be able to switch an object from kinematic to dynamic. I can switch an object from Dynamic to kinematic without any problems.

The switch from dynamic is done below:

Code: Select all

btTransform btt;
Globals::phyWorld->removeRigidBody(mObjBody);
mObjBody->setMassProps(0, btVector3(0,0,0));
ObjBody->setCollisionFlags(mObjBody->getCollisionFlags() |  btCollisionObject::CF_KINEMATIC_OBJECT);
mObjBody->setActivationState(DISABLE_DEACTIVATION);
Globals::phyWorld->addRigidBody(mObjBody);
I update the object this way (currently I am only translating the object in kinematic mode)

Code: Select all

btVector3 vNewPos = MyNewPosition;
btTransform btt;
Globals::phyWorld->removeRigidBody(mObjBody);
btt.setIdentity();
mObjBody->getMotionState()->getWorldTransform(btt);
btQuaternion cOri = btt.getRotation();
btt.setOrigin(vNewPos);
btt.setRotation(cOri);
mObjBody->getMotionState()->setWorldTransform(btt);
Globals::phyWorld->addRigidBody(mObjBody);
I am trying to switch the object back to dynamic from kinematic. I set the object mass non-zero as per the
following code and recalculate the inertia and addrigidbody again to the scene.

Code: Select all

Globals::phyWorld->removeRigidBody(mObjBody);
btVector3 inertia(0,0,0);
mObjShape->calculateLocalInertia(DynData.Mass, inertia);
mObjBody->setActivationState(DISABLE_DEACTIVATION);
mObjBody->setMassProps(DynData.Mass, inertia);
mObjBody->updateInertiaTensor();
Globals::phyWorld->addRigidBody(mObjBody);
My problem is this does not work. The object still floats in space where it was last placed in kinematic mode.
Can someone help me with the problem. What am i doing wrong here?

Thanks
User avatar
Garibalde
Posts: 44
Joined: Fri Dec 18, 2009 6:06 pm
Location: Montreal

Re: Switching Rigid Body to a Kinematic At Runtime user cont

Post by Garibalde »

I changed the function when converting from kinematics to Dynamics
i set the collisionflags to CF_STATIC_OBJECT

Code: Select all

Globals::phyWorld->removeRigidBody(mObjBody);
btVector3 inertia(0,0,0);
mObjShape->calculateLocalInertia(DynData.Mass, inertia);
mObjBody->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
mObjBody->setMassProps(DynData.Mass, inertia);
mObjBody->updateInertiaTensor();
Globals::phyWorld->addRigidBody(mObjBody);
Everything seems to work now.

Hope this helps someone else.
User avatar
Garibalde
Posts: 44
Joined: Fri Dec 18, 2009 6:06 pm
Location: Montreal

Re: Switching Rigid Body to a Kinematic At Runtime user cont

Post by Garibalde »

Its seems that object i switch to kniematics and returned to dynamics do not go to sleep EVER!!!
Before i touch the object (I.e switch the object tends to sleep and activate when forced).

to convert the objects to kinematic i do the following:

Code: Select all

Globals::phyWorld->removeRigidBody(Obj->BodyRigid);
Obj->BodyRigid->setMassProps(0, btVector3(0,0,0));
Obj->BodyRigid->setCollisionFlags(Obj->BodyRigid->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT | btCollisionObject::CF_NO_CONTACT_RESPONSE);
Obj->BodyRigid->setLinearVelocity(btVector3(0,0,0));
Obj->BodyRigid->setAngularVelocity(btVector3(0,0,0));
Obj->BodyRigid->setActivationState(DISABLE_DEACTIVATION);
Globals::phyWorld->addRigidBody(Obj->BodyRigid);
to switch the object back to dyn from kinematics i do this:

Code: Select all

Globals::phySoftWorld->removeRigidBody(Obj->BodyRigid);
btVector3 inertia(0,0,0);
Obj->BodyShape->calculateLocalInertia(Obj->Behavior.ObjTraits->Mass, inertia);
Obj->BodyRigid->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
Obj->BodyRigid->setMassProps(Obj->Behavior.ObjTraits->Mass, inertia);
Obj->BodyRigid->updateInertiaTensor();
Obj->BodyRigid->setLinearVelocity(btVector3(0,0,0));
Obj->BodyRigid->setAngularVelocity(btVector3(0,0,0));
Obj->BodyRigid->setActivationState(WANTS_DEACTIVATION);
Globals::phySoftWorld->addRigidBody(Obj->BodyRigid);
Once the object is switched back it never sleeps nor does any body that is making contact with it, which is logical i guess. Why does my body returned with dynamic properties does not go to sleep. I believe its with the setactivationstate command.. i have tried several combinations and nothings seems to make it work. I switch it to DISABLE_DEACTIVATION for me to move it in kinematics mode. Otherwise i cant move the object.
When i return to dynamics i set it to WANTS_DEACTIVATION so that it can go to sleep when conditions are satisfied.

When the object is in kinematics i move it around with the keyboard. So i need interaction with the object while it is in kinematic mode.

Thanks for any help.
User avatar
Garibalde
Posts: 44
Joined: Fri Dec 18, 2009 6:06 pm
Location: Montreal

[Solved] Switching Rigid Body to a Kin At Runtime user contr

Post by Garibalde »

Seems that the objects shake because because they never sleep.
The option of setting DISABLE_DEACTIVATION when setting it to kinematics cause the object never to sleep
when reactivated. This cause drift over time due to small forces/moments possibly from numerical stability?

Well its solved now. I use a force method to move the object with converting them to kinematics and also
fixed the kinematics with the use of DISABLE_DEACTIVATION. When objects are returned to Dynamics they
do fall asleep.

Hope this helps someone else. Spend quite sometime on this one.