Opcode: turning a ray collision into an intersection point

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
Post Reply
sirSolarius
Kobold
Posts: 36
Joined: Fri May 27, 2005 11:34 pm

Opcode: turning a ray collision into an intersection point

Post by sirSolarius »

I've been getting pretty frustrated with Opcode, but I think I'm close to getting what I need.

What I want to do is to load a walkmap .mesh into Ogre and perform ray collisions on it to determine if my character can walk to a certain place (and where to move him, ie up a ramp).

I basically copy-pasted the OgreOpcode code to load an Entity into Opcode, but now I don't understand how I can turn the results of a ray collision into an intersection point.

Here is what I have:

Code: Select all

bool CollisionManager::RayCollide(const Vector3 &start, const Vector3 &end, 
													MeshCollider *mesh, Vector3 &intersect)
{
	RayCollider RC;
	RC.SetFirstContact(true);
	RC.SetClosestHit(true);
	RC.SetCulling(true);
	RC.SetTemporalCoherence(false);
	RC.SetMaxDist( (end-start).length());

	CollisionFaces CF;
	RC.SetDestination(&CF);

	RC.SetCallback(collisionCallback, (udword)mesh);

	// We know that there is only one subentity per entity
	IceMaths::Matrix4x4 opWorld; 
	mesh->GetWorldMatrix(&opWorld);

	IceMaths::Ray ray(start, (end-start).normalisedCopy());
	RC.GetNbIntersections();

	bool isOK = collider.Collide(ray, mesh->mCollisionModel, opWorld, mColCache);
	if(!isOk)
	{
		ErrorManager::SendError(false, "Collision error!");
		return false;
	}
Thanks!
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Post by jacmoe »

You should call RC.GetNbIntersections(); after your call to collider.Collide - and you should loop through CollisionFaces (through CF) to see the results.
You also need a function to extract the hit vertices from your mesh data from the returned index.
Take a closer look at OgreOpcode. :wink:
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
sirSolarius
Kobold
Posts: 36
Joined: Fri May 27, 2005 11:34 pm

Post by sirSolarius »

Ok, well if I can find out the triangle then I can use ray-triangle collision to find the intersection point.

Looking at the SourceForge CVS, it seems that OgreOpcode just does a boolean test like "does A overlap B?" rather than "where does A intersect B?" So OgreOpcode doesn't seem to help with this question.

Looking through Opcode, a CollisionFaces object returns an array of CollisionFace objects. Each CollisionFace object then has a few details, one of them being faceID. Thanks to the kind folks at Opcode, there is absolutely no documentation on this. What do I do from here to return the 3 points of the stabbed triangle?
sirSolarius
Kobold
Posts: 36
Joined: Fri May 27, 2005 11:34 pm

Post by sirSolarius »

Ok, well here's my function. Is this the correct usage of the faceid?

Also, excuse the loop that terminates after one iteration... I'm going to be expanding it but I need to make sure it works first =)

Code: Select all

bool CollisionManager::GetIntersectPoint(const Vector3 &start, const Vector3 &dir, 
							MeshCollider *m, Opcode::CollisionFaces *cf, Vector3 &intersect)
{
	int num=cf->GetNbFaces();
	const Opcode::CollisionFace *f=cf->GetFaces();

	for(int i=0; i < num; ++i)
	{
		int index=3*f[i].mFaceID;
		/******************************************************************************/
		/************* THIS IS GHETTO CODE- No idea what index is used for! ***********/
		IceMaths::Point p1=m->mIndexList[index], p2=m->mIndexList[index+1], 
																p3=m->mIndexList[index+2];
		/******************************************************************************/

		Vector3 v1(p1.x, p1.y, p1.z), v2(p2.x, p2.y, p2.z), v3(p3.x, p3.y, p3.z);
		
		Ogre::Plane pn(v1, v2, v3);
		Ogre::Ray r(start, dir);
		std::pair<bool, Real> info=r.intersects(pn);
		float t=info.second;

		intersect=r.getPoint(t);
		return true;
	}
	return false;
}
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Post by jacmoe »

You retrieve the three vertices like this:

Code: Select all

/// Extract triangle coordinates from triangle index.
inline void CollisionShape::GetTriCoords(int index, Vector3& v0, Vector3& v1, Vector3& v2)
{
      int* indexPtr = &(faceData[3 * index]);
      float* vp0 = &(vertexData[3 * indexPtr[0]]);
      float* vp1 = &(vertexData[3 * indexPtr[1]]);
      float* vp2 = &(vertexData[3 * indexPtr[2]]);
      v0 = Vector3(vp0[0], vp0[1], vp0[2]);
      v1 = Vector3(vp1[0], vp1[1], vp1[2]);
      v2 = Vector3(vp2[0], vp2[1], vp2[2]);
}
In other words: the index from facedata is an index into the indexed mesh data.
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
sirSolarius
Kobold
Posts: 36
Joined: Fri May 27, 2005 11:34 pm

Post by sirSolarius »

Sorry, but where do I get the faceData array from? Looking at your OgreCollisionEntity class, I only see mIndexList and mVertexList (here).

I basically just used your code to load an Entity into Opcode, so I am also missing this array.
User avatar
okki
Halfling
Posts: 90
Joined: Mon Jan 03, 2005 3:14 pm
Contact:

Post by okki »

take a look at jacmoe's postings at https://developer.berlios.de/project/sh ... up_id=3423 and the OgreOpcode::OgreCollisionShape->load(). it refers to the getMeshInformation function :)
hth
- ogre4j.org -
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Post by jacmoe »

@sirSolarius:
There's two versions of OgreOpcode: one from ogreaddons CVS (which works with Opcode 1.3 using my patch) and the WIP from Berlios, which I posted a link to in the other opcode thread in general discussion.
If you are using the ogreaddons version, which you are, the code for getting the tricoords is available from the callback:

Code: Select all

  udword* indexList = obj->getIndexList();
  Point* vertexList = obj->getVertexList();

  unsigned int index = triIndex * 3;

  triangle.Vertex[0] = &vertexList[indexList[index]];
  triangle.Vertex[1] = &vertexList[indexList[index + 1]];
  triangle.Vertex[2] = &vertexList[indexList[index + 2]];
:wink:
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
Post Reply