Game Development Community

Custom Collision in T3D

by Jack Stone · in Torque 3D Professional · 12/07/2014 (7:02 am) · 16 replies


Hello,

I am currently working on a Spherical Terrain implementation in T3D, which I posted about here:


http://www.garagegames.com/community/forums/viewthread/140267/2


I have achieved quite a lot, such as generating a quad sphere, applying a noise function, and applying procedural texturing.

Now comes one of the hardest parts: Collision.

Eventually, I want to have support for very large terrains, which will involve complicated paging/LOD's/Optimisations, however I want to start with a smaller terrain, and implement basic collision with the player object only.

I have looked through the engine codebase, but the collision system is unfortunately as complex as I suspected.

What I am looking for is an example of very simple collision that I can modify, similiar to the "rendermeshexample" which I based my spherical terrain on, however, the collision system seems to all be tied up in shapebase, there doesn't seem to be an isolated example.

Does anyone have any advice or information for a basic collision concept system that I could modify? Trying to get my head around this is proving difficult.

Thanks!

#1
12/07/2014 (7:04 pm)
We have just the thing for you buried somewhere in this thread. First, take a look at the collision overview on the wiki for a broad introduction, keeping in mind it may be slightly outdated. Then go through that thread from where I linked - you might have to step backwards a bit to understand the context. The final result is here if you just want to look at code. It's basically RenderMeshExample plus collision and networking. Should give you a good place to start.
#2
12/08/2014 (5:04 pm)
Ah, thank you, that is excellent information! I have implemented what I think is a correct solution based on "cubes.cpp", however, I'm still not getting collision.

Am I to infer that the collision hull is created in build convex, and collision is then detected in cast ray?

What I'm trying to do, and this is just for testing, is this:


bool SphericalTerrainExample::castRay( const Point3F &start, const Point3F &end, RayInfo *info )
{
   info->t = 1;
   // Used for its utility method, collideLine, which you'll see below.
   Box3F cube;
   // Position along the ray that we hit (0 is the start, 1 is the end).
   F32 t = 1.0f;
   // Normal vector of the ray collision.
   Point3F n= Point3F(0,0,0);
   // Did any of the cubes get hit?
   bool hit = false;
 
   //return true if user is within a certain distance of the origin:

   Con::printf("TERRAIN: %f %f %f %f %f %f" , start.x,start.y,start.z, end.x,end.y,end.z);
		

   cube.set(Point3F(0,0,0), Point3F(0,0,0) + Point3F(1, 1, 1));
   if(cube.collideLine(start, end, &t, &n))
   {
	      Con::printf("TERRAIN!");
	   hit = true;
	   info->t = t;
	   info->normal = n;
	   info->material = NULL;//mMaterialInst;
	   info->object = this;

   }


   // Return true if one of our cubes was hit.
   return hit;
}
 
// Collision: The point of this function is to return a very simple
//   version of the geometry optimized for collision detection.
void SphericalTerrainExample::buildConvex( const Box3F& box, Convex* convex ) 
{
	// I have no idea what this does.
   mConvexList->collectGarbage();

   //create a single collision cube and return it:

   BoxConvex *boxConvex = NULL;

   CollisionWorkingList &wl = convex->getWorkingList();
      CollisionWorkingList *itr = wl.wLink.mNext;


	  for ( ; itr != &wl; itr = itr->wLink.mNext )
      {
         if (  itr->mConvex->getType() == BoxConvexType &&
               itr->mConvex->getObject() == this)
         {
 
            break;
         }
      }


	   // If we didn't find a convex in the cache, create one.
      if ( !boxConvex )
      {
         boxConvex = new BoxConvex;
         mConvexList->registerObject( boxConvex );
         boxConvex->init( this );
 
         // Store the cube index.
         //boxConvex->cubeIndex = n;
 
         // Add our cube to the return geometry.
         convex->addToWorkingList( boxConvex );
      }
 
      // Update the convex
      if ( boxConvex )
      {
		   boxConvex->mCenter  = Point3F(0,0,0);
		    boxConvex->mSize    = Point3F(100.0f,100.0f,100.0f);
      }
   }

My quad sphere is centered around the origin, and I am just trying to create a convex box in that location for collisions. Everything compiles and runs, but there is no collision, and the check here: " if(cube.collideLine(start, end, &t, &n))" fails.

I am sure I am doing something fundamentally wrong here, since I'm not at all familiar with T3D's collision system, or collision detection in general.
#3
12/08/2014 (6:53 pm)
Don't have time to check code right now, but maybe the wiki should be clearer. castRay and buildConvex are for two different types of collision, convex hull and raycasts. Players, for example, move around represented by a big box (a convex hull), whereas projectiles just cast rays, which have 0 width. Raycasts are typically used for 'line of sight' type calculations, whereas hulls are for actual physical objects.
#4
12/10/2014 (4:20 pm)

Thanks Daniel, I had a good look through the wiki, and I managed to get the boxConvex Collision working.

