Problem using Irrlicht with ODE
Problem using Irrlicht with ODE
I´ve set up a test application using the ODE-Integration tutorial.
I use a ms3d file for my terrain and create some cube that should bounce around when falling on the terrain, but some of them are just falling through...
Another thing is that my cubes are only bouncing when i use dWorldStepFast and not dWorldStep. With dWorldStep my cubes just fall down and dont bounce.
Has anyone successfully integrated ode in his project ?
I use a ms3d file for my terrain and create some cube that should bounce around when falling on the terrain, but some of them are just falling through...
Another thing is that my cubes are only bouncing when i use dWorldStepFast and not dWorldStep. With dWorldStep my cubes just fall down and dont bounce.
Has anyone successfully integrated ode in his project ?
Hi, nice screenshot,
how many boxes are stacked? how much FPS does it render?
just curious
I build ODE in the command shell using the make file, that is, i don't use VC++ IDE. Ihis is what I changed to make it run with irrlicht:
my user settings
You need to precompile OPCODE and copy the lib into the OPCODE directory
This should let You build the ODE libs. Just do this in a command prompt (assuming You use VC++)
> cd [my_vc7_dir]\bin\
> vcvars32.bat
> cd [my_ode_dir]
> make
configure writes some error messages to the screen, just ignore them
btw. you need a compatible make.exe, I think You can dl from www.ode.org somewhere on the page.
I hope this help
how many boxes are stacked? how much FPS does it render?
just curious
I build ODE in the command shell using the make file, that is, i don't use VC++ IDE. Ihis is what I changed to make it run with irrlicht:
Code: Select all
Add the following to the Makefile in config directory
ifeq ($(BUILD),release)
OPT=2
C_FLAGS+=/Oy /MD
endif
ifeq ($(BUILD),debug)
C_FLAGS+=/MDd
OPT=d
endif
Code: Select all
PLATFORM=msvc
// ode needs single precision if using trimeshes! double does not work
PRECISION=SINGLE
BUILD=release
WINDOWS16=0
OPCODE_DIRECTORY=OPCODE
This should let You build the ODE libs. Just do this in a command prompt (assuming You use VC++)
> cd [my_vc7_dir]\bin\
> vcvars32.bat
> cd [my_ode_dir]
> make
configure writes some error messages to the screen, just ignore them
btw. you need a compatible make.exe, I think You can dl from www.ode.org somewhere on the page.
I hope this help
-
- Posts: 41
- Joined: Mon Feb 16, 2004 7:37 pm
have you succeeded in getting ode in combination with irrlicht to work on linux? great!!!!!
i could'nt get it to work together (irrlicht and ode do work separate) (i get an linking error when i try to compile the files from the ode tutorial)
can you publish your makefiles and libraries and source or e-mail them to me, please?
my e-mail address is hansmbakker@hotmail.com
thank you very much!
i could'nt get it to work together (irrlicht and ode do work separate) (i get an linking error when i try to compile the files from the ode tutorial)
can you publish your makefiles and libraries and source or e-mail them to me, please?
my e-mail address is hansmbakker@hotmail.com
thank you very much!
-
- Posts: 41
- Joined: Mon Feb 16, 2004 7:37 pm
Here it is...
DPhysicsManager.cpp
DPhysicsManager.h
DPhysicsBounceable.cpp
DPhysicsBounceable.h
And a interface-class
DCollisionInterface.h
Makefile.win :
Makefile.linux :
The physicsmanager is used this way :
physicsmanager = new DPhysicsManager(device);
// this adds my terrain.. i didnt clean addEntity up so there are still unnecessary parameters... have a look at the code and you'll see...
physicsmanager->addEntity(smallMap, false, false, false);
// this creates a crate at the given position
physicsmanager->CreateBounceable(smgr, core::vector3df(320,100,460));
P.S. : Big THX to Zola for helping
DPhysicsManager.cpp
Code: Select all
#include "DPhysicsManager.h"
float stepSize=0.1f;
// available simulation time
float simtime=0.0f;
unsigned long lastFrame=0;
unsigned long thisFrame=0;
dWorldID DPhysicsManager::theWorld=0;
dSpaceID DPhysicsManager::theSpace=0;
dJointGroupID DPhysicsManager::theJointGroup=0;
float inline frand(int precis=4)
{
int val=(int)pow(10,precis);
return (rand()%val)/(float)val;
}
float inline max(float a, float b)
{
return a>b?a:b;
}
DPhysicsManager::DPhysicsManager(IrrlichtDevice *device)
{
std::list<DPhysicsBounceable*> bounceables;
this->device = device;
now=device->getTimer()->getTime();
this->init();
}
DPhysicsManager::~DPhysicsManager()
{}
void DPhysicsManager::updatePhysics()
{
//updateEntitiesBeforePhysics();
//we do nothing here since there are no user controlled objects in the simulation
// build the collision joints for all objects in 'theSpace'
dSpaceCollide(theSpace,0, &nearCollisionCallback);
// make a simulation step for 'theWorld'
//dWorldQuickStep(theWorld,0.05);
//dWorldStep(theWorld,0.1f);
//optionally use dWorldStepFast1 instead of dWorldStep
//when stack overflows occure or speed is important
dWorldStepFast1(theWorld,stepSize,10);
// clean up joints from collisions;
dJointGroupEmpty(theJointGroup);
// apply the new positions and rotations to the scenenodes
updateEntitiesAfterPhysics();
}
void DPhysicsManager::init()
{
bounceables.clear();
theWorld=dWorldCreate();
theSpace=dSimpleSpaceCreate(0);
theJointGroup=dJointGroupCreate(0);
// play around with these settings
dWorldSetGravity(theWorld,0,GRAVITY,0);
dWorldSetCFM (theWorld,1e-5);
dWorldSetAutoDisableFlag (theWorld,1);
dWorldSetContactMaxCorrectingVel (theWorld,0.1);
dWorldSetContactSurfaceLayer (theWorld,0.001);
}
void DPhysicsManager::addEntity(DCollisionInterface *entity, bool box, bool test, bool updatephysics)
{
DPhysicsBounceable *tempbounce = new DPhysicsBounceable(theWorld,theSpace,0,0,entity->getSceneNode(),entity->getMesh(), updatephysics);
if(!box&&!test)
{
tempbounce->setGeomData(entity->getMesh());
//tempbounce->timetolive=0;
}
if(box&&!test)
{
tempbounce->setGeomData();
}
if(test)
{
tempbounce->setGeomDataTest();
}
bounceables.push_back(tempbounce);
}
DPhysicsBounceable* DPhysicsManager::CreateBounceable(ISceneManager* smgr, core::vector3df position)
{
ITexture* metalcube=device->getVideoDriver()->getTexture("metal2.jpg");
ISceneNode* bouncetest=NULL;
bouncetest=smgr->addTestSceneNode(20.0f,0,-1, position);
bouncetest->setMaterialTexture(0,metalcube);
DPhysicsBounceable* b=new DPhysicsBounceable(theWorld,theSpace,0,0,bouncetest,NULL, true);
b->setGeomData();
// b->timetolive=now + LIVETIME*frand();
bounceables.push_back(b);
return b;
}
void DPhysicsManager::updateEntitiesAfterPhysics(){
irr::core::vector3df pos;
irr::core::vector3df rot;
std::list<DPhysicsBounceable*>::iterator iter=NULL;
for(iter=bounceables.begin();iter!=bounceables.end();++iter){
DPhysicsBounceable* entity=(*iter);
dGeomID geom=entity->geom;
if(geom!=0){
if(entity->updatephysics)
{
// get the new position of the ODE geometry
dReal* ode_pos=(dReal*)dGeomGetPosition(geom);
// set the position at the scenenode
pos.set((irr::f32)ode_pos[0],(irr::f32)ode_pos[1],(irr::f32)ode_pos[2]);
entity->node->setPosition(pos);
// get the rotation quaternion
dQuaternion result;
dGeomGetQuaternion(geom, result);
// convert it to eulerangles
QuaternionToEuler(result,rot);
// set the rotation
entity->node->setRotation(rot);
}
}
}
}
void DPhysicsManager::nearCollisionCallback(void* data, dGeomID o1, dGeomID o2)
{
int i=0;
dBodyID b1=dGeomGetBody(o1);
dBodyID b2=dGeomGetBody(o2);
if(b1 && b2 && dAreConnectedExcluding(b1,b2,dJointTypeContact))return;
dContact contact[MAX_CONTACTS];
for(i=0;i<MAX_CONTACTS;i++){
contact[i].surface.mode =dContactBounce |
dContactSoftERP | dContactSoftCFM;
contact[i].surface.mu = dInfinity;
contact[i].surface.slip1 = 0.1; // friction
contact[i].surface.slip2 = 0.1;
contact[i].surface.bounce=0.2f;
contact[i].surface.soft_erp = 0.2f;
contact[i].surface.soft_cfm = 0.2f;
}
int numc=dCollide(o1,o2,MAX_CONTACTS,&contact[0].geom,sizeof(dContact));
if(numc>0){
/*
// do something usefull with the colliding objects
if(o1) {
Bounceable* bounce1=(Bounceable*)dGeomGetData(o1);
}
if(o2) {
Bounceable* bounce2=(Bounceable*)dGeomGetData(o2);
}
*/
for(i=0;i<numc;i++){
dJointID c = dJointCreateContact(theWorld,theJointGroup,contact+i);
dJointAttach(c,b1,b2);
}
}
}
void DPhysicsManager::QuaternionToEuler(const dQuaternion quaternion,irr::core::vector3df &euler){
dReal w,x,y,z;
w=quaternion[0];
x=quaternion[1];
y=quaternion[2];
z=quaternion[3];
double sqw = w*w;
double sqx = x*x;
double sqy = y*y;
double sqz = z*z;
// heading
euler.Z = (irr::f32) (atan2(2.0 * (x*y + z*w),(sqx - sqy - sqz + sqw))*irr::core::GRAD_PI);
// bank
euler.X = (irr::f32) (atan2(2.0 * (y*z + x*w),(-sqx - sqy + sqz + sqw))*irr::core::GRAD_PI);
// attitude
euler.Y = (irr::f32) (asin(-2.0 * (x*z - y*w))*irr::core::GRAD_PI);
}
void DPhysicsManager::EulerToQuaternion(const irr::core::vector3df &euler, dQuaternion quaternion){
double _heading=euler.Z*irr::core::GRAD_PI2/2.0;
double _attitude=euler.Y*irr::core::GRAD_PI2/2.0;
double _bank=euler.X*irr::core::GRAD_PI2/2.0;
double c1 = cos(_heading);
double s1 = sin(_heading);
double c2 = cos(_attitude);
double s2 = sin(_attitude);
double c3 = cos(_bank);
double s3 = sin(_bank);
double c1c2 = c1*c2;
double s1s2 = s1*s2;
//w
quaternion[0]=(dReal) (c1c2*c3 + s1s2*s3);
//x
quaternion[1]=(dReal) (c1c2*s3 - s1s2*c3);
//y
quaternion[2]=(dReal) (c1*s2*c3 + s1*c2*s3);
//z
quaternion[3]=(dReal) (s1*c2*c3 - c1*s2*s3);
}
Code: Select all
#ifndef DPHYSICSMANAGER_H
#define DPHYSICSMANAGER_H
#include <list>
#include <ode/ode.h>
#include <irrlicht.h>
#include "DPhysicsBounceable.h"
#include "DCollisionInterface.h"
#pragma comment(lib,"ode.lib")
#pragma comment(lib,"irrlicht.lib")
// gravitation force y-direction
#define GRAVITY -1.0f
#define QUBE_SPACING 50.0f
#define LIVETIME 5000
#define QUBE_INITHEIGHT 7000
#define QUBE_SIZE 150.0f
// maximum number of qubes in the simulation
#define MAX_QUBES 200
// maximum amount of contact joints the simulation will create for each collision
#define MAX_CONTACTS 64
class DPhysicsManager{
public:
// ODE Part
std::list<DPhysicsBounceable*> bounceables;
static dWorldID theWorld; // just one world for now
static dSpaceID theSpace; // and one space for all objects
static dJointGroupID theJointGroup; // the group to which all contact joint are added
// for mesh geometry collisions
dVector3 *vertices; // vertex array for trimesh geom
int *indices; // index array for trimesh geom
int vertexcount; // number of vertices in the vertex array
int indexcount; // number of indices in the index array
u32 timetolive;
u32 now;
DPhysicsBounceable* bounce;
core::vector3df pos;
// End of ODE Part
DPhysicsManager(IrrlichtDevice *device);
~DPhysicsManager();
void init();
void addEntity(DCollisionInterface *entity, bool box, bool test, bool updatephysics);
DPhysicsBounceable* CreateBounceable(ISceneManager* smgr, core::vector3df position);
void updatePhysics();
static void nearCollisionCallback(void* data, dGeomID o1, dGeomID o2);
void updateEntitiesAfterPhysics();
void QuaternionToEuler(const dQuaternion quaternion,irr::core::vector3df &euler);
void EulerToQuaternion(const irr::core::vector3df &euler, dQuaternion quaternion);
private:
IrrlichtDevice *device;
};
#endif
Code: Select all
#include "DPhysicsBounceable.h"
DPhysicsBounceable::DPhysicsBounceable(dWorldID w, dSpaceID s, dBodyID b, dGeomID g, ISceneNode* n, IMesh* m, bool updatephysics):world(w),space(s),body(b),geom(g),node(n),mesh(m),indexcount(0),vertexcount(0),indices(NULL),vertices(NULL), updatephysics(updatephysics)
{
}
DPhysicsBounceable::~DPhysicsBounceable()
{}
void DPhysicsBounceable::setGeomData(){
irr::core::aabbox3d<irr::f32> box=node->getBoundingBox();
irr::core::vector3df extend=box.getExtend();
irr::core::vector3df pos=node->getPosition();
geom=dCreateBox(space,(dReal)extend.X,(dReal)extend.Y,(dReal)extend.Z);
dGeomSetData(geom,(void*)this);
dGeomSetPosition(geom,pos.X,pos.Y,pos.Z);
// create a body for this object
body=dBodyCreate(world);
// set mass shape
dMassSetBox(&mass,1.0f,(dReal)extend.X,(dReal)extend.Y,(dReal)extend.Z);
// adjust mass weight
dMassAdjust(&mass,0.25);
// make the body have a mass
dBodySetMass(body,&mass);
// add the body to the geom
dGeomSetBody(geom,body);
dBodySetPosition(body,pos.X,pos.Y,pos.Z);
dBodySetData(body,(void*)this);
}
void DPhysicsBounceable::setGeomData(IMesh* m){
if(mesh==NULL || node==NULL) return; // do nothing if the mesh or node is NULL
int i,j,ci,cif,cv;
indexcount=0;
vertexcount=0;
// count vertices and indices
//for(i=0;i<m->getMeshBufferCount();i++){
IMeshBuffer* mb=mesh->getMeshBuffer(0);
indexcount+=mb->getIndexCount();
vertexcount+=mb->getVertexCount();
std::cout << indexcount << std::endl;
std::cout << vertexcount << std::endl;
//}
// build structure for ode trimesh geom
vertices=new dVector3[vertexcount];
indices=new int[indexcount];
// fill trimesh geom
ci=0;
cif=0;
cv=0;
for(i=0;i<mesh->getMeshBufferCount();i++){
irr::scene::IMeshBuffer* mb=mesh->getMeshBuffer(i);
// fill indices
irr::u16* mb_indices=mb->getIndices();
for(j=0;j<mb->getIndexCount();j++){
indices[ci]=cif+mb_indices[j];
ci++;
}
cif=cif+mb->getVertexCount();
// fill vertices
if(mb->getVertexType()==irr::video::EVT_STANDARD){
irr::video::S3DVertex* mb_vertices=(irr::video::S3DVertex*)mb->getVertices();
for(j=0;j<mb->getVertexCount();j++){
vertices[cv][0]=mb_vertices[j].Pos.X;
vertices[cv][1]=mb_vertices[j].Pos.Y;
vertices[cv][2]=mb_vertices[j].Pos.Z;
cv++;
}
}else if(mb->getVertexType()==irr::video::EVT_2TCOORDS){
std::cout << "Type : EVT_2TCOORDS" << std::endl;
irr::video::S3DVertex2TCoords* mb_vertices=(irr::video::S3DVertex2TCoords*)mb->getVertices();
for(j=0;j<mb->getVertexCount();j++){
vertices[cv][0]=mb_vertices[j].Pos.X;
vertices[cv][1]=mb_vertices[j].Pos.Y;
vertices[cv][2]=mb_vertices[j].Pos.Z;
cv++;
}
}
}
irr::core::vector3df pos=node->getPosition();
// build the trimesh data
dTriMeshDataID data=dGeomTriMeshDataCreate();
//dGeomTriMeshDataBuildSimple(data,(dReal*)vertices,vertexcount,indices,indexcount);
dGeomTriMeshDataBuildSimple(data,(dReal*)vertices,vertexcount,indices,indexcount);
// build the trimesh geom
geom=dCreateTriMesh(space,data,0,0,0);
// set the geom position
dGeomSetPosition(geom,pos.X,pos.Y,pos.Z);
// lets have a pointer to our bounceable, we could need this in the collision callback
dGeomSetData(geom,(void*)this);
// in our application we don't want geoms constructed with meshes (the terrain) to have a body
dGeomSetBody(geom,0);
}
void DPhysicsBounceable::setGeomDataTest(){
irr::core::aabbox3d<irr::f32> box=node->getBoundingBox();
irr::core::vector3df extend=box.getExtend();
irr::core::vector3df pos=node->getPosition();
geom=dCreateBox(space,(dReal)extend.X,(dReal)extend.Y,(dReal)extend.Z);
dGeomSetData(geom,(void*)this);
dGeomSetPosition(geom,pos.X,pos.Y,pos.Z);
// create a body for this object
body=dBodyCreate(world);
// set mass shape
dMassSetBox(&mass,1.0f,(dReal)extend.X,(dReal)extend.Y,(dReal)extend.Z);
// adjust mass weight
dMassAdjust(&mass,0.25);
// make the body have a mass
dBodySetMass(body,&mass);
// add the body to the geom
dGeomSetBody(geom,0);
//dBodySetPosition(body,pos.X,pos.Y,pos.Z);
//dBodySetData(body,(void*)this);
}
Code: Select all
#ifndef DPHYSICSBOUNCEABLE_H
#define DPHYSICSBOUNCEABLE_H
#include <iostream>
#include <list>
#include <ode/ode.h>
#include <irrlicht.h>
#pragma comment(lib,"ode.lib")
#pragma comment(lib,"irrlicht.lib")
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
class DPhysicsBounceable{
public:
dWorldID world; // the world to which the object will belong to
dSpaceID space; // the objects space
dBodyID body; // body data of the object
dGeomID geom; // geometry data of the object
dMass mass; // mass of the object
// for mesh geometry collisions
dVector3 *vertices; // vertex array for trimesh geom
int *indices; // index array for trimesh geom
int vertexcount; // number of vertices in the vertex array
int indexcount; // number of indices in the index array
u32 timetolive;
ISceneNode* node; // visualizing node
IMesh* mesh; // mesh of the visualizing node
DPhysicsBounceable(dWorldID w, dSpaceID s, dBodyID b, dGeomID g, ISceneNode* n, IMesh* m, bool updatephysics);
~DPhysicsBounceable();
void setGeomData();
void setGeomData(IMesh* m);
void setGeomDataTest();
bool updatephysics;
private:
};
#endif
DCollisionInterface.h
Code: Select all
#ifndef DCOLLISIONINTERFACE_H
#define DCOLLISIONINTERFACE_H
#include <irrlicht.h>
#pragma comment(lib,"irrlicht.lib")
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
class DCollisionInterface
{
public:
virtual IMesh *getMesh() = 0;
virtual ISceneNode *getSceneNode() = 0;
};
#endif
Code: Select all
CPP = g++
OPTS = -I"C:\irrlicht\include" -I"c:/MinGW/include/c++/3.2.3" -I"C:\irrlicht\source" -I"..\..\common" -I"C:\OpenAL\Include" -I"C:\ode\include"
OPTSL = -L"C:\irrlicht\bin\DevCpp" -lIrrlicht -L"C:\OpenAL\libs" -lalut -lopenal32 -L"C:\ode\lib" -lode
BINNAME = example.exe
Code: Select all
CPP = g++
CCFLAGS = -O2
OPTS = -I"../../libs/linux/irrlicht/include/" -I"/usr/X11R6/include" -I"../../libs/linux" -I"../../common/" -I"../../libs/linux/openal/include/" -I"../../libs/linux/ode/include"
OPTSL = -L"/usr/X11R6/lib" -L"../../libs/linux/irrlicht/lib/Linux/" -L"../../libs/linux/ace" -L"../../libs/linux/openal/lib" -L"../../libs/linux/ode/lib" -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lz -ljpeg -lACE -lopenal -lode
BINNAME = example
include Makefile.common
The physicsmanager is used this way :
physicsmanager = new DPhysicsManager(device);
// this adds my terrain.. i didnt clean addEntity up so there are still unnecessary parameters... have a look at the code and you'll see...
physicsmanager->addEntity(smallMap, false, false, false);
// this creates a crate at the given position
physicsmanager->CreateBounceable(smgr, core::vector3df(320,100,460));
P.S. : Big THX to Zola for helping
Last edited by erSitzt on Thu Sep 02, 2004 2:20 pm, edited 2 times in total.
I'm going insane
I just checked out ODE CVS and wanted to compile an msvc-dll.
Well, now I understand what every one is complaining about this mean s***er !@#$ ***t.
I can compile a static lib, which works ok but, it is a bit large for distributing as a dependency package for my project and I need to compile ode myself because I want to enalbe Cylinder primitives!
I just checked out ODE CVS and wanted to compile an msvc-dll.
Well, now I understand what every one is complaining about this mean s***er !@#$ ***t.
I can compile a static lib, which works ok but, it is a bit large for distributing as a dependency package for my project and I need to compile ode myself because I want to enalbe Cylinder primitives!
DBasics.h is not needed, i just forgot to remove it...
Makefile.common is all standard :
The needed code to handle physics is
physicsmanager = new DPhysicsManager(device);
physicsmanager->addEntity(CollisionInterface *entity, bool box, bool test, bool updatephysics);
box is for boundingbox collision
test was for testing purposes when i still had problems with a self-compiled version of ode... you dont need it
updatephysics was used for testing too, all objects that have updatephysics set to false wont be updated by ode during runtime.
// this creates a crate at the given position
physicsmanager->CreateBounceable(smgr, core::vector3df(320,100,460));
in your engineloop call
physicsmanager->updatePhysics();
if you still have problem post your code/errormessages
Makefile.common is all standard :
Code: Select all
%.o: %.cpp
$(CPP) $(CCFLAGS) $(OPTS) -c -o $@ $<
MODS := \
your files.o \
default: all
your files.o: your files.h
all: $(MODS) exe
exe:
$(CPP) $(CCFLAGS) -o $(BINNAME) $(MODS) $(OPTSL)
clean:
rm *.o;rm $(BINNAME)
physicsmanager = new DPhysicsManager(device);
physicsmanager->addEntity(CollisionInterface *entity, bool box, bool test, bool updatephysics);
box is for boundingbox collision
test was for testing purposes when i still had problems with a self-compiled version of ode... you dont need it
updatephysics was used for testing too, all objects that have updatephysics set to false wont be updated by ode during runtime.
// this creates a crate at the given position
physicsmanager->CreateBounceable(smgr, core::vector3df(320,100,460));
in your engineloop call
physicsmanager->updatePhysics();
if you still have problem post your code/errormessages