Irr Collision help-Trinangle slector from non octree

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
limvot
Posts: 20
Joined: Sun Sep 09, 2007 2:41 am

Irr Collision help-Trinangle slector from non octree

Post by limvot »

I need some help with my code. I am using code from this tut.
http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=26191

However, i have made a few modifications, mostly just creatieing the collision cam function. Here is the complete code. I would like to load stuff that is not an octree and still have collision with out the bounding box. I know it could eat up processer, but it is neccesary and what i am looking at is a small levle.

Please help!

Code: Select all

/*
Since version 1.1, Irrlicht is able to save and load
the full scene graph into an .irr file, an xml based
format. There is an editor available to edit
those files, named irrEdit on http://www.ambiera.com/irredit,
which can also be used as world and particle editor.
This tutorial shows how to use .irr files.

Lets start: Create an Irrlicht device and setup the window.
*/

#include <irrlicht.h>
#include <iostream>
using namespace irr;

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

class CollisionMaker : public irr::scene::ISceneUserDataSerializer
{
   irr::IrrlichtDevice* mDevice;
   irr::scene::IMetaTriangleSelector* mSelector;
public:
   CollisionMaker(irr::IrrlichtDevice* pDev);
   irr::scene::IMetaTriangleSelector* getSelector();
   irr::io::IAttributes* createUserData (irr::scene::ISceneNode *forSceneNode); //override from
   void OnReadUserData (irr::scene::ISceneNode *forSceneNode, irr::io::IAttributes *userData);
   void LoadScene(const c8 *filename);
   void AddCollisionCam ();
};

CollisionMaker::CollisionMaker(irr::IrrlichtDevice* pDev)
{
   mDevice = pDev;
   mSelector = mDevice->getSceneManager()->createMetaTriangleSelector();
}

irr::scene::IMetaTriangleSelector* CollisionMaker::getSelector()
{
   return mSelector;
}


irr::io::IAttributes* CollisionMaker::createUserData (irr::scene::ISceneNode *forSceneNode)
{
   //Sending 0 caus' we don't care
   return (irr::io::IAttributes*)0;
}


void CollisionMaker::OnReadUserData (irr::scene::ISceneNode *forSceneNode, irr::io::IAttributes *userData)
{
   //if the attribute is not set, it's considered false. If it's false, we don't do anything.
   if(userData->getAttributeAsBool("Collidee"))
   {
      //Detecting node type
      if(forSceneNode->getType()==irr::scene::ESNT_OCT_TREE)
      {
         //Node is an octree, let's get mesh info
         irr::io::IAttributes *attributes = mDevice->getFileSystem()->createEmptyAttributes();
         forSceneNode->serializeAttributes(attributes);
         irr::scene::IAnimatedMesh* mesh = mDevice->getSceneManager()->getMesh(attributes->getAttributeAsString("Mesh").c_str());
         attributes->drop();
         //Creating selector based on mesh
         irr::scene::ITriangleSelector* thisSelector = mDevice->getSceneManager()->createOctTreeTriangleSelector(mesh->getMesh(0), forSceneNode, 128);
         //Adding the selector to the meta selector
         mSelector->addTriangleSelector(thisSelector);
         thisSelector->drop();
      }
      else
      {

         //Node isn't an octree, we build a triangle selector based on bounding box
         //Node isn't an octree, we build a triangle selector based on bounding box
         irr::scene::ITriangleSelector* thisSelector = mDevice->getSceneManager()->createTriangleSelectorFromBoundingBox(forSceneNode);
         //And we add it to the metaSelector
         mSelector->addTriangleSelector(thisSelector);
         thisSelector->drop();
      }
   }
   if(userData->getAttributeAsBool("Collider"))
   {
      //Now we animate nodes that are supposed to respond to collisions based on the metaselector
      //create an animator using the metaselector. Collision values are arbitrary. Elipsoid is made according to mesh bounding box
      irr::scene::ISceneNodeAnimatorCollisionResponse* anim = mDevice->getSceneManager()->createCollisionResponseAnimator(
         mSelector, forSceneNode, forSceneNode->getBoundingBox().MaxEdge,
         irr::core::vector3df(0,-1,0), irr::core::vector3df(0,0,0));
      //Adding the animator to the node
      forSceneNode->addAnimator(anim);

      anim->drop();
      std::cout<< "here at collider";
   }
}


void CollisionMaker::LoadScene(const c8 *filename)
{
   mDevice->getSceneManager()->loadScene(filename, this);
}

