COLLISION DETECTION

MrLapa

11-12-2008 22:26:15

now my problem is how to manage the collision between objects.
I saw some tutorials,but i dont understand much of what i have to do.

I 'd like to do a simple project with a crate that fall down on a plane and manage the collision.

I do tha plane and the crate that fall down with the gravity...but now i dont know which function i have to use to manage the collision between this 2 objects.

The code now is:


#include "ExampleApplication.h"


OgreOde::World *mWorld;
OgreOde::Space *mSpace;
OgreOde::StepHandler *mStepper;

class TutorialFrameListener : public ExampleFrameListener, public OIS::MouseListener, public OIS::KeyListener
{
public:
TutorialFrameListener(RenderWindow* win, Camera* cam)
: ExampleFrameListener(win, cam, true, true)
{
// Populate the camera containers
mCamNode = cam->getParentSceneNode();

// set the rotation and move speed
//mRotate = 0.13;
mMove = 250;

// continue rendering
mContinue = true;

//setta questa classe come ascoltatore di mouse e tastiera
mMouse->setEventCallback(this);
mKeyboard->setEventCallback(this);

//settiamo la direzione iniziale verso l'origine
mDirection = Vector3::ZERO;
}

bool frameStarted(const FrameEvent &evt)
{
if(mMouse)
mMouse->capture();
if(mKeyboard)
mKeyboard->capture();

//applica i movimenti fatti tramite tastiera
mCamNode->translate(mDirection * evt.timeSinceLastFrame, Node::TS_LOCAL);

Ogre::Real time = 0.1;
if (mStepper->step(time))
{
mWorld->synchronise();
}



return mContinue;
}

// MouseListener
bool mouseMoved(const OIS::MouseEvent &e)
{
return true;
}

bool mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id)
{
return true;
}

bool mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id) { return true; }

// KeyListener
bool keyPressed(const OIS::KeyEvent &e)
{
switch (e.key)
{
//con il tasto ESC chiude il programma
case OIS::KC_ESCAPE:
mContinue = false;
break;
//movimenti tastiera
case OIS::KC_UP:
case OIS::KC_W:
mDirection.z = -mMove;
break;

case OIS::KC_DOWN:
case OIS::KC_S:
mDirection.z = mMove;
break;

case OIS::KC_LEFT:
case OIS::KC_A:
mDirection.x = -mMove;
break;

case OIS::KC_RIGHT:
case OIS::KC_D:
mDirection.x = mMove;
break;

case OIS::KC_PGDOWN:
case OIS::KC_E:
mDirection.y = -mMove;
break;

case OIS::KC_PGUP:
case OIS::KC_Q:
mDirection.y = mMove;
break;

default:
break;
}
return mContinue;
}

bool keyReleased(const OIS::KeyEvent &e)
{
//annullare i cambiamenti dopo che il pulsante è rilasciato...se nn messo,continua sempre in quella direzione
switch (e.key)
{
case OIS::KC_UP:
case OIS::KC_W:
mDirection.z = 0;
break;

case OIS::KC_DOWN:
case OIS::KC_S:
mDirection.z = 0;
break;

case OIS::KC_LEFT:
case OIS::KC_A:
mDirection.x = 0;
break;

case OIS::KC_RIGHT:
case OIS::KC_D:
mDirection.x = 0;
break;

case OIS::KC_PGDOWN:
case OIS::KC_E:
mDirection.y = 0;
break;

case OIS::KC_PGUP:
case OIS::KC_Q:
mDirection.y = 0;
break;

default:
break;
} // switch
return true;
}

protected:
Real mRotate; // The rotate constant
Real mMove; // The movement constant

SceneManager *mSceneMgr; // The current SceneManager
SceneNode *mCamNode; // The SceneNode the camera is currently attached to

bool mContinue; // Whether to continue rendering or not
Vector3 mDirection; // Value to move in the correct direction
};






