Game Development Community

dev|Pro Game Development Curriculum

Auto Bounds

by Duncan Gray · 05/15/2007 (8:54 am) · 11 comments

add the following to the TSShapeinstance class in TSShapeinstance.h
void computeBounds(const VectorF &WorldScale, Box3F &LocalBounds);
add the following to TSShapeinstance.cc
void TSShapeInstance::computeBounds(const VectorF &WorldScale, Box3F &LocalBounds)
{
	// this method is called by both client and server, once per tick

	S32 dl=getCurrentDetail();  //  or you can also specify a different detail, for instance,
	// you may construct a very low poly mesh purely for the purpose of getting the bounds
	// in which case you need to set dl to whatever detail to use
        // (your lowest LOD would be clever...)


    animate(); // strike a pose from the current timescale of the current animation thread

   // get subshape and object detail
   const TSDetail * detail = &mShape->details[dl];
   S32 ss = detail->subShapeNum;
   S32 od = detail->objectDetailNum;

   // set up static data
   setStatics(dl);

   S32 start = mShape->subShapeFirstObject[ss];
   S32 end   = mShape->subShapeNumObjects[ss] + start;

   // run through objects and updating bounds as we go
   Box3F bounds;
   bounds.min.set( 10E30f, 10E30f, 10E30f);
   bounds.max.set(-10E30f,-10E30f,-10E30f);
   bool complete=false;
   for (S32 i=start; i<end; i++)
   {
	   MeshObjectInstance * mesh = &mMeshObjects[i];
	   if (od >= mesh->object->numMeshes)
		   continue;  

	   if (mesh->getMesh(od))
	   {		   
		   TSMesh *m = mesh->getMesh(od); 
		   MatrixF LocalTransform;	  
		   /*
		   S32 groundNode = getShape()->findNode("Ground");
		   if(groundNode > 0)				
		       LocalTransform.mul(*mesh->getTransform(), mNodeTransforms[groundNode]);
		   else  */
			   LocalTransform = *mesh->getTransform(); 
           
                   // for the player class, we only care about skin mesh
		   if (m->getMeshType()==TSMesh::SkinMeshType)
		   {
			   TSSkinMesh * skin = (TSSkinMesh*)m;
			   skin->updateSkin(); // this will move the vertices into the currecnt pose
			   Point3F p;
			   for (S32 vert=0; vert< m->vertsPerFrame; vert++)
			   {
				   LocalTransform.mulP(m->verts.address()[vert],&p);
				   bounds.max.setMax(p);
				   bounds.min.setMin(p);
			   }
                           complete=true;
		   }
	   }
   }
   clearStatics();
   
   bounds.min.convolve(WorldScale);
   bounds.max.convolve(WorldScale);
   if(complete)
      LocalBounds = bounds;
   
}
In player.cc, locate Player::processTick and right at the top of the method add
mShapeInstance->computeBounds(getScale(), mObjBox); //duncan autobounds
resetRenderWorldBox(); //duncan autobounds
resetWorldBox();  //duncan autobounds
onScaleChanged(); //duncan autobounds


Thats all you need to change.

This method does add a slight bit more CPU time to the process tick method, so ideally you should move the updateTick additions to a location where they will only be called when you change a player position or scale etc.

Having an always accurate bounds box can have advantages in reducing time in other functions like cast-ray etc.

So comment out any bounds box modifying code from those other resources if you are using them.

For the Custom Shape Mod people, scaling everything from the waist up works fine. Scaling the legs up will have you players feet sticking through the terrain until you perform a jump which will sort out the problem.

It's probably possible to add a Z offset to the transform equal to the amount to scaled up by which should raise the player back up to ground level, but I have not played with that yet. If you get a neat solution, let me know.

#1
04/24/2007 (10:26 pm)
More background here and pictures
and here
Custom Shape Mod

Crouch, prone, swim resources
original
Updated
#2
05/01/2007 (12:10 pm)
Awesome concept! Instead of every tick for performance, how about adding in the call to computeBounds whenever the objbox changes? Like in the aforementioned scale or position changes.
#3
05/01/2007 (2:29 pm)
You are correct in your assesment. My reasoning was in trying to satisfy two resources with one solution.

It work fine in the setPlayerPosition method of the crouch-prone resource and would give better performance if placed there.

I was considering the guys using the Custom Shape Mod where you can scale your character proportions anywhere anytime. Even then it would be better/more efficient to make the compute bounds call only when a player does a scale change, rather than in every tick.

But that would complicate the resource.

If you know the code well enough, then only make the compute bounds call where and when you need it.
#4
05/07/2007 (12:33 pm)
#5
06/20/2007 (11:46 pm)
Battlefield Torque BFT has an updated and more robust version of this resource in it.
#6
08/13/2007 (2:21 pm)
Not quite sure why this resource didn't work in version 1.5.2 (kept getting overload errors). But anyway, I had to add the following in tsShapeInstance.h

virtual void computeBounds (const VectorF &WorldScale, Box3F &LocalBounds);

Don't know how safe this is though.
#7
08/13/2007 (5:29 pm)
Hi Andy, TGE does not rotate the player collision mesh by default so just adding Autobounds is not enough in most cases. You will therefore also need to make other changes in player.cc to get the collision code working with it.
#8
11/01/2007 (12:42 am)
I want to use this resource in TGEA.But I found that it's doesn't work,The App crashed in this:

...
LocalTransform = *mesh->getTransform();
...

If the shape type is SkinType,LocalTransform is NULL,and the getTransform() function is :

inline MatrixF * TSShapeInstance::ObjectInstance::getTransform()
{
return nodeIndex<0 ? NULL : smTransforms + nodeIndex;
}

the nodeIndex is -1, so LocalTransform is NULL:-(

What's the problem?Is it enough that just call computeBounds() function every tick,without redraw boundbox render?
#9
12/10/2007 (5:06 am)
The same problem with TGE1.5.2(it crashes when executing "LocalTransform = *mesh->getTransform();
"),

Anybody may help with this?

Thanks
#10
06/10/2008 (9:29 pm)
I would like to use this for the positions resource as well, the resource Duncan linked to is good but not as robust as I would like it to be sice you tend to get oversized boxes or weapons that cut out at different angles if the box isn't sized correctly. Has anyone gotten this to work well wit TGEA 1.03? Additionally does anyone know if there is a way to add the size of the mounted image(s) into the calculation?
#11
05/02/2015 (12:18 am)
In case anyone is looking at this in 2015, you only need to add the following to Player:processTick in order to get this to work in T3D 3.7:
mShapeInstance->computeBounds(mShapeInstance->getCurrentDetail(), mObjBox);
resetRenderWorldBox();
resetWorldBox();