Problem with MotionState / setWorldTransform

Fdot
Posts: 6
Joined: Wed Sep 29, 2010 8:02 am

Problem with MotionState / setWorldTransform

Post by Fdot »

Hi,

I have a really weird problem with the motion state. When I run the program everything is fine. I can drive thru the world. But if I stay for a while (few seconds) setWorldTransform isn't called by bullet and I cannot move anymore. I have no clue what to do...

Here is the code:

Code: Select all

    void BodyHandler::AddPhysicsBody(std::string strObjectID, bool bolStatic)
    {
        Ogre::SceneNode* ptrSceneNode = Scenegraph::GetSingleton().GetSceneNode(strObjectID);
        Ogre::Entity* mEntity = Scenegraph::GetSingleton().GetEntity(strObjectID);

        BtOgre::StaticMeshToShapeConverter converter(mEntity);
        btCollisionShape* ptrShape;
        btScalar mass;

        /*
         * Static RigidBody - doesn't move
         */
        if(bolStatic)
        {
            //ptrShape = converter.createTrimesh();
            //ptrShape = converter.createBox();
            ptrShape = converter.createSphere();
            mass = 0;
        }

        /*
         * Dynamic Body
         */
        else
        {
            ptrShape = converter.createConvex();
            //ptrShape = converter.createSphere();
            mass = 100;
        }

        btVector3 inertia;
        ptrShape->calculateLocalInertia(mass, inertia);

        BtOgre::RigidBodyState *state = new BtOgre::RigidBodyState(ptrSceneNode);

        btRigidBody* mBody = new btRigidBody(mass, state, ptrShape, inertia);


        mBody->setInvInertiaDiagLocal(btVector3(0,0,0));
        mBody->updateInertiaTensor();

        mapBodies[ ptrSceneNode->getName() ] = mBody;
        PhysicsController::GetSingleton().GetPhysicsWorld()->addRigidBody(mBody);
    }

    void BodyHandler::DeletePhysicsBody(std::string strMesh)
    {
        delete mapBodies[strMesh]->getMotionState();
        delete mapBodies[strMesh];

        mapBodies.erase(strMesh);
    }

    void BodyHandler::Slow()
    {
        mapSpeed :: const_iterator iter;
        for(iter = mapFrontVector.begin(); iter != mapFrontVector.end(); iter++)
        {
            if(iter->second > 0)
            {
                mapFrontVector[ iter->first ] -= 400;
                BodyHandler::GetSingleton().Move(iter->first, true);
            }
            else if(iter->second < 0)
            {
                mapFrontVector[ iter->first ] += 400;
                BodyHandler::GetSingleton().Move(iter->first, false);
            }
            else
            {
                //mapFrontVector.erase(iter);
            }
        }
    }

    void BodyHandler::Move(std::string strObjectID, bool bolForward)
    {
        Ogre::SceneNode *SceneNode = Scenegraph::GetSingleton().GetSceneNode(strObjectID);
        Ogre::Vector3 vec3Force;

        if(bolForward)
        {
            mapFrontVector[ strObjectID ] += 200;
            if(mapFrontVector[ strObjectID ] > 5000)
                mapFrontVector[ strObjectID ] = 5000;
            vec3Force = SceneNode->getOrientation () * (mapFrontVector[ strObjectID ] * Ogre::Vector3::UNIT_Z);
        }
        else
        {
            mapFrontVector[ strObjectID ] -= 200;
            if(mapFrontVector[ strObjectID ] < -5000)
                mapFrontVector[ strObjectID ] = -5000;
            vec3Force = SceneNode->getOrientation () * (mapFrontVector[ strObjectID ] * Ogre::Vector3::UNIT_Z);
        }

        mapBodies[strObjectID]->setLinearVelocity(btVector3(vec3Force.x, vec3Force.y, vec3Force.z));
    }

    void BodyHandler::Yaw(std::string strObjectID, double dblAngle)
    {
        if(mapFrontVector[ strObjectID ] < 0)
            dblAngle = -dblAngle;

        btMatrix3x3 orn = mapBodies[strObjectID]->getWorldTransform().getBasis();
        orn *= btMatrix3x3(btQuaternion(btVector3(0,1,0),dblAngle));
        mapBodies[strObjectID]->getWorldTransform ().setBasis(orn);
    }

    void BodyHandler::MoveToPosition(std::string strObjectID, btVector3 vec3Position)
    {
        btTransform transform;
        transform.setOrigin(vec3Position);
        transform.setRotation(btQuaternion(btVector3(0.0,0.0,1.0),0));

        mapBodies[strObjectID]->setWorldTransform(transform);
    }

}
I'm using a dynamic character (the others are static). I use Ogre3D and a little OgreBullet Wrapper:
http://www.ogre3d.org/forums/viewtopic.php?f=5&t=46856
Kanttori
Posts: 38
Joined: Thu Jul 08, 2010 12:52 am

Re: Problem with MotionState / setWorldTransform

Post by Kanttori »

It seems like your object is falling a sleep and needs more than just a setLinearVelocity to wake up. You could try adding

Code: Select all

if(!mapBodies[strObjectID]->isActive()) mapBodies[strObjectID]->activate();
to where you call the setLinearVelocity
Fdot
Posts: 6
Joined: Wed Sep 29, 2010 8:02 am

Re: Problem with MotionState / setWorldTransform

Post by Fdot »

Thanks!

But isn't that a bug in the library? I mean bullet says, that they update the position if a object moves... However it works now :):)