I want to use Bullet in my game project.
The first thing i did was implementing the HelloWorld code in some function which is
often called (Quick n' dirty, just to test). This worked out pretty good for a "hack".
Next thing was of course implementing the complete necessary code in the engine
(I'm using OGRE3D for graphics). I've set up everything and I'm calling stepSimulation
after every frame (I had some output code, so the handler function is called). But
the function seems to do nothing at all. Via output I could see, that Bullet once
retrieves the position and rotation of new objects (getWorldTransform) but never
calls "setWorldTransform". I've also recently tried using btDefaultMotionState and
setting the new positions in a loop, but stepSimulation does nothing. So, after
trying about 4 days getting this to work, I have no clue what to do to get it to
work :/
Here are the code chunks that are doing something with Bullet:
Code: Select all
/ ProjektilMotionState.h - My custom MotionState
#ifndef _PROJEKTIL_MOTION_STATE_H_
#define _PROJEKTIL_MOTION_STATE_H_
class ProjektilMotionState : public btMotionState {
protected:
ork_object *mObj;
//Ogre::SceneNode *mNode;
public:
btTransform mPos;
ProjektilMotionState (const btTransform &initpos, ork_object *obj);
virtual ~ProjektilMotionState ();
void setObject (ork_object *newobj);
//void setPosition (float x, float y, float z);
virtual void getWorldTransform (btTransform &worldTrans) const;
virtual void setWorldTransform (const btTransform &worldTrans);
};
#endif // _PROJEKTIL_MOTION_STATE_H_
// ProjektilMotionState.cpp
#include <kaym_common.h>
ProjektilMotionState::ProjektilMotionState (const btTransform &initpos, ork_object *obj) {
mPos = initpos;
mObj = obj;
DBG ("Neue ProjektilMotionState Instanz");
}
ProjektilMotionState::~ProjektilMotionState () {
}
void ProjektilMotionState::setObject (ork_object *newobj) {
mObj = newobj;
}
void ProjektilMotionState::getWorldTransform (btTransform &worldTrans) const {
DBG ("ProjektilMotionState::getWorldTransform");
worldTrans = mPos;
}
void ProjektilMotionState::setWorldTransform (const btTransform &worldTrans) {
if (!mObj || !mObj->node)
return;
DBG ("ProjektilMotionState::setWorldTransform");
btQuaternion rot = worldTrans.getRotation ();
mObj->node->setOrientation(rot.w(), rot.x(), rot.y(), rot.z());
//object_rotate (mObj, rot.w (), rot.x (), rot.z (), rot.y ());
btVector3 pos = worldTrans.getOrigin ();
mObj->node->setPosition(pos.x(), pos.y(), pos.z());
//object_move (mObj, pos.x (), pos.z (), pos.y ());
}
// projektil.cpp - (De-)Inits Bullet and calls stepSimulation
#include <kaym_common.h>
/* Richtet Bullet ein
* Parameter: Ork Handle
* Rückgaben: Keine
*/
void projektil_setup (ork_t *ork) { // <- called on start up
ork->broadphase = new btDbvtBroadphase();
ork->collisionConfiguration = new btDefaultCollisionConfiguration();
ork->dispatcher = new btCollisionDispatcher(ork->collisionConfiguration);
ork->solver = new btSequentialImpulseConstraintSolver;
ork->dynamicsWorld = new btDiscreteDynamicsWorld(ork->dispatcher, ork->broadphase, ork->solver, ork->collisionConfiguration);
ork->dynamicsWorld->setGravity(btVector3(0,-10,0));
}
/* Gibt Daten von Bullet im Ork Handle wieder frei
* Parameter: Ork Handle
* Rückgaben: Keine
*/
void projektil_shutdown (ork_t *ork) {
delete ork->broadphase;
delete ork->collisionConfiguration;;
delete ork->dispatcher;
delete ork->solver;
delete ork->dynamicsWorld;
}
/* Berechnet den nächsten Physik Schritt und setzt die Objekte entsprechend
* Parameter: Ork Handle, FrameEvent (von OGRE)
* Rückgaben: Keine
*/
void projektil_update_handler (int eventid, ork_t *ork, const Ogre::FrameEvent *evt, void *user_data) {
float hz = ((float)evt->timeSinceLastFrame) ? 1.0f / (float)evt->timeSinceLastFrame : 1.0f;
//DBG ("projektil_update_handler, %fHz", hz);
ork->dynamicsWorld->stepSimulation (1.0f/hz);
/* Other things I tried: (No change)
//DBG ("projektil_update_handler, %fHz", hz);
//ork->dynamicsWorld->stepSimulation ((btScalar)evt->timeSinceLastFrame, 10); //(hz);
//ork->dynamicsWorld->stepSimulation (0.01f, 20);
ork->dynamicsWorld->stepSimulation (1/60.f, 10);
*/
}
// I use this function to add a rigidBody (Planes or Boxes)
void primitive_setup_physics (ork_primitive *ret, btVector3 pos, btQuaternion rot, btVector3 size, btScalar mass, btVector3 inertia) {
INFO("Richte Physik ein für ein OrkPrimitive. type = %i Pos(%f %f %f) Size(%f %f %f) Inertia(%f %f %f) State: %p",
ret->type, pos.getX(), pos.getY(), pos.getZ(), size.getX(), size.getY(), size.getZ(),
inertia.getX(), inertia.getY(), inertia.getZ(), ret->state);
if (ret->state) {
ret->world->ork->dynamicsWorld->removeRigidBody (ret->rigidBody);
ret->state->~ProjektilMotionState ();
delete ret->state;
ret->rigidBody->~btRigidBody ();
delete ret->rigidBody;
}
//printf ("Erstelle Physikform... ");
switch (ret->type) {
case TYPE_BOX:
// printf ("TYPE_BOX ");
ret->shape = new btBoxShape (size);
break;
case TYPE_PLANE:
// printf ("TYPE_PLANE ");
ret->shape = new btStaticPlaneShape (size, 1); // Wofür ist die 1 ?
break;
default:
FAIL("Unbekannter OrkPrimitive Typ: %i", ret->type);
break;
}
//printf ("OK\n");
ret->mass = mass;
ret->inertia.x = (float)inertia.getX();
ret->inertia.y = (float)inertia.getY();
ret->inertia.z = (float)inertia.getZ();
ret->state = new ProjektilMotionState (btTransform(rot, pos), (ork_object*)ret);
ret->shape->calculateLocalInertia (mass, inertia);
btRigidBody::btRigidBodyConstructionInfo BodyCI (mass, ret->state, ret->shape, inertia);
ret->rigidBody = new btRigidBody (BodyCI);
ret->world->ork->dynamicsWorld->addRigidBody (ret->rigidBody);
//printf ("OK\n");
}
1. In my code the Z-axis is the one pointing up ("Internal" functions are using the "Y-Axis is upwards" scheme though)
2. ork_t is a structure that holds all the data used by the engines. ork_object is a structure that
holds data about a single object.
3. I don't like C++, so I'm using C function names (Have to add extern "C"), so I can code a game in plain C.
4. The obvious one: I hope i didn't forgot any important code part. When you need more info about something, please ask
rather than ignoring my post ...
Here are the ork_t and ork_object Structures:
Code: Select all
#define ORK_OBJECT_HEADER const ork_object_header *header; \
ork_world *world; \
bool linked; \
Ogre::SceneNode *node; \
Ogre::MeshPtr mesh; \
Ogre::Entity *entity; \
btCollisionShape *shape; \
btDefaultMotionState *state; \
btRigidBody *rigidBody;
/* The ork_object struct is reimplemented by any displayable object
* Its used so that one can use the "standard functions" (like object_move, _rotate, ...)
* on any graphical object. The only thing any of these structures shares
* is the ORK_OBJECT_HEADER
*/
typedef struct struct_ork_object {
ORK_OBJECT_HEADER
} ork_object;
// The OrkPrimitive struct is one of these graphical objects
typedef struct {
ORK_OBJECT_HEADER
int type;
vec3 pos;
vec3 rot;
vec3 scale;
vec3 inertia;
btScalar mass;
bool visible;
} ork_primitive;
typedef struct struct_ork_t {
/// Ork.World
ork_world *world;
/// OGRE
Root *mRoot;
RenderWindow *mWindow;
OrkFrameListener *mFrameListener;
/// Bullet
btBroadphaseInterface *broadphase;
btDefaultCollisionConfiguration *collisionConfiguration;
btCollisionDispatcher *dispatcher;
btSequentialImpulseConstraintSolver *solver;
btDiscreteDynamicsWorld *dynamicsWorld;
/// Python
pyork_t *py;
/// LibLen
len_handle_t *events;
} ork_t;
// My 3D vector
typedef struct {
float x;
float y;
float z;
} vec3;

Thanks in advance
