ODE Issues

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
delark
Posts: 8
Joined: Wed Dec 03, 2008 1:38 pm

ODE Issues

Post by delark »

Hi,

I started with the wiki ode tutorial and have sort of integrated parts of an ode demo.

Initially I was trying to use 'addCubeSceneNode()' and 'addSphereSceneNode()', but I got strange behaviour.

If I alter the following code to only generate cylinders then they don't seem to collide, but work fine in an assortment.

The most annoying thing is that some nodes just hang near the generation points and never disappear.

Code: Select all

#include <iostream>
#include <string>
#include <map>
#include <time.h>

#include <irrlicht.h>
#include <ode/ode.h>

using namespace std;


using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;


#ifdef _MSC_VER

#pragma comment(lib, "Irrlicht.lib")

#endif


class node {
	public:
		dBodyID body;
		dGeomID geom;
		ISceneNode* snode;
		int life;
		node()	{	life = 0;	}
		node(std::string s)	{	life = 0;	}
};

std::map <std::string, node*> nodes;

static dWorldID world;
static dSpaceID space;
static dJointGroupID contactgroup;

dGeomID geom_ground;
irr::core::vector3df rot;

int obj_id = 0;

bool keys[irr::KEY_KEY_CODES_COUNT];

int get_rand(int from, int range)	{	return rand() % range + from;	}

void nearCallback(void* node, dGeomID o1, dGeomID o2)
{
	int i=0;
	dBodyID b1=dGeomGetBody(o1);
	dBodyID b2=dGeomGetBody(o2);
	int MAX_CONTACTS = 8;
	if(b1 && b2 && dAreConnectedExcluding(b1,b2,dJointTypeContact))return;
	dContact contact[MAX_CONTACTS];
	for(i=0;i<MAX_CONTACTS;++i)
	{
		contact[i].surface.mode=dContactBounce | dContactSoftCFM;
		contact[i].surface.mu=dInfinity;
		contact[i].surface.mu2=0;
		contact[i].surface.bounce=.1;
		contact[i].surface.bounce_vel=.1;
		contact[i].surface.soft_cfm=.01;
	}
	int numc=dCollide(o1,o2,MAX_CONTACTS,&contact[0].geom,sizeof(dContact));
	if(numc>0)
	{
		for(i=0;i<numc;i++)
		{
			dJointID c=dJointCreateContact(world,contactgroup,&contact[i]);
			dJointAttach(c,b1,b2);
		}
	}
}

void setPosition(dGeomID geom)
{
    dReal * ode_pos =(dReal*)dGeomGetPosition(geom);
    ISceneNode *node =  (ISceneNode*)dGeomGetData(geom);
    vector3df pos((irr::f32)ode_pos[0],(irr::f32)ode_pos[1],(irr::f32)ode_pos[2]);
    node->setPosition(pos);
    dQuaternion result;
    dGeomGetQuaternion(geom, result);
    irr::core::quaternion quat(result[1],result[2],result[3],result[0]);
    quat.toEuler(rot);
    vector3df degrees(rot.X*180/PI,rot.Y*180/PI,rot.Z*180/PI);
    node->setRotation(degrees);
}

void add_box(dWorldID &world,dSpaceID &space,ISceneNode* node,dBodyID &body,dGeomID &geom)
{
    vector3df extend = (node->getBoundingBox()).getExtent();
    vector3df pos=node->getPosition();
    geom=dCreateBox(space,(dReal)extend.X,(dReal)extend.Y,(dReal)extend.Z);
    dGeomSetPosition(geom,pos.X,pos.Y,pos.Z);
    dGeomSetData(geom,node);
    body=dBodyCreate(world);
    dMass mass;
    dMassSetBox(&mass,2.0,(dReal)extend.X,(dReal)extend.Y,(dReal)extend.Z);
    dBodySetMass(body,&mass);
    dGeomSetBody(geom,body);
    dBodySetPosition(body,pos.X,pos.Y,pos.Z);
    dBodySetData(body,node);
}