class TutorialApplication : public ExampleApplication,public OgreOde::CollisionListener
{
protected:
OgreOde::InfinitePlaneGeometry *mGround;
OgreOde::Body *mBody;
OgreOde::Geometry *mGeom;
OgreOde::BoxMass mMass;
Ogre::SceneNode *mNode;
Ogre::Entity *mEntity;



public:

TutorialApplication()
{
}

~TutorialApplication()
{
}


void createCamera(void)
{
// create camera, but leave at default position
mCamera = mSceneMgr->createCamera("PlayerCam");
mCamera->setNearClipDistance(5);
}

void createFrameListener(void)
{
// Create the FrameListener
mFrameListener = new TutorialFrameListener(mWindow, mCamera);
mRoot->addFrameListener(mFrameListener);

// Show the frame stats overlay
mFrameListener->showDebugOverlay(true);
}

void createScene(void)
{
/*la gerarchia è SCENEMANAGER...SCENENODE...ENTITY*/

//settaggio luce di ambiente...R,G,B da 0 ad 1
mSceneMgr->setAmbientLight( ColourValue( 1, 1, 1 ) );

//attacco camera allo SceneNode
// Create the scene node
SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode("CamNode1", Vector3(0, 80, 300));

// Create the pitch node
//node = node->createChildSceneNode("PitchNode1");
node->attachObject(mCamera);

//INIZIO PARTE MOTORE FISICO
mWorld = new OgreOde::World(mSceneMgr);
mWorld->setGravity(Ogre::Vector3(0,-9.80665,0));
mWorld->setCFM(10e-5);
mWorld->setERP(0.8);
mWorld->setAutoSleep(true);
mWorld->setAutoSleepAverageSamplesCount(10);
mWorld->setContactCorrectionVelocity(1.0);
mSpace = mWorld->getDefaultSpace();

const Ogre::Real _time_step = 0.5;
const Ogre::Real time_scale = Ogre::Real(1.7);
const Ogre::Real max_frame_time = Ogre::Real(1.0 / 4);
mStepper = new OgreOde::StepHandler(mWorld, OgreOde::StepHandler::QuickStep,_time_step, max_frame_time,
time_scale);

mGround = new OgreOde::InfinitePlaneGeometry(Plane(Ogre::Vector3(0,1,0),0), mWorld, mWorld->getDefaultSpace());
// Use a load of meshes to represent the floor
int i = 0;
StaticGeometry* s;
s = mSceneMgr->createStaticGeometry("StaticFloor");
s->setRegionDimensions(Ogre::Vector3(160.0, 100.0, 160.0));
// Set the region origin so the center is at 0 world
s->setOrigin(Ogre::Vector3::ZERO);
for (Real z = -80.0;z <= 80.0;z += 20.0)
{
for (Real x = -80.0;x <= 80.0;x += 20.0)
{
String name = String("Ground") + StringConverter::toString(i++);
Entity* entity = mSceneMgr->createEntity(name, "plane.mesh");
entity->setQueryFlags (1<<4);
entity->setUserObject(mGround);
entity->setCastShadows(false);
s->addEntity(entity, Ogre::Vector3(x,0,z));
}
}
s->build();

mEntity = mSceneMgr->createEntity("crate","crate.mesh");
mEntity->setQueryFlags (1<<2);
mNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("crate");
mNode->attachObject(mEntity);
//mEntity->setNormaliseNormals(true);
mEntity->setCastShadows(true);

mBody = new OgreOde::Body(mWorld);
mNode->attachObject(mBody);

Vector3 size(10.0,10.0,10.0);
OgreOde::BoxMass mMass(0.5,size);
mMass.setDensity(5.0,size);
mGeom = (OgreOde::Geometry*)new OgreOde::BoxGeometry(size, mWorld, mSpace);
mNode->setScale(size.x * 0.1,size.y * 0.1,size.z * 0.1);
mBody->setMass(mMass);
mGeom->setBody(mBody);
mEntity->setUserObject(mGeom);

mBody->setOrientation(Quaternion(Radian(5.0),Ogre::Vector3(0,0,0)));
mBody->setPosition(Vector3(0,120,-20));
}

};

//MAIN
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
// Create application object
TutorialApplication app;

try {
app.go();
} catch( Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.what(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
fprintf(stderr, "An exception has occurred: %s\n",
e.what());
#endif
}

return 0;
}



I know there is a function like this:



bool collision(OgreOde::Contact* contact)
{
// Check for collisions between things that are connected and ignore them
OgreOde::Geometry * const g1 = contact->getFirstGeometry();
OgreOde::Geometry * const g2 = contact->getSecondGeometry();

if (g1 && g2)
{
const OgreOde::Body * const b1 = g1->getBody();
const OgreOde::Body * const b2 = g2->getBody();
//if connected ignore them
if (b1 && b2 && OgreOde::Joint::areConnected(b1, b2))
return false;
}

// Set the friction at the contact
contact->setCoulombFriction(OgreOde::Utility::Infinity);

contact->setBouncyness(0.1);

// Yes, this collision is valid
return true;
}



