No Collisions in Subspace

void80

07-12-2009 12:00:30

Hi there,

I have a little Problem with some collisions. Here is a code sample which shows the problem. I tried to minimize the program. The real program does not use the ExampleApplication Framework and is more object oriented. But I think the problem is easier to be unterstand this way.

I think most of the relevant code is in the createSceneMethod. The createPolygons method just adds box shaped polygons to a given ManualObject. Here is the code:

#include "MyExampleFrameListener.h" // this is the same as ExampleApplication.h, but without "using namespace Ogre;". Can't understand why someone put this in a header file, since it causes a lot of problems
#include "MyExampleApplication.h" // likewise
#include "OgreOde_Core.h"


#define SUBSPACE 0

class Listener : public ExampleFrameListener
{
public:
Listener(Ogre::RenderWindow* win, Ogre::Camera* cam, OgreOde::World *_world)
: ExampleFrameListener(win, cam)
, world(_world)
, stepHandler(0)
{
const Ogre::Real time_step = 0.5;
const Ogre::Real time_scale = 1.7;
const Ogre::Real max_frame_time = 1.0 / 4;

stepHandler = new OgreOde::StepHandler(world, OgreOde::StepHandler::QuickStep, time_step, max_frame_time, time_scale);
}

~Listener() {}

bool frameStarted(const Ogre::FrameEvent &evt)
{
stepHandler->step(evt.timeSinceLastFrame);
world->synchronise();
return ExampleFrameListener::frameStarted(evt);
}
private:
OgreOde::StepHandler *stepHandler;
OgreOde::World *world;
};


class Application : public ExampleApplication
{
public:
Application() {}
~Application() {}
protected:

void createFrameListener(void)
{
Listener *l = new Listener(mWindow, mCamera, world);
l->showDebugOverlay(true);
mRoot->addFrameListener(l);
}

void createScene(void)
{
// Set ambient light
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));
mSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8);

// Set camera look point
mCamera->setPosition(10, 15, 0);
mCamera->lookAt(0, 0, 0);

// setup ode
world = new OgreOde::World(mSceneMgr);
world->setGravity(Ogre::Vector3(0,-9.80665,0));
world->setShowDebugGeometries(true);

OgreOde::Space *space = world->getDefaultSpace();
#if SUBSPACE
/**************** The problem is in this branch *******************/
OgreOde::Space *mySpace = new OgreOde::SimpleSpace(world, space);
mySpace->setInternalCollisions(true);
#else
/***************** This branch works as expected ****************/
OgreOde::Space *mySpace = space;
#endif
// ground box
Ogre::SceneNode *groundBoxNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("groundBox");
Ogre::ManualObject *groundBoxObject = new Ogre::ManualObject("groundBox");
groundBoxNode->attachObject(groundBoxObject);
createPolygons(groundBoxObject);
// ground box: Geo
OgreOde::Geometry *groundBoxGeometry = new OgreOde::BoxGeometry(Ogre::Vector3(1, 1, 1), world, mySpace);

// Falling box
Ogre::SceneNode *fallingBoxNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("fallingBox");
fallingBoxNode->setPosition(Ogre::Vector3(0, 10, 0));
Ogre::ManualObject *fallingBoxObject = new Ogre::ManualObject("fallingBox");
fallingBoxNode->attachObject(fallingBoxObject);
createPolygons(fallingBoxObject);
// falling box: Body
OgreOde::Body *fallingBoxBody = new OgreOde::Body(world, "fallingBoxBody");
fallingBoxBody->setMass(OgreOde::BoxMass(5.0, Ogre::Vector3(1, 1, 1)));
fallingBoxNode->attachObject(fallingBoxBody);
// falling box: Geo
OgreOde::Geometry *fallingBoxGeometry = new OgreOde::BoxGeometry(Ogre::Vector3(1, 1, 1), world, mySpace);
fallingBoxGeometry->setPosition(fallingBoxNode->getPosition());
fallingBoxGeometry->setBody(fallingBoxBody);
}

private:
OgreOde::World * world;