Now, the tricky part, which is to get the spherical terrain collision working. I guess, the best way would be to select a subset of the polys on the sphere close to the player, and return those in buildConvex?

#5
12/10/2014 (4:47 pm)
Yup. Actually you might research buildPolyList; I've forgotten whether it's used for collision. But the idea is that buildConvex takes a query box, and you can just return geometry that overlaps that box.
#6
12/12/2014 (2:22 pm)
That's exactly what I did, but I found buildPolyList() required a shape instance for a call to "buildPolyListOpcode" so I am working with getPolyList() instead, this seems to just require a list of vertices.

For the moment, I am planning to just add all of the vertices in my mesh to getPolyList().

I am not sure how to use this poly list for collision then, I have a simple boxConvex working in buildconvex, do I modify buildConvex() to use the more complex geometry that I created in getPolyList? Or is get polylist separate from build convex?

I am slowly making progress with the collision system, but there are still many gaps in my knowledge.


#7
12/17/2014 (9:34 pm)
I have been working on this for some time, and I can't seem to get my head around the polysoup collision. I gather the "opcode" build convex functions are the key to this, but they all seems to rely on a TsStatic instance.

I can't seem to figure out how to get polysoup collision working with a vertex list, and not an actual mesh. Is this possible?
#8
12/18/2014 (1:29 am)
How does the Terrain do it? I imagine it's eminently possible, but I've never tried it myself.
#9
12/18/2014 (6:09 pm)
The Terrain system used it's own Convex Object type, called "TerrainConvex". I had looked at this first, but didn't get very far with it, so I was working on modifying TsStatic's system.

I have modified BuildConvex from the terrain system to compile in my spherical Terrain Code:



http://paste.ofcode.org/35DZAVQqKKCQp3tNeEtxd7B



It seems to iterate through the entire terrain and add discrete points to the Terrain convex. Would I be right in assuming that modifying that nested for loop and adding in my points from the vertex buffer would produce a collision object usable to T3D?

I am about to try it, and I'll report back, but I wanted to know if I am way off base here first.
#10
12/20/2014 (10:36 am)
@Daniel:

I found your very useful fxRoad resource on an archive site, which contains a convex object called "triangleConvex". This seems to be exactly what I need, and I implemented it successfully in my codebase.

However, I am still not getting working collision. What I am doing in buildConvex is:

if(i < tempvec.size()){
			
	    //New convex
            TriangleConvex* cp;
            //Make a convex for each triangle: top surface
            cp = new TriangleConvex();
            cp->setObject(this);

            cp->set(tempvec[i],tempvec[i+2],tempvec[i+1]);
	    convex->addToWorkingList(cp);
			
	}

This seems simple enough, is there something I am missing? Is there some kind of initial prep work that's needed to get convex shapes working?
#11
12/20/2014 (5:48 pm)
I have made some progress with this. I have created a collision mesh, and I can see it in the editor when I turn on "view player collision". Also, items can collide with it (when static is turned off), but bizarrely, players fall through?

Any idea why item collision works when player collision doesn't?

Some pics and a description are here:


http://phoenixgamedevelopment.com/blog/?p=1180
#12
12/20/2014 (7:12 pm)
Interesting- Player and Item use very similar collision code IIRC. What typemask bits does your new class have? EDIT: also, surely that should be
if (i+2 < tempvec.size())
#13
12/21/2014 (8:53 am)
Yes, indeed it should, good catch!

My type masks are set to:

mTypeMask |= StaticObjectType | StaticShapeObjectType;

The player seems to behave differently when encountering static objects:

if ((pConvex->getObject()->getTypeMask() & StaticObjectType) != 0 && !skip)
      {
         Box3F convexBox = pConvex->getBoundingBox();
         if (box.isOverlapped(convexBox))
            pConvex->getPolyList(&polyList);
      }
      pList = pList->wLink.mNext;
   }

However changing the type masks doesn't seem to help fix this. I tried removing staticobjecttype, and adding terrainobjecttype, but no luck. I'll keep fiddling with it!
#14
12/21/2014 (3:59 pm)
I have now tried every typemask, and still no player collision. What I have noticed though, is that in some areas of the mesh, the player seems to collide briefly, then pass through. Almost like there is something there to collide with, but it isn't properly stopping the player?
I am not sure what could cause that (I checked the winding order of the vertices), and I'm not sure why Item's would still work...

I am very close to figuring this out!
#15
12/21/2014 (5:39 pm)
Bizarre. And you mentioned that the Player collision debugging visualisation seems to look correct? I might give this a go today and see if I can get custom shape collision working reasonably...
#16
12/21/2014 (8:15 pm)
Yeah, I spent all day working on this, and it just seems like something obvious that I can't figure out.

The collision mesh looks fine, I have some pics here:


http://phoenixgamedevelopment.com/blog/?p=1180


Seems ok to me, but there is possibly some distortion to parts of the mesh?

If it works ok for items, I can't see why the player is falling through.

If you try it, let me know how you get on, I might be missing something obvious.