void add_sphere(dWorldID &world,dSpaceID &space,ISceneNode* node,dBodyID &body,dGeomID &geom)
{
    vector3df pos=node->getPosition();
    float RADIUS = 1.5f;
	geom = dCreateSphere (space,RADIUS);
    dGeomSetPosition(geom,pos.X,pos.Y,pos.Z);
    dGeomSetData(geom,node);
    body=dBodyCreate(world);
    dMass mass;
    dMassSetSphere(&mass,2.0,RADIUS);
    dBodySetMass(body,&mass);
    dGeomSetBody(geom,body);
    dBodySetPosition(body,pos.X,pos.Y,pos.Z);
    dBodySetData(body,node);
}

void add_cylinder(dWorldID &world,dSpaceID &space,ISceneNode* node,dBodyID &body,dGeomID &geom)
{
    vector3df pos=node->getPosition();
    float WMASS = 0.2f;
    float RADIUS = 1.5f;
    float HEIGHT = 2.0f;
	geom = dCreateCylinder(space, RADIUS, HEIGHT);
    dGeomSetPosition(geom,pos.X,pos.Y,pos.Z);
    dGeomSetData(geom,node);
    body=dBodyCreate(world);
    dMass mass;
    dMassSetCylinder (&mass,WMASS,3,RADIUS, HEIGHT);
    dBodySetMass(body,&mass);
    dGeomSetBody(geom,body);
    dBodySetPosition(body,pos.X,pos.Y,pos.Z);
    dBodySetData(body,node);
}

void add_obj(ISceneManager* smgr)
{
	int type = get_rand(0, 3);
	cout << "rand: " << type << endl;
	
	std::string name = "obj_" + obj_id;
	obj_id++;
	
	nodes.insert(std::map<std::string,node*>::value_type(name, new node()));
	
	IAnimatedMesh* mesh;
	if(type==0) {
		mesh = smgr->getMesh("media/box.x");
	}
	else if(type==1) {
		mesh = smgr->getMesh("media/sphere.x");
	}
	else {
		mesh = smgr->getMesh("media/cylinder.x");
	}
	nodes[name]->snode = smgr->addAnimatedMeshSceneNode( mesh );
	
	nodes[name]->snode->setPosition(vector3df(0.0+get_rand(1, 5),20.0+get_rand(1, 5),-10+get_rand(1, 5)));
	//nodes[name]->snode->setPosition(vector3df(0.0,20.0,-10));
	//nodes[name]->snode->setScale(vector3df(0.25,0.25,0.25));
	nodes[name]->snode->setMaterialFlag(EMF_LIGHTING, true);
	nodes[name]->snode->getMaterial(0).Shininess = 20.0f;
	nodes[name]->snode->getMaterial(0).SpecularColor.set(128,255,0,0);
	nodes[name]->snode->getMaterial(0).AmbientColor.set(128,0,155,0);
	nodes[name]->snode->getMaterial(0).DiffuseColor.set(128,128,0,0);
	nodes[name]->snode->getMaterial(0).EmissiveColor.set(128,255,0,0);
	nodes[name]->snode->setMaterialType( video::EMT_SOLID );
	
	if(type==0) {
		add_box(world,space,nodes[name]->snode,nodes[name]->body,nodes[name]->geom);
	}
	else if(type==1) {
		add_sphere(world,space,nodes[name]->snode,nodes[name]->body,nodes[name]->geom);
	}
	else {
		add_cylinder(world,space,nodes[name]->snode,nodes[name]->body,nodes[name]->geom);
	}
}

class MyEventReceiver : public IEventReceiver
{
public:
	virtual bool OnEvent(const SEvent& event) { 
		if(event.EventType == irr::EET_KEY_INPUT_EVENT){
			keys[event.KeyInput.Key] = event.KeyInput.PressedDown;
			return false;
		}
	return false;
	}
};

int handle_input(ISceneManager* smgr)
{
	if(keys[KEY_KEY_W]) {	}
	if(keys[KEY_KEY_S]) {	}
	if(keys[KEY_KEY_A]) {
		add_obj(smgr);
	}
	if(keys[KEY_KEY_D]) {	}
	
	if(keys[KEY_ESCAPE]) {
		return 1;
	}
	return 0;
}

