Bounding Boxes on Collada Objects
Andor Salga | 18 December, 2008 | 14:14
I ran into a nasty bug that has left me scratching my head recently. It involved taking the work Patrick has done on picking, more specifically his bounding box code and integrating it with Collada objects. It seemed pretty straightforward when I first started working on it, but I have had little success. Hopefully it’s just the bugs that are the causing the problem. So I decided to rewrite my initial design. After some thought I believe I have figured out what went wrong. It’s a series of problems. It starts when a call is made to Collada::getBoundingBox(). This function is defined something like this:
Therefore if the collada file has 2 nodes, one transform and one geometry, my parser adds a root node. The Collada object in memory will therefore have 3 nodes: the root with an identity, then the transform node and finally the geometry. This caused me some frustration when I tried getting the transform of the Collada object and it was returning an identity, but the object obviously wasn’t at the origin.
Halfway through my debugging I decided to add a visual box, numbers weren’t cutting it anymore. It helped me quite a bit.
Collada::getBoundingBox()
{
// The Collada object has a scene graph which always has one root.
// We pass in an identity matrix since the Root is a TransformNode
// which wants a matrix. We could also pass in null and do a check.
return sceneGraph.getRoot().getBoudingBox(identityMatrix);
}
A root node is actually just an instance of a TransformNode which main purpose is to hold a transformation matrix. Calling the TransformNode’s getBoundingBox will walk down
the graph until we reach the base case and call the GeometryNode’s getBoundingBox().
TransformNode::getBoundingBox(matrix)
{
// don’t set these to zero as the smallest vertex may actually be a
// positive number, instead use undefined to flag there are no values
// associated with these variables. This was one of my bugs.
var minVertex, maxVertex, boudingBox;
for( all child nodes)
{
// get the bounding box of all the children.
var boundingBox = child[iter].getBoundingBox(matrix * thisTransform);
// if we don’t have any values for the min and max, then use the values
// returned form the first child.
if(minVertex is not defined)
{
minVertex = new Array(boundingBox[0], boundingBox[1], boundingBox[2]);
maxVertex = new Array(boundingBox[3], boundingBox[4], boundingBox[5]);
}
else
{
for( i =0; i < 3 i++ )
{
if( boundingBox[i] < min) min[i] = boundingBox;
}
for( i =3; i < 6 i++ )
{
if( boundingBox[i] > max) max[i] = boundingBox;
}
}
}
return boundingBox;
}
The purpose of the geometry node is to store geometry, in our case it will store a Model instance, which has all the vertices.
GeometryNode::getBoudingBox(matrix)
{
var minVertex, maxVertex;
// Here was another bug. Previously I had been just getting the bounding box of the
// model (in model space), returning it, then transforming it and then finally comparing.
// The vertices need to be transformed first then compared.
for( all verts in model)
{
var v = vert * matrix;
if(minVertex is undefined)
{
minVertex = maxVertex = v;
}
else
{
for(var i=0; i < 3; i++)
{
if( v[i] < minVertex[i] ) minVertex[i] = v[i];
}
for(var i=0; i < 3; i++)
{
if( v[i] > maxVertex[i] ) maxVertex[i] = v[i];
}
}
}
return [minVertex[0], minVertex[1], minVertex[2], maxVertex[0], maxVertex[1], maxVertex[2]];
}
Going back to the scenegraph having only one root, this created some problems. When I wrote the parser, I noticed the standard allowed many nodes to be at the top level. However, I needed to have only a single root node, which would make transforming entire Collada objects simple. If a Collada object was transformed, it would just relay that transformation to the scenegraph’s root.Therefore if the collada file has 2 nodes, one transform and one geometry, my parser adds a root node. The Collada object in memory will therefore have 3 nodes: the root with an identity, then the transform node and finally the geometry. This caused me some frustration when I tried getting the transform of the Collada object and it was returning an identity, but the object obviously wasn’t at the origin.
Halfway through my debugging I decided to add a visual box, numbers weren’t cutting it anymore. It helped me quite a bit.
I’m so close, goshdarnit… 
