Code snippet for using IRR Files and have camera collision..

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
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Code snippet for using IRR Files and have camera collision..

Post by christianclavet »

Hi, I'm really new to the engine and a very begginer in C++. I've found the site yesterday...

I would like to use the full demo and instead of loading the Quake mesh. Load a .IRR scene, find all elements and be able to do proper collisions treament with the camera. So that the camera doesnt go thru the meshes in my scene.

So it's should be on the surface the same thing as the IRRLicht full demo, but I would use the LOADSCENE argument instead of the GETMESH. But I'm not good enough at the moment in C++ (basic knowledge) and my engine knowledge is pretty limited at the moment. :oops:

Would there be somebody kind enough to show me some code snippet for doing this? :?:

Regards,
Christian Clavet
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

I posted some code here a while back for doing this. You will probably find that if you have a lot of scene nodes or your meshes have many faces the performance will be poor. That is because the collision animator doesn't do any broad phase collision testing before doing the triangle intersections tests.

You could modify ISceneNode_gatherTriangleSelectors() so that it is called in the main loop, only gathering selectors for scene nodes that are near to the camera. That should dramatically improve the performance.

Code: Select all

void ISceneNode_gatherTriangleSelectors(scene::ISceneNode* node, scene::IMetaTriangleSelector* meta, const core::aabbox3df& box) 
{ 
  scene::ITriangleSelector* selector = node->getTriangleSelector(); 
  if (selector)
  {
    core::aabbox3df nbox (node->getBoundingBox());
    node->getAbsoluteTransformation().transformBoxEx(nbox);

    if (selector && nbox.intersectsWithBox(box)) 
      meta->addTriangleSelector(selector); 
  }

  // now recurse on children... 
  core::list<scene::ISceneNode*>::Iterator begin = node->getChildren().begin(); 
  core::list<scene::ISceneNode*>::Iterator end   = node->getChildren().end(); 

  for (/**/; begin != end; ++begin) 
    ISceneNode_gatherTriangleSelectors(*begin, meta, box); 
} 

void ISceneManager_gatherTriangleSelectors(scene::ISceneManager* smgr, scene::IMetaTriangleSelector* meta, const core::aabbox3df& box) 
{ 
  ISceneNode_gatherTriangleSelectors(smgr->getRootSceneNode(), meta, box); 
} 
And you'd use it something like this...

Code: Select all

smgr->loadScene("../../media/example.irr");

ISceneManager_assignTriangleSelectors(smgr, device->getFileSystem()); 

scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); 

scene::IMetaTriangleSelector* meta = smgr->createMetaTriangleSelector();

scene::ISceneNodeAnimator* anim = 
    smgr->createCollisionResponseAnimator(meta, camera, core::vector3df(3,3,3), core::vector3df(0,-1,0), core::vector3df(0,6,0)); 
  camera->addAnimator(anim); 
anim->drop(); 

meta->drop(); 

while (device->run())
{
  if (driver->beginScene(...))
  {
    smgr->drawAll();

    driver->endScene();
  }

  // update the collision animator stuff.
  meta->removeAllTriangleSelectors();

  core::aabbox3df box(-10.f, -10.f, -10.f, 10.f, 10.f, 10.f);
  camera->getAbsoluteTransformation().transformBoxEx(box);

  // put all selectors into meta selector if they intersect the bounding box
  ISceneManager_gatherTriangleSelectors(smgr, meta, box);
}
I haven't attempted to compile the above code, but it should be pretty close to working. Good luck.

Travis

edit: fixed const problem and now use transformBoxEx() in ISceneNode_gatherTriangleSelectors()
Last edited by vitek on Mon Apr 07, 2008 8:10 am, edited 2 times in total.
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Post by christianclavet »

Thanks Travis! :D

I'll try to implement this. But I think I will have to update my Irrlicht.dll. The one I have currently is 1.3 and a bug was reported. :? I'll check also for the SVN and how it work.

Regards,
Christian Clavet
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Post by christianclavet »

Hi Travis. :)

I've put as much code as I could to make the compilation work. (Usign IRRlicht 1.3 with DevCpp)