void CollisionMaker::AddCollisionCam ()
{
//This is my code! I adapted the collision camera code from the collision tut
//Basically I added a new function that creates a camera that collides with stuff
//to the class. I did it in the class for neatness and because all of the stuff was declared here
//any way. As to the changes to the Collision tut code i replaces smgr with
//mDevice->getSceneManager() this gets the secen manager from mDevice. Also selcector (one mesh)
//is replaced with the mSlector (definged eirler, contains sub slectors in one big slector)



	/*
	We add a first person shooter camera to the scene for being able to move in the quake 3
	level like in tutorial 2. But this, time, we add a special animator to the
	camera: A Collision Response animator. This thing modifies the scene node to which
	it is attached to in that way, that it may no more move through walls and is affected
	by gravity. The only thing we have to tell the animator is how the world looks like,
	how big the scene node is, how gravity and so on. After the collision response animator
	is attached to the camera, we do not have to do anything more for collision detection,
	anything is done automaticly, all other collision detection code below is for picking.
	And please note another cool feature: The collsion response animator can be attached
	also to all other scene nodes, not only to cameras. And it can be mixed with other
	scene node animators. In this way, collision detection and response in the Irrlicht
	engine is really, really easy.
	Now we'll take a closer look on the parameters of createCollisionResponseAnimator().
	The first parameter is the TriangleSelector, which specifies how the world, against
	collision detection is done, looks like. The second parameter is the scene node, which
	is the object, which is affected by collision detection, in our case it is the camera.
	The third defines how big the object is, it is the radius of an ellipsoid. Try it out
	and change the radius to smaller values, the camera will be able to move closer to walls
	after this. The next parameter is the direction and speed of gravity. You could
	set it to (0,0,0) to disable gravity. And the last value is just a translation: Without
	this, the ellipsoid with which collision detection is done would be around the camera,
	and the camera would be in the middle of the ellipsoid. But as human beings, we are
	used to have our eyes on top of the body, with which we collide with our world, not
	in the middle of it. So we place the scene node 50 units over the center of the
	ellipsoid with this parameter. And that's it, collision detection works now.
	*/



		scene::ICameraSceneNode* camera =
		mDevice->getSceneManager()->addCameraSceneNodeFPS(0, 100.0f, 300.0f, -1, 0, 0, true);
	camera->setPosition(core::vector3df(0,1300,0));


	if (mSelector)
	{
		scene::ISceneNodeAnimator* animcam = mDevice->getSceneManager()->createCollisionResponseAnimator(
			mSelector, camera, core::vector3df(10,50,10),
			core::vector3df(0,-0.1,0),
			core::vector3df(0,50,0));
		mSelector->drop();
		camera->addAnimator(animcam);
		animcam->drop();
	}
}
int main()
{
	// ask user for driver

	video::E_DRIVER_TYPE driverType;

	printf("Please select the driver you want for this example:\n"\
		" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
		" (d) Software Renderer\n (e) Burning's Software Renderer\n"\
		" (f) NullDevice\n (otherKey) exit\n\n");

	char i;
	std::cin >> i;

	switch(i)
	{
		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;
		default: return 1;
	}

	// create device and exit if creation failed

	IrrlichtDevice* device =
		createDevice(driverType, core::dimension2d<s32>(640, 480));

	if (device == 0)
		return 1; // could not create selected driver.

	device->setWindowCaption(L"Load .irr file example");

	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();

	/* Now load our .irr file.
	.irr files can store the whole scene graph including animators, materials
	and particle systems. And there is also the possibility to store arbitrary
	user data for every scene node in that file. To keep this
	example simple, we are simply loading the scene here. See the documentation
	at ISceneManager::loadScene and ISceneManager::saveScene for more information.
	So to load and display a complicated huge scene, we only need a single call
	to loadScene().
	*/

	// load the scene
	CollisionMaker mk(device);
	mk.LoadScene("scenes/Scene.irr");
    std::cout<< "here at load";
	/*
	That was it already. Now add a camera and draw the scene
	*/


	// add a user controlled camera

mk.AddCollisionCam ();

	// 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)
		{
		  core::stringw str = L"Load Irrlicht File example - Irrlicht Engine [";
		  str += driver->getName();
		  str += "] FPS:";
		  str += fps;

		  device->setWindowCaption(str.c_str());
		  lastFPS = fps;
		}

	}

	device->drop();

	return 0;
}

Hi me noob so help me.
twilight17
Posts: 362
Joined: Sun Dec 16, 2007 9:25 pm

Post by twilight17 »

You didn't post the problem and/or compile errors you're getting :?
Post this userbar I made on other websites to show your support for Irrlicht!
Image
http://img147.imageshack.us/img147/1261 ... wernq4.png
radiant
Posts: 112
Joined: Fri Feb 22, 2008 8:04 pm
Location: Mexico

Post by radiant »

what u need is to post whats the error... so we all know where to look... are the nodes falling and not colliding? does your program crashes? be specific... i dont think anyone here has the time(or probably the will) to debug your code...

not trying to be rude...

but it would be best if u ask things properlly so someone here can help u faster and u can get on with your proyect

best regards
limvot
Posts: 20
Joined: Sun Sep 09, 2007 2:41 am

No error

Post by limvot »

I am not getting an error, that is valid code.

I am very sorry if i have wasted your time.

I may have posted this in the wrong forum.

What i would like is advice/ a howto/ a code snippit etc.

I want to be able to load a non octree mesh and still have accuret collision detection, not bounding box collision detection.

I need this because i am useing the Irrb exporter for blender.

It creates a .irr and the nessassery .irrmesh files.

However, .irrmesh files are not octtree meshes.

So i need a way to make regulur meshes collidible.
Hi me noob so help me.
radiant
Posts: 112
Joined: Fri Feb 22, 2008 8:04 pm
Location: Mexico

