Gravity and Collision Detecting.

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
Eric the half a bee

Gravity and Collision Detecting.

Post by Eric the half a bee »

Hello. I am trying to put together a short demo and it involves seeing a model run around a q2 level. Following the tutorial on collision detecting, I am able to set the camera to follow the normal rules of physics (ie the camera doesnt float and can't walk through walls. However, when I create a new SceneNodeAnimator, the model (node1) still floats. Anys suggestions?

Code below:

#include<irrlicht.h>
#include<wchar.h>

using namespace irr;

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

scene::ICameraSceneNode* camera = 0;

class MyEventReceiver : public IEventReceiver
{
public:
virtual bool OnEvent(SEvent event)
{
if (camera)
return camera->OnEvent(event);
return false;
}
};

int main()
{
MyEventReceiver receiver;
IrrlichtDevice *device = createDevice(video::DT_DIRECTX8,core::dimension2d<s32>(640, 480), 16, false, false, &receiver);
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();

device->getFileSystem()->addZipFileArchive("map-20kdm2.pk3");

scene::IAnimatedMesh* mesh = smgr->getMesh("20kdm2.bsp");
scene::ISceneNode* node = 0;

if (mesh)
node = smgr->addOctTreeSceneNode(mesh->getMesh(0));

if (node)
node->setPosition(core::vector3df(-1300,-70,-1249));


scene::ITriangleSelector* selector = 0;

if (node)
{
selector = smgr->createOctTreeTriangleSelector(
mesh->getMesh(0), node, 128);
node->setTriangleSelector(selector);
selector->drop();
}

scene::IAnimatedMesh* mesh1 = smgr->getMesh("sydney.md2");
scene::IAnimatedMeshSceneNode* node1 = smgr->addAnimatedMeshSceneNode( mesh1 );
node1->setScale(core::vector3df(2,2,2));
node1->setPosition(core::vector3df(0,100,0));

if (node1)
{
node1->setMaterialFlag(video::EMF_LIGHTING, false);
node1->setMaterialTexture( 0, driver->getTexture("sydney.bmp") );
node1->setMD2Animation(scene::EMAT_RUN);

}

scene::ISceneNodeAnimator* anim1 = 0;

anim1 = smgr->createCollisionResponseAnimator(selector, node1, core::vector3df(30,50,30),
core::vector3df(0,-100,0), 100.0f,
core::vector3df(0,50,0));
node1->addAnimator(anim1);
anim1->drop();


scene::ISceneNodeAnimator* anim = 0;

camera = smgr->addCameraSceneNodeFPS(0,100.0f,300.0f);
camera->setPosition(core::vector3df(0,100,0));

anim = smgr->createCollisionResponseAnimator(
selector, camera, core::vector3df(30,50,30),
core::vector3df(0,-100,0), 100.0f,
core::vector3df(0,50,0));
camera->addAnimator(anim);
anim->drop();

device->getCursorControl()->setVisible(false);


int lastFPS = -1;
while(device->run())
{
driver->beginScene(true, true, video::SColor(0,100,100,100));
smgr->drawAll();
driver->endScene();
int fps = driver->getFPS();
if (lastFPS != fps)
{
wchar_t tmp[1024];
swprintf(tmp, 1024, L"Quake 3 Map Example - Irrlicht Engine (fps:%d) Triangles:%d",
fps, driver->getPrimitiveCountDrawn());
device->setWindowCaption(tmp);
lastFPS = fps;
}
}
device->drop();
return 0;
}
Boogle
Posts: 162
Joined: Fri Nov 21, 2003 3:16 pm
Location: Toronto, Canada

Post by Boogle »

The elipsoid you use for your sydney model is too big I suspect. In general, you should be able to use:

Code: Select all

irr::core::vector3df elipsoidSize = node->getBoundingBox()->MaxEdge - node->getBoundingBox()->MinEdge;
elipsoidSize = elipsoidSize/2.0f;
This gets the size of the node's bounding box and divides it by 2 so you have the bounding box's radius in all 3 dimensions. Then use this in your collision response animator constructor. ie:

Code: Select all

anim1 = smgr->createCollisionResponseAnimator(selector, node1, elipsoidSize, 
core::vector3df(0,-100,0), 100.0f, 
core::vector3df(0,0,0));
Note that I also set the offset (the last paramter) to zero. You may need to adjust this somewhat to get the feet perfectly on the ground.
Eric the half a bee

Gravity and Collision Detection

Post by Eric the half a bee »

Thanks for the swift reply. I am now just trying to get my compiler to get over the following error:

error C2819: type 'irr::core::aabbox3d<float>' does not have an overloaded member 'operator ->'
error C2227: left of '->MaxEdge' must point to class/struct/union
error C2819: type 'irr::core::aabbox3d<float>' does not have an overloaded member 'operator ->'
error C2227: left of '->MinEdge' must point to class/struct/union
Error executing cl.exe.

map.obj - 4 error(s), 0 warning(s)

Any assistance greatly appreciated.

Ta.
Boogle
Posts: 162
Joined: Fri Nov 21, 2003 3:16 pm
Location: Toronto, Canada

Post by Boogle »

Oops...

node->getBoundingBox().MaxEdge, and same for MinEdge
Eric the half a bee

Gravity and collision detection

Post by Eric the half a bee »

Many many thanks boogle. :D
Epsilon
Posts: 38
Joined: Fri Jan 09, 2004 1:46 pm
Location: Argentina

Post by Epsilon »

hello.

Dont work for me !!!! help !!!


video::SMaterial material;
material.Texture1 = driver->getTexture("faerie2.bmp");
material.Lighting = true;

scene::IAnimatedMeshSceneNode* node = 0;
scene::IAnimatedMesh* faerie = smgr->getMesh("faerie.md2");

node = smgr->addAnimatedMeshSceneNode(faerie);
node->setPosition(core::vector3df(-70,0,-60));
node->setMD2Animation(scene::EMAT_JUMP);
node->getMaterial(0) = material;
node->setScale(core::vector3df(2.0f,2.0f,2.0f));

irr::core::vector3df elipsoidSize = node->getBoundingBox().MaxEdge - node->getBoundingBox().MinEdge;
elipsoidSize = elipsoidSize/2.0f;

scene::ISceneNodeAnimator* anim2 = smgr->createCollisionResponseAnimator(
selector, node, elipsoidSize,core::vector3df(0,-100,0), 10.0f, core::vector3df(0,0,0));
node->addAnimator(anim2);
anim2->drop();


help me please !!! :wink:
Boogle
Posts: 162
Joined: Fri Nov 21, 2003 3:16 pm
Location: Toronto, Canada

Post by Boogle »

What isn't working about it?
Epsilon
Posts: 38
Joined: Fri Jan 09, 2004 1:46 pm
Location: Argentina

Post by Epsilon »

i cant collide with faeries scene nodes.
Boogle
Posts: 162
Joined: Fri Nov 21, 2003 3:16 pm
Location: Toronto, Canada

Post by Boogle »

Ah yes. For that you will need to create a MetaTriangleSelector. Then add the level's OctTreeTriangleSelector to it, as well as a triangleSelector for each faerie. eg:

Code: Select all

irr::scene::IMetaTriangleSelector bob = smgr->createMetaTriangleSelector();
bob->addTriangleSelector(selector);

irr::scene::ITriangleSelector *faerie = smgr->createTriangleSelector(fmesh1,fnode1);
bob->addTriangleSelector(faerie);
faerie->drop();

irr::scene::ITriangleSelector *faerie = smgr->createTriangleSelector(fmesh2,fnode2);
bob->addTriangleSelector(faerie);
faerie->drop();

scene::ISceneNodeAnimator* anim2 = smgr->createCollisionResponseAnimator( 
bob, node, elipsoidSize,core::vector3df(0,-100,0), 10.0f, core::vector3df(0,0,0)); 
node->addAnimator(anim2); 
anim2->drop(); 
That's the basic idea. The code will likely have to be debugged. This is kind of inefficient though, especially if you start getting lots of faeries (or other nodes). Irrlicht doesn't really have a good way of doing collision detection on things other than the level. If you find this method takes too much time, you'll have to write your own method which will first do collision detection on bounding boxes only, then if they are close enough, do use a triangle selector.

Unless there is some other more efficient method, but I've never heard anyone talk about one on the forums.
Epsilon
Posts: 38
Joined: Fri Jan 09, 2004 1:46 pm
Location: Argentina

Post by Epsilon »

Ok, thank you very much.

I will try to make my own Collide method but i have a lot of question.

In my case the game is looked in 3d but the collision should be in 2d (a platform game).

What is the essence of the collision methods ??

Only store the collision box dates or cylinder and position of every ObjectCollider and check for every one if it is colliding with every ObjectCollider in the world ??? with a "while" or "for" moving along of an list of ObjectCollider ????

I think it is too slow.

Again, thank you. :wink:
keless
Posts: 805
Joined: Mon Dec 15, 2003 10:37 pm
Location: Los Angeles, California, USA

Post by keless »

epsilon, that is the very first and most basic way of doing collision detection-- brute force.

from there, you add code to speed it up:
1) use culling methods (similar to frustrum culling, but dealing with whole objects instead of individual triangles). For instance, if you're using a portal renderer, and one of the monsters is in a portal you're not currently able to view-- you dont have to check collision with it.