int main()
{
	srand ( time(NULL) );
	
	dInitODE();
	world = dWorldCreate();
	space = dHashSpaceCreate (0);
	contactgroup = dJointGroupCreate (0);
	dWorldSetGravity (world,0,-10.0,0);
	dWorldSetCFM (world,1e-5);
	dWorldSetAutoDisableFlag (world,1);
	
	IrrlichtDevice *device = createDevice(EDT_OPENGL);
	IVideoDriver* video = device->getVideoDriver();
	ISceneManager* smgr = device->getSceneManager();
	IGUIEnvironment* guienv = device->getGUIEnvironment();
	
	MyEventReceiver rv;
	device->setEventReceiver(&rv);
	
	for(int x=0; x<irr::KEY_KEY_CODES_COUNT; x++) keys[x] = false;
	
	//	LIGHTING
	smgr->setAmbientLight(video::SColorf(0.3,0.3,0.3,1));
	ILightSceneNode* light1 = smgr->addLightSceneNode( 0, core::vector3df(0,40,-20), video::SColorf(0.9f,0.9f,0.9f), 100.0f, 1 );
	
	//We create a plane geom at level zero so the boxes won't drop off the screen.
	geom_ground=dCreatePlane(space,0,1,0,1);
	
	smgr->addCameraSceneNode(0, vector3df(0,20,-40), vector3df(0,5,0));

	while(device->run() && device) {
		if(handle_input(smgr)) {
			device->closeDevice();
		}
		
		for( std::map<std::string, node*>::iterator ii=nodes.begin(); ii!=nodes.end(); ++ii)
		{
			node *n = (*ii).second;
			setPosition(n->geom);
			n->life++;
			if(n->life>1000) {
				dBodyDestroy (n->body);
				dGeomDestroy (n->geom);
				n->snode->remove();
				nodes.erase(ii);
			}
		}

		video->beginScene(true, true, SColor(255,100,101,140));
		smgr->drawAll();
		guienv->drawAll();
		
		dSpaceCollide(space,0,&nearCallback);
		dWorldQuickStep(world,0.025);
		dJointGroupEmpty(contactgroup);
		
		video->endScene();
	}
	
	dWorldDestroy(world);
	dCloseODE();
	
	device->drop();

	return 0;
}
and here's my makeshift makefile for irrlicht and ode on linux:

Code: Select all

Target = run

Sources = main.cpp



# general compiler settings

CPPFLAGS = -I../../include -I/usr/X11R6/include -I /home/ai/z_ode/ode-0.11.1/include

CXXFLAGS = -O3 -ffast-math

#CXXFLAGS = -g -Wall



#default target is Linux

all: all_linux



ifeq ($(HOSTTYPE), x86_64)

LIBSELECT=64

endif



# target specific settings

all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lode

all_linux clean_linux: SYSTEM=Linux

all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm

all_win32 clean_win32: SYSTEM=Win32-gcc

all_win32 clean_win32: SUF=.exe

# name of the binary - only valid for targets which set SYSTEM

#DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF)
DESTPATH = $(Target)$(SUF)



all_linux all_win32:

	$(warning Building...)

	$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS)



clean: clean_linux clean_win32

	$(warning Cleaning...)



clean_linux clean_win32:

	@$(RM) $(DESTPATH)



.PHONY: all all_win32 clean clean_linux clean_win32

Brainsaw
Posts: 1183
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Post by Brainsaw »

Hmm ... I didn't test your code, so I can't tell you where all your problems come from. But (at least for the cylinder collision) you could take a look at the following table:

http://opende.sourceforge.net/wiki/inde ... _Detection

There you can see that the cylinder won't collide with other cylinders and capsules.

If you give ODE a try you could take a look at my IrrODE wrapper (see signature), maybe just use it as a starting point. It is quite stable.
Dustbin::Games on the web: https://www.dustbin-online.de/

Dustbin::Games on facebook: https://www.facebook.com/dustbingames/
Dustbin::Games on twitter: https://twitter.com/dustbingames
delark
Posts: 8
Joined: Wed Dec 03, 2008 1:38 pm

Post by delark »

Thanks Brainsaw... I've downloaded it and I am attempting to write a makefile for linux, but my skills there are limited, so...
Post Reply