but if i dont understand bad,this only check if two body are linked(in this case return false) or are in colliosion(and in this case return true)...but i would like to know what i have to do after this to make the crate bouncing on the plane.


:?:

rewb0rn

13-12-2008 10:50:37

nothing, ode will handle the collision automatically if true is returned and you should see the box bounce off the plane.

MrLapa

13-12-2008 14:50:40

nothing, ode will handle the collision automatically if true is returned and you should see the box bounce off the plane.

Now it works,but i dont have changed nothind...but,very strange!!!

Can you explain what do

contact->setCoulombFriction(OgreOde::Utility::Infinity);

and

contact->setBouncyness(0.9);

mean?(i tried to change this values but nothing changes)

rewb0rn

14-12-2008 18:48:08

http://www.ogre3d.org/wiki/index.php/Og ... Parameters

MrLapa

15-12-2008 17:31:43

http://www.ogre3d.org/wiki/index.php/OgreOde_Collision_Handling#Contact_Parameters

Thanks a lot...but i read about this:

Friction:
How fast does the object lose speed when hitting another object.
(i think it's the "setCoulombFriction" method)

Now i solved all problems(thanks again), i've done a ball that fall down on the plane and bounce...then with the Keys(H,B,N,M) i can move the ball(on the left,the right,back and forward).
The problem is that once i apply the force to move the ball,then the ball never stops...it continues to move indefinitely.
I've setted:

contact->setCoulombFriction(OgreOde::Utility::Infinity);
contact->setBouncyness(0.9);


and i've tried also to set:
contact->setCoulombFriction(0);

and other values...but nothing changes(the ball never stops)...do you know why?

Thanks

rewb0rn

15-12-2008 18:10:50

Yea try OgreOde::Util::Infinity (or something like that)
It does not expect a value between 0 and 1 but 0 and integer max (or so)

MrLapa

16-12-2008 11:27:46

Yea try OgreOde::Util::Infinity (or something like that)
It does not expect a value between 0 and 1 but 0 and integer max (or so)


Nothing,always the ball never stops.
I have a class that extends the CollisionListener:

class AscoltatoreCollisioni : public OgreOde::CollisionListener
{
public:
AscoltatoreCollisioni(OgreOde::World *world)
{
//recupero del puntatore al mondo,allo SceneManager ed allo Spazio di collisione
mWorld = world;
mScene = mWorld->getSceneManager();
mSpace = mWorld->getDefaultSpace();
}
//metodi che verranno implementati nelle classi che estendono questa classe
virtual bool collision(OgreOde::Contact *contact);
virtual void addForcesAndTorques(){}

protected:
OgreOde::World *mWorld;
OgreOde::Space *mSpace;
Ogre::SceneManager *mScene;
};


And the class for the ball:

#ifndef _PALLA_H_
#define _PALLA_H_



#include "ClassiBase.h"



class Palla : public AscoltatoreCollisioni
{
public:
//il costruttore della classe Palla richiama prima quello dell'ascoltatore e poi aggiunge altre istruzioni
Palla(OgreOde::World *world,Ogre::String nomepalla,Ogre::String nomemesh,Ogre::Real m,Ogre::Real sx,
Ogre::Real sy,Ogre::Real sz,Ogre::Real px,Ogre::Real py,Ogre::Real pz,Ogre::Real forzaApplicata) :
AscoltatoreCollisioni(world)
{
/* INIZIALIZZAZIONE VARIABILI */
avanti = indietro = destra = sinistra = sopra = false;


/* RECUPERO PARAMETRI */
scala.x = sx;
scala.y = sy;
scala.z = sz;
posizione.x = px;
posizione.y = py;
posizione.z = pz;
massa = m;
nomePalla = nomepalla;
nomeMesh = nomemesh;
forza=forzaApplicata;

/* DISEGNO PALLA */
//creazione nodo al quale attaccare la palla
nodo = mScene->getRootSceneNode()->createChildSceneNode(nomePalla);
//creazione entità che rappresentarà la palla
Entity* entita = mScene->createEntity(nomePalla,nomeMesh);
entita->setNormaliseNormals(true);
entita->setCastShadows(true);
//attaccare l'entità al nodo,che poi viene scalato e posizionato
nodo->attachObject(entita);
nodo->setScale(scala.x,scala.y,scala.z);
nodo->setPosition(posizione.x,posizione.y,posizione.z);
//creazione di una sfera dinamica con la massa m passata come parametro
OgreOde::EntityInformer eiBall(entita,Matrix4::getScale(nodo->getScale()));
corpo = eiBall.createSingleDynamicSphere(m,mWorld, mSpace);
}
/*
Metodo collision per settare le caratteristiche fisiche dell'oggetto
*/
virtual bool collision(OgreOde::Contact* contact)
{

//Settaggio delle leggi fisiche da rispettare per la palla
contact->setCoulombFriction(OgreOde::Utility::Infinity);
contact->setBouncyness(0.9);

return true;
}

/*
Metodo che applica una forza all'oggetto
*/
virtual void addForcesAndTorques()
{
if(avanti)
{
corpo->wake();
corpo->addTorque(Ogre::Vector3(forza,0,0));
corpo->addForce(Ogre::Vector3(0,0,forza));
}
if(indietro)
{
corpo->wake();
corpo->addTorque(Ogre::Vector3(-forza,0,0));
corpo->addForce(Ogre::Vector3(0,0,-forza));
}
if(destra)
{
corpo->wake();
corpo->addTorque(Ogre::Vector3(0,0,-forza));
corpo->addForce(Ogre::Vector3(forza,0,0));
}
if(sinistra)
{
corpo->wake();
corpo->addTorque(Ogre::Vector3(0,0,forza));
corpo->addForce(Ogre::Vector3(-forza,0,0));
}
if(sopra)
{
corpo->wake();
corpo->addForce(mWorld->getGravity() * -forza);
}
}
OgreOde::Body *getCorpo() { return corpo; }

Ogre::SceneNode *getNodo() { return nodo; }

Ogre::Entity *getEntita() { return entita; }

Ogre::Real getMassa() { return massa; }

Ogre::Vector3 getPosizione() { return posizione; }

Ogre::Vector3 getScala() { return scala; }

Ogre::String getNomePalla() { return nomePalla; }

Ogre::String getNomeMesh() { return nomeMesh; }

Ogre::Real getForza() { return forza; }

bool getAvanti() { return avanti; }

bool getIndietro() { return indietro; }

bool getDestra() { return destra; }

bool getSinistra() { return sinistra; }

bool getSopra() { return sopra; }

/*
Metodi per settare gli indicatori di movimento + la forza impressa
*/
void setAvanti(bool value) { avanti = value; }

void setIndietro(bool value) { indietro = value; }

void setDestra(bool value) { destra = value; }

void setSinistra(bool value) { sinistra = value; }

void setSopra(bool value) { sopra = value; }

void setForza(Ogre::Real f) { forza = f; }


//variabili utilizzate
protected:
OgreOde::Body *corpo;
Ogre::SceneNode *nodo;
Ogre::Entity *entita;
Ogre::Real massa;
Ogre::Vector3 posizione;
Ogre::Vector3 scala;
Ogre::String nomePalla;
Ogre::String nomeMesh;
Ogre::Real forza;
bool avanti,indietro,destra,sinistra,sopra;
};
#endif


And in the file Application.cpp i have this code for the collision method

bool AscoltatoreCollisioni::collision(OgreOde::Contact* contact)
{
//Recupero dei 2 parametri
OgreOde::Geometry * const g1 = contact->getFirstGeometry();
OgreOde::Geometry * const g2 = contact->getSecondGeometry();

//se ci sono tutti e 2
if (g1 && g2)
{
//recupero dei body(corpo degli oggetti)
const OgreOde::Body * const b1 = g1->getBody();
const OgreOde::Body * const b2 = g2->getBody();
//controllo se ci sono entrambi,e se sono connessi[metodo areConnected()]...in tal caso ritorna falso
if (b1 && b2 && OgreOde::Joint::areConnected(b1, b2))
return false;
}

//Se siamo arrivati qui allora i 2 oggetti sono in collisione,e ritorna true in modo da elaborare tale collisione
return true;
}


The values of friction and bouncyness are setted in the collision method of the class BALL.

It's right or wrong?