Physics Simulation Forum

 

All times are UTC




Post new topic Reply to topic  [ 3 posts ] 
Author Message
PostPosted: Sat Nov 14, 2009 4:02 pm 
Offline

Joined: Sat Nov 14, 2009 3:52 pm
Posts: 2
I'm trying to manually place a dynamic rigid body using setWorldTransform, but I'm running into some snags. I'm setting a new transform between simulation steps, but my "changes" seem to be overwritten/ignored on subsequent steps.

Here's a program demonstrating my problem (output follows):

Code:
#include <iostream>

#include "btBulletDynamicsCommon.h"

struct MyMotionState : public btMotionState
{
    MyMotionState(const btTransform& transform)
        : mTransform(transform)
    {
    }

    virtual void getWorldTransform(btTransform& returnTransform) const
    {
        std::cout << "getWorldTransform called... Y: " << mTransform.getOrigin().getY() << std::endl;
        returnTransform = mTransform;
    }

    virtual void setWorldTransform(const btTransform& newTransform)
    {
        std::cout << "setWorldTransform called... Y: " << newTransform.getOrigin().getY() << std::endl;

        mTransform = newTransform;
    }

    btTransform mTransform;
};

const float DEFAULT_X = 0.0f;
const float DEFAULT_Y = 10.0f;
const float DEFAULT_Z = 0.0f;

const float RADIUS = 5.0f;
const float MASS   = 5.0f;

const float SIM_DELAY = 10.0f;
const int SLEEP_DELAY = 1000; // ms

int main()
{
    btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
    btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);

    btBroadphaseInterface* broadphase = new btDbvtBroadphase;
    btConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
    btDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);


    btTransform startTransform;
    startTransform.setIdentity();
    startTransform.setOrigin(btVector3(DEFAULT_X, DEFAULT_Y, DEFAULT_Z));
    btCollisionShape* fallShape = new btSphereShape(RADIUS);

    MyMotionState* motionState = new MyMotionState(startTransform);

    btVector3 fallInertia(0,0,0);
    fallShape->calculateLocalInertia(MASS, fallInertia);

    btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(MASS, motionState, fallShape, fallInertia);
    btRigidBody* rigidBody = new btRigidBody(fallRigidBodyCI);

    dynamicsWorld->addRigidBody(rigidBody);

   
    for (int frameCount = 1; ; ++frameCount)
    {
        dynamicsWorld->stepSimulation(SIM_DELAY);

        btTransform btt;
        rigidBody->getMotionState()->getWorldTransform(btt);
        std::cout << "Frame stepped.... Actual Y position: " << btt.getOrigin().getY() << std::endl;

        if (frameCount % 3 == 0) // every few frames, try to reset rigidbody's MotionState
        {
            std::cout << "Resetting position..." << std::endl;
            btTransform bttReset;
            bttReset.setIdentity();
            bttReset.setOrigin(btVector3(DEFAULT_X, DEFAULT_Y, DEFAULT_Z));
            rigidBody->getMotionState()->setWorldTransform(bttReset);
        }

        Sleep(SLEEP_DELAY);
    }
   
}


And here's the ouput:

Code:
getWorldTransform called... Y: 9.98611
Frame stepped.... Actual Y position: 9.98611
setWorldTransform called... Y: 9.975
getWorldTransform called... Y: 9.975
Frame stepped.... Actual Y position: 9.975
Resetting position...
setWorldTransform called... Y: 10
setWorldTransform called... Y: 9.96111
getWorldTransform called... Y: 9.96111
Frame stepped.... Actual Y position: 9.96111
setWorldTransform called... Y: 9.94445
getWorldTransform called... Y: 9.94445
Frame stepped.... Actual Y position: 9.94445
setWorldTransform called... Y: 9.92501
getWorldTransform called... Y: 9.92501
Frame stepped.... Actual Y position: 9.92501
Resetting position...
setWorldTransform called... Y: 10
setWorldTransform called... Y: 9.90279
getWorldTransform called... Y: 9.90279
Frame stepped.... Actual Y position: 9.90279
setWorldTransform called... Y: 9.87779
getWorldTransform called... Y: 9.87779
Frame stepped.... Actual Y position: 9.87779
...


I've run a similar simulation using a falling dynamic rigid body in which the body lands and bounces on a static rigid body. If I let the simulation run long enough for the dynamic body to come to a rest, I can set the transform and it holds between frames. Unfortunately, once I can do this, stepping the simulation doesn't affect the transform anymore. Is it possible to "restart" the simulation at that point so that further calls to stepSimulation affect the repositioned dynamic rigid body?


Top
 Profile  
 
PostPosted: Sat Nov 14, 2009 6:11 pm 
Offline

Joined: Fri Oct 30, 2009 7:44 pm
Posts: 11
This bit works for me:
Code:
rigidBody->getWorldTransform().setIdentity();
rigidBody->getWorldTransform().setOrigin(btVector3(DEFAULT_X, DEFAULT_Y, DEFAULT_Z));

instead of your
Code:
btTransform bttReset;
bttReset.setIdentity();
bttReset.setOrigin(btVector3(DEFAULT_X, DEFAULT_Y, DEFAULT_Z));
rigidBody->getMotionState()->setWorldTransform(bttReset);

But keep in mind that the velocity is not affected by this, so it will continue to grow faster and the object will fall further and further by the next step.

Once the object stops it gets set to a sleeping state, you can wake it up with
Code:
rigidBody->activate(true);


Top
 Profile  
 
PostPosted: Sat Nov 14, 2009 6:59 pm 
Offline

Joined: Sat Nov 14, 2009 3:52 pm
Posts: 2
Thanks Jasonrun! You've cleared up all of my concerns. I really appreciate it!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC


Who is online

Users browsing this forum: Exabot [Bot], Google [Bot], xexuxjy and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group