Post by radiant »

have u seen vitek's code? in that same tutorial theres a link to it... u just have to implement the parts for non-octree scene nodes.....(instead just check for non camera/light scene nodes and add collision detection for all others)
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

It sounds like you just need to add another case to deal with animated mesh scene nodes (i.e. any node created from a mesh file):

Code: Select all

      if(forSceneNode->getType()==irr::scene::ESNT_OCT_TREE)
      {
         ...
      }
      else if(forSceneNode->getType()==irr::scene::ESNT_ANIMATED_MESH)
      {
         irr::scene::ITriangleSelector* thisSelector =
              mDevice->getSceneManager()->createTriangleSelector(forSceneNode->getMesh()->getMesh(0), forSceneNode);
         //And we add it to the metaSelector
         mSelector->addTriangleSelector(thisSelector);
         thisSelector->drop();
      }
      else ...
   }
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
limvot
Posts: 20
Joined: Sun Sep 09, 2007 2:41 am

Post by limvot »

Thank you for the preposed sultion, but I get an error when i try to impliment it.

Code:

Code: Select all

void CollisionMaker::OnReadUserData (irr::scene::ISceneNode *forSceneNode, irr::io::IAttributes *userData)
{
   //if the attribute is not set, it's considered false. If it's false, we don't do anything.
   if(userData->getAttributeAsBool("Collidee"))
   {
      //Detecting node type
      if(forSceneNode->getType()==irr::scene::ESNT_OCT_TREE)
      {
         //Node is an octree, let's get mesh info
         irr::io::IAttributes *attributes = mDevice->getFileSystem()->createEmptyAttributes();
         forSceneNode->serializeAttributes(attributes);
         irr::scene::IAnimatedMesh* mesh = mDevice->getSceneManager()->getMesh(attributes->getAttributeAsString("Mesh").c_str());
         attributes->drop();
         //Creating selector based on mesh
         irr::scene::ITriangleSelector* thisSelector = mDevice->getSceneManager()->createOctTreeTriangleSelector(mesh->getMesh(0), forSceneNode, 128);
         //Adding the selector to the meta selector
         mSelector->addTriangleSelector(thisSelector);
         thisSelector->drop();
      } else {
          if (forSceneNode->getType()==irr::scene::ESNT_ANIMATED_MESH)
      {
         irr::scene::ITriangleSelector* thisSelector =
              mDevice->getSceneManager()->createTriangleSelector(forSceneNode->getMesh()->getMesh(0), forSceneNode);
         //And we add it to the metaSelector
         mSelector->addTriangleSelector(thisSelector);
         thisSelector->drop();
      } else {

         //Node isn't an octree or animated mesh, so we build a triangle selector based on bounding box
         irr::scene::ITriangleSelector* thisSelector = mDevice->getSceneManager()->createTriangleSelectorFromBoundingBox(forSceneNode);
         //And we add it to the metaSelector
         mSelector->addTriangleSelector(thisSelector);
         thisSelector->drop();
      }
      }
   }
   if(userData->getAttributeAsBool("Collider"))
   {
      //Now we animate nodes that are supposed to respond to collisions based on the metaselector
      //create an animator using the metaselector. Collision values are arbitrary. Elipsoid is made according to mesh bounding box
      irr::scene::ISceneNodeAnimatorCollisionResponse* anim = mDevice->getSceneManager()->createCollisionResponseAnimator(
         mSelector, forSceneNode, forSceneNode->getBoundingBox().MaxEdge,
         irr::core::vector3df(0,-1,0), irr::core::vector3df(0,0,0));
      //Adding the animator to the node
      forSceneNode->addAnimator(anim);

      anim->drop();
      std::cout<< "here at collider";
   }
}

the error message is "
'class Irr::scene::ISceneNode' has no member named 'getMesh'"
_________________
Hi me noob so help me.
Hi me noob so help me.
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, sorry, I didn't compile ir. You'll need to cast the node to (IAnimatedMeshSceneNode*) before doing the getMesh().
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
limvot
Posts: 20
Joined: Sun Sep 09, 2007 2:41 am

Post by limvot »

Ok, after some playing around i finally have it. Thanks so much for your help guys! :D :lol: :o :shock: :) 8) :P :wink:

Any way, you half to save meshes as animated meshes in irrEdit,
then use this code. (what rogerborg said)

Full code here!
http://limvot.x10hosting.com/tests/uplo ... lision.cpp

Code: Select all

      ...} else {
if (forSceneNode->getType() == scene::ESNT_ANIMATED_MESH)
  {
    scene::IAnimatedMeshSceneNode* msn = (scene::IAnimatedMeshSceneNode*)forSceneNode;

         irr::scene::ITriangleSelector* thisSelector =
              mDevice->getSceneManager()->createTriangleSelector(msn->getMesh()->getMesh(0), forSceneNode);
         //And we add it to the metaSelector
         mSelector->addTriangleSelector(thisSelector);
         thisSelector->drop();



      } else {...

Hi me noob so help me.
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

Great! I'm glad you got that working.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Post Reply