void createPolygons(Ogre::ManualObject *object)
{
const Ogre::Real size = 1;

const Ogre::Real positionLeft = size * (- 0.5);
const Ogre::Real positionRight = size * (+ 0.5);
const Ogre::Real positionBottom = size * (- 0.5);
const Ogre::Real positionTop = size * (+ 0.5);
const Ogre::Real positionBack = size * (- 0.5);
const Ogre::Real positionFront = size * (+ 0.5);

const Ogre::Real textureTop = 0;
const Ogre::Real textureLeft = 0;
const Ogre::Real textureBottom = 1;
const Ogre::Real textureRight = 1;

object->begin("blocks/steel", Ogre::RenderOperation::OT_TRIANGLE_LIST); // this material simple displays a steel looking texture

object->position(positionLeft, positionBottom, positionFront);
object->textureCoord(textureLeft, textureBottom);

object->position(positionRight, positionBottom, positionFront);
object->textureCoord(textureRight, textureBottom);

object->position(positionRight, positionTop, positionFront);
object->textureCoord(textureRight, textureTop);

object->position(positionLeft, positionTop, positionFront);
object->textureCoord(textureLeft, textureTop);


object->position(positionLeft, positionBottom, positionBack);
object->textureCoord(textureLeft, textureTop);

object->position(positionRight, positionBottom, positionBack);
object->textureCoord(textureRight, textureTop);

object->position(positionRight, positionTop, positionBack);
object->textureCoord(textureRight, textureBottom);

object->position(positionLeft, positionTop, positionBack);
object->textureCoord(textureLeft, textureBottom);

// adds on the backside for left, right-> Extra because of different texture Coodinates
object->position(positionRight, positionBottom, positionBack);
object->textureCoord(textureLeft, textureBottom);

object->position(positionRight, positionTop, positionBack);
object->textureCoord(textureLeft, textureTop);

object->position(positionLeft, positionBottom, positionBack);
object->textureCoord(textureRight, textureBottom);

object->position(positionLeft, positionTop, positionBack);
object->textureCoord(textureRight, textureTop);

object->quad(0, 1, 2, 3); // front
object->quad(2, 6, 7, 3); // top
object->quad(7, 6, 5, 4); // back
object->quad(0, 4, 5, 1); // bottom

object->quad(0, 3, 11, 10); // left;
object->quad(1, 8, 9, 2); // right

object->end();
}
};

#define WIN32_LEAN_AND_MEAN
#include "windows.h"

INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)
{
// Create application object
Application app;
try {
app.go();
} catch(Ogre::Exception& e) {
MessageBoxA(NULL, e.getFullDescription().c_str(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
}

return 0;
}


As you can see I am trying to collide Ogre::ManualObject s. In this example every Object is just a Cube of Unit length. There are two Cubes, one called groundBox and one called fallingBox. The ground Box doesn't have a Body and therefore does not fall. Thisi box is later meant to create some floor to stand on. The falling Box is the simulation of a character. It has a body and is therefore meant to fall and to collide with the ground.

All collision works as expected in the above example. The problem is, if the Macro SUBSPACE is set to 1, then a subspace is created as a child of the default space (OgreOde::World::getDefaultSpace). Referring to the Ode Manual subspaces should be used to improve colliding speed. Also I would later like to put all ground elements into one subspace that doesn't collide internally (OgreOde::Space::setInternalCollisions(false)). But for the moment this doesn't work. If the subspace is used, then the falling box passes right through the ground.

As you can see the subspace (myspace) has the interal collisions set to true. I therefore suspected the subspace version to work to.

Can anybody solve this problem?

Thanks in advance.

void80

07-12-2009 22:08:37

I think I solved the problem.

Seems that Spaces are not conidered recursivly. Collisions are only detected if it happens on top level of the space that is tested. If on top level a geom colliding is a space, than this is considered recursivly. Sadly a collison inside of a subspace of the top level space is not considered if the space does not collide with something else of direct child level of the tested space.

Long story short: i put the two boxes in different spaces that are DIRECT children of the default space.

I just don't know if this is intended (by Ode).