I've only a problem with this line:
camera->getAbsoluteTransformation().transformBoxEx(box);

I'm getting this:
no matching function for call to `irr::core::matrix4::transformBoxEx(const irr::core::aabbox3df&) const'

But the function is there (seen it in docs).
This could simply be C++ problem. I'm still learning C++.
:oops:

If I comment that line, I see my scene and the camera "drop" down. My mesh is going farther away until it dissapear.

I could sent back the code if you need to check.
Regards,

Christian Clavet
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Post by christianclavet »

Ok. Here is my codes for the main()

Code: Select all

int main()
{
	video::E_DRIVER_TYPE driverType;
   /*	case 'a': driverType = video::EDT_DIRECT3D9;break;
		case 'b': driverType = video::EDT_DIRECT3D8;break;
		case 'c': driverType = video::EDT_OPENGL;   break;
		case 'd': driverType = video::EDT_SOFTWARE; break;
		case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
		case 'f': driverType = video::EDT_NULL;     break;    */
    driverType = EDT_DIRECT3D9;
	// create device and exit if creation failed
	IrrlichtDevice* device =
		createDevice(driverType, dimension2d<s32>(640, 480));
	if (device == 0)
		return 1; // could not create selected driver.

	device->setWindowCaption(L"Load .irr file example");
	IVideoDriver* driver = device->getVideoDriver();
	ISceneManager* smgr = device->getSceneManager();
	// Now load our .irr file.
	// load the scene
	smgr->loadScene("room.irr");
	// Assign Triangle selector
    ISceneManager_assignTriangleSelectors(smgr, device->getFileSystem()); 
	// add a user controlled camera
	ICameraSceneNode* camera = 	smgr->addCameraSceneNodeFPS(0, 100.0f, 300.0f, -1, 0, 0, true);
	// Position the Camera
	camera->setPosition(vector3df(-50,60,0));
	// Rotate the Camera
	camera->setRotation(vector3df(0,90,0));
	//Put the Meta Triangle Selector
	scene::IMetaTriangleSelector* meta = smgr->createMetaTriangleSelector(); 
	// Node "meta" animation for the Camera
    scene::ISceneNodeAnimator* anim = 
    smgr->createCollisionResponseAnimator(meta, camera, core::vector3df(3,3,3), core::vector3df(0,-1,0), core::vector3df(0,6,0)); 
    // Assign the node anim to the camera
    camera->addAnimator(anim); 
    anim->drop(); 
    meta->drop(); 

	// and draw everything.

	int lastFPS = -1;

	while(device->run())
	if (device->isWindowActive())
	{
		driver->beginScene(true, true, video::SColor(0,200,200,200));
		smgr->drawAll();
		driver->endScene();

		int fps = driver->getFPS();

		if (lastFPS != fps)
		{
		  stringw str = L"Load Irrlicht File example - Irrlicht Engine [";
		  str += driver->getName();
		  str += "] FPS:";
		  str += fps;

		  device->setWindowCaption(str.c_str());
		  lastFPS = fps;
		}
    // update the collision animator stuff. 
    meta->removeAllTriangleSelectors(); 
    const core::aabbox3df box(-10.f, -10.f, -10.f, 10.f, 10.f, 10.f); 
    camera->getAbsoluteTransformation().transformBox(box); 
    // put all selectors into meta selector if they intersect the bounding box 
    ISceneManager_gatherTriangleSelectors(smgr, meta, box); 
	}
	device->drop();
	return 0;
}
Here is the other routine Travis submitted to interract with the main()

Here is the Node Assign routine for the triangle selector

Code: Select all

void ISceneNode_assignTriangleSelector(scene::ISceneNode* node, scene::ISceneManager* smgr, io::IFileSystem* ifs) 
{ 
 // From vitek
  if (!node || !smgr || !ifs) 
    return; 

  if (node->getType() == scene::ESNT_OCT_TREE) 
  { 
    io::IAttributes* attribs = ifs->createEmptyAttributes(); 
    if (attribs) 
    { 
      node->serializeAttributes(attribs); 

      // get the mesh name out 
      core::stringc name = attribs->getAttributeAsString("Mesh"); 

      attribs->drop(); 

      // get the animated mesh for the object 
      scene::IAnimatedMesh* mesh = smgr->getMesh(name.c_str()); 
      if (mesh) 
      { 
        scene::ITriangleSelector* selector = 
          smgr->createOctTreeTriangleSelector(mesh->getMesh(0), node, 128); 
        node->setTriangleSelector(selector); 
        selector->drop(); 
      } 
    } 
  } 
  else if (node->getType() == scene::ESNT_MESH) 
  { 
    scene::IMeshSceneNode* msn = (scene::IMeshSceneNode*)node; 

    if (msn->getMesh()) 
    { 
      scene::ITriangleSelector* selector = 
        smgr->createTriangleSelector(msn->getMesh(), msn); 
      msn->setTriangleSelector(selector); 
      selector->drop(); 
    } 
  } 
  else if (node->getType() == scene::ESNT_ANIMATED_MESH) 
  { 
    scene::IAnimatedMeshSceneNode* msn = (scene::IAnimatedMeshSceneNode*)node; 

    scene::IAnimatedMesh* am = msn->getMesh(); 
    if (am) 
    { 
      scene::ITriangleSelector* selector = 
        smgr->createTriangleSelector(am->getMesh(0), msn); 
      msn->setTriangleSelector(selector); 
      selector->drop(); 
    } 
  } 
  else if (node->getType() == scene::ESNT_TERRAIN) 
  { 
    scene::ITerrainSceneNode* tsn = (scene::ITerrainSceneNode*)node; 

    scene::ITriangleSelector* selector = 
      smgr->createTerrainTriangleSelector(tsn, 0); // probably don't want lod 0 all the time... 
    tsn->setTriangleSelector(selector); 
    selector->drop(); 
  } 
  else 
  { 
    // not something we want to collide with 
  } 
} 
Here is the assign routing for the selector

Code: Select all

void ISceneNode_assignTriangleSelectors(scene::ISceneNode* node, scene::ISceneManager* smgr, io::IFileSystem* ifs) 
{ 
// From Vitek
  // assign a selector for this node 
  ISceneNode_assignTriangleSelector(node, smgr, ifs); 

  // now recurse on children... 
  core::list<scene::ISceneNode*>::Iterator begin = node->getChildren().begin(); 
  core::list<scene::ISceneNode*>::Iterator end   = node->getChildren().end(); 

  for (/**/; begin != end; ++begin) 
    ISceneNode_assignTriangleSelectors(*begin, smgr, ifs); 
} 

void ISceneManager_assignTriangleSelectors(scene::ISceneManager* smgr, io::IFileSystem* ifs) 
{ 
  ISceneNode_assignTriangleSelectors(smgr->getRootSceneNode(), smgr, ifs); 
} 
Gather selector

Code: Select all

void ISceneNode_gatherTriangleSelectors(scene::ISceneNode* node, scene::IMetaTriangleSelector* meta, const core::aabbox3df& box) 
// From Vitek
{ 
  scene::ITriangleSelector* selector = node->getTriangleSelector(); 
  if (selector && node->getTransformedBoundingBox().intersectsWithBox(box)) 
    meta->addTriangleSelector(selector); 

  // now recurse on children... 
  core::list<scene::ISceneNode*>::Iterator begin = node->getChildren().begin(); 
  core::list<scene::ISceneNode*>::Iterator end   = node->getChildren().end(); 

  for (/**/; begin != end; ++begin) 
    ISceneNode_gatherTriangleSelectors(*begin, meta, box); 
} 

void ISceneManager_gatherTriangleSelectors(scene::ISceneManager* smgr, scene::IMetaTriangleSelector* meta, const core::aabbox3df& box) 
{ 
  ISceneNode_gatherTriangleSelectors(smgr->getRootSceneNode(), meta, box); 
} 
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

The compiler is giving you an error message that tells you the problem, and you are ignoring it. The functions transformBoxEx and transformBox take references to aabbox3df, not a references to const aabbox3df. My code pasted above has an obvious problem. You need to remove the const qualifier in the box declaration.

Also, you will want to use the transformBoxEx function, not transformBox. The latter function is not very good as the generated bounding box does not always fully enclose the original box.

Travis
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Post by christianclavet »

Thanks Travis. :D

The code compile correctly now. :roll: That was my fault... Removed the "const" and put back the transformBoxEx at it's place.

I still go thru the wall of my mesh. (At the beginning, the camera was falling down because of the motion vector)

Perhaps, I should try to check in your code and use only the parts that treat for my 3d mesh for the moment. Once I understand more of It; I could perhaps find what is the problem in the current code. I can only think the updating of the collision is not working for a reason. "ISceneManager_gatherTriangleSelectors(smgr, meta, box);" is perhaps not being called as it should.

Regards,
Christian Clavet
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

I've just tested the code above and it works quite well. I don't know what the issue you are having is, but it does work for me with Irrlicht 1.2. If you are using Irrlicht 1.3 the ISceneManager_assignTriangleSelectors function will fail to do anything useful because of a well-known bug with Irrlicht 1.3.

Travis
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Post by christianclavet »

Thanks Travis.

I've been studying your code and understood more about Irrlicht for collision detection.

I'm still not ready to "optimize it" but now it seem to work. :)

Regards,
Christian Clavet
baiqian
Posts: 43
Joined: Sun Apr 06, 2008 2:29 pm

Post by baiqian »

I use above code,but when i compile it, it occur errors as below
.\main.cpp(81) : error C3861: “ISceneManager_assignTriangleSelectors”: undeclaration
.\main.cpp(126) : error C3861: “ISceneManager_gatherTriangleSelectors”: undeclaration
.\main.cpp(209) : error C2440:can not transfer “irr::core::list<T>::ConstIterator” to “irr::core::list<T>::Iterator”

Anyone know what's wrong with it? I have been work on irr collision for 2 weeks... I use Irrlicht 1.4
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

Urgh. Is it really so hard to copy and paste the actual error text?

The errors tell you exactly what's wrong.

ISceneManager_assignTriangleSelectors() isn't defined at the point where you refer to it. You'll have to include the definition of it, or at least a declaration of it, before the point where you call it. Likewise for ISceneManager_gatherTriangleSelectors()

The C2440 error is also unambiguous. I don't know what line in your source code it refers to, but you have, or are being returned, a ConstIterator, and are trying to pass it to or assign it to a reference to a (non const) Iterator. You will need to be consistent in your use of iterators.

If you post the line that's actually causing that error, I can be more specific.

As an aside, just copying and pasting other people's code, particularly older code, is only going to get you so far. You are going to have to learn and understand all of this yourself.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
radiant
Posts: 112
Joined: Fri Feb 22, 2008 8:04 pm
Location: Mexico

Post by radiant »

Hi, i have a little... and probably very nobb cuestion on this... what does the following code do?

Code: Select all

core::aabbox3df box(-10.f, -10.f, -10.f, 10.f, 10.f, 10.f);
camera->getAbsoluteTransformation().transformBoxEx(box);
My first guess was that u re ... placing the box centered on the camera position so then u can check collision only in that box... but i was under the impression that the code wasnt optimized to check only the nodes near the camera...

did i got it right??

Thanks in advance
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Those two lines get a box that is 20 units in each dimension and places it around the current camera position. The call to ISceneManager_gatherTriangleSelectors() finds all nodes who have bounding boxes that intersect that box, and adds their triangle selectors to a meta selector for the collision response animator.

This is a cheap and dirty optimization. Instead of doing ellipse to triangle intersection tests for every triangle selector, it only does those tests for selectors that have scene nodes near the camera. It could be optimized further by using a partitioning scheme so that the scene nodes near the camera can be found without doing a bunch of bounding box intersection tests. Of course you could just opt to not use the Irrlicht collision system too...

Travis
radiant
Posts: 112
Joined: Fri Feb 22, 2008 8:04 pm
Location: Mexico

Post by radiant »

Thanks, i wasnt so lost after all ^_^

one more question... what do u get when u call:

Code: Select all

selector && node->getTransformedBoundingBox().intersectsWithBox(box);
if one is contained into the other?
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Maybe you should take a look at the code for aabbox3d<T>::intersectsWithBox() and tell us all what you find.

Travis
Post Reply