I do use the DOM because I like open source and standards.
That’s fair enough, I’m writing my parser/interpreter from scratch as a side project in an attempt to improve my skills. If I wanted to produce results quickly, I’d be using the DOM too ;).
I can’t afford to parse collada documents in real time - way to slow - so I don’t have a tree I build from node information in collada documents.
Instead I read the document convert the data I want from it to binary form and then use this binary info at load time.
I agree with this, the code I’m working on also converts the data to my predefined binary state before usage, although I do use a tree for ordering multiple scene objects.
More concisely I use a recursive function yo “walk” the “node tree” to the “furthest” ancestor of the “current” node and as recursive calls complete transformations from the “furthest” ancestor to the “current” node are combined. Ultimately the combined transformations are assigned to any instanced geometry attached to the current node. Using recursion in this manner should be guaranteeing me that all transformations are applied in reverse order from the greatest anscestor(root) to the current node (leaf).
I was attempting to imply that the reverse transformations are applied in reverse order only at each node location, not globally for the scene tree. For example:
<node id="TeapotParent" name="TeapotParent" type="NODE">
<rotate>1.0 0.0 0.0 -15.0</rotate>
<rotate>0.0 1.0 0.0 -45.0</rotate>
<translate>0 -5 0</translate>
<node id="Teapot" name="Teapot" type="NODE">
<translate>0 5 0</translate>
<rotate>0.0 1.0 0.0 45.0</rotate>
<rotate>1.0 0.0 0.0 15.0</rotate>
<instance_geometry url="#Teapot-mesh">...</instance_geometry>
</node>
</node>
In order would…
// ‘TeapotParent’ node:
- translate the object by -5 in the direction of the y axis to y=-5.
- rotate on the y axis by angle -45 degrees.
- rotate on the x axis by angle -15 degrees.
// ‘Teapot’ node:
- rotate on the x axis by angle +15 degrees.
- rotate on the y axis by angle +45 degrees.
- translate the object by +5 in the direction of the y axis to y=0.
Then render geometry at the resultant location (in this case I).
I personally, for my output, have chosen to bake any transform in a node location into a single transformation matrix for processing. (When baking transformations you obviously have to be aware that animations can target individual transforms from within a node, and for example, an animation may only vary a single rotational value, but I digress).
Using the above example if we name the baked ‘TeapotParent’ matrix P and the baked matrix at the ‘Teapot’ node M. The resultant matrix would be a multiplication of P x M to convert the geometry from local space to a world space.
I know you’re not going to be rendering the geometry directly from baking the transform matrices, that would be crazy, but here’s a rough implementation for what I’ve described:
// ++ Transform is a structure containing the type of transformation (translate, rotate etc.), and associated values.
// ++ Matrix is a matrix class implementation
// ++ RenderObject is a function you'd use to render your geometry
// ++ SceneTree is a scene structure you could probably replace with the dom equivalent
SceneTree g_sceneTreeObj; // Visual Scene Tree Storage
// input: a vector containing the transformations of the current node
// returns: a matrix of the combined transforms
Matrix BakeTransforms( vector<Transform>& input )
{
Matrix tempMatrix;
for( each transform in **reverse order** for the vector 'input' as 'revIter' )
{
switch( an enum variable specifying the type of transform from 'revIter' )
{
case: a matrix transformation
{
tempMatrix *= revIter->matrixValue;
}
break;
case: a roation transformation
{
tempMatrix *= CreateRotationMatrix( revIter->roationAxis, revIter->roationAngle );
}
break;
// ....... ETC .......
}
}
return tempMatrix;
}
// input: the current node to process
void ProcessNodeWithRender( SceneNode currentnode )
{
Matrix localTransform = BakeTransforms( currentNode.transformationStorageVector );
Push the current graphical api modelview matrix onto the stack.
Multiply the current graphical api modelview matrix by 'localTransform'
for( all objects stored locally in 'currentNode' as 'obj' )
{
RenderObject( obj );
}
for( all children of 'currentNode' as 'child' )
{
ProcessNodeWithRender( child );
}
Pop the current graphical api modelview matrix off the stack, returning the transformation to it's previous state.
}
void MyRender( void )
{
ProcessNodeWithRender( g_sceneTreeObj.rootNode );
}
I can’t help with the DOM ‘transparent’ issue though I’m affraid.
Good luck with that,
Regards,
Adam