2) get the distance between the current object and the object you're testing against-- if the distance is greater than your radius plus their radius, you cant possibly be colliding

3) get your movement direction and their movement direction, if neither of the objects are moving towards the other, you cant possibly colliding

it may seem like putting all these checks before your actual collision detection code means you'll be doing a lot more work right? wrong: most objects will not even pass the first test, which means you're only doing a few small checks instead of a full collision check on most objects. It will make the full collision check a little longer, but statistics shows that overall this is much faster.
a screen cap is worth 0x100000 DWORDS
Epsilon
Posts: 38
Joined: Fri Jan 09, 2004 1:46 pm
Location: Argentina

Post by Epsilon »

hi again !.

I think is not so dificult make a simplest collision detection for simplest objects, like the body od the player or something, but how can i make the gravity for collide with the terrain like in tutorial 8 the terrain is room.3ds, i already tryed using the irrlicht function

scene::IAnimatedMesh* mesh = smgr->getMesh("../irrlicht/media/room.3ds");
smgr->getMeshManipulator()->makePlanarTextureMapping(mesh->getMesh(0), 0.008f);
scene::ISceneNode* node = 0;
node = smgr->addAnimatedMeshSceneNode(mesh);
node->setMaterialTexture(0, driver->getTexture("../irrlicht/media/wall.jpg"));

scene::ITriangleSelector* selector = 0;

if (node)
{
selector = smgr->createOctTreeTriangleSelector(mesh->getMesh(0), node, 128);
node->setTriangleSelector(selector);
selector->drop();
}

and making some other objectcollider

mesh = smgr->getMesh("cuchillo.3ds");
anode = smgr->addAnimatedMeshSceneNode(mesh);
anode->setPosition(core::vector3df(-50,80,-60));

camera = smgr->addCameraSceneNodeFPS();
camera->setPosition(core::vector3df(-50,50,-150));

scene::IMetaTriangleSelector *bob = smgr->createMetaTriangleSelector();
bob->addTriangleSelector(selector);

scene::ITriangleSelector *cuchillo = smgr->createOctTreeTriangleSelector(mesh->getMesh(0), anode, 128);
//scene::ITriangleSelector *cuchillo = smgr->createTriangleSelector(mesh,anode);
bob->addTriangleSelector(cuchillo);
cuchillo->drop();

anim = smgr->createCollisionResponseAnimator(
bob, camera, core::vector3df(30,50,30),
core::vector3df(0,-100,0), 100.0f,
core::vector3df(0,35,0));
camera->addAnimator(anim);
anim->drop();

thanks.
Post Reply