Collada Loader - missing geometry - Please Help

Hello,

I have been desperately trying to fix an issue where my collada loader doesn’t not load all the geometry found in my collada documents.

I am using the Collada DOM.
I am using the Collada refinery conditioners/macros: toTriangles, deindexer

To begin some questions:

I use this to capture all defined meshes in a document:
daeDatabase *db(dae.getDatabase());
db->typeLookup<domMesh>();

Will this capture all defined meshes?

I use this to capture all defined triangles for each mesh:
mesh->getChildrenByType<domTriangles>();

I use this to capture all defined domNodes in a document:
db->typeLookup(domNode);

I capture all domNodes because they own 3D transformations.

Here is how I assign transformations to triangle meshes:

  1. Eliminate nodes which don’t have at least one instance_geometry child
  2. extract the transformation information for each domNode that passes the test
  3. for each domNode that passed test if it has a parent domNode
  4. a) if yes - recurse extract transformation information for ancestor node
  5. b) if no - stop recursion
  6. Combine all transformations from ancestors and that of current domNode.
  7. Assign transformations to the instanced geometry.

The problem is that I often have missing geometry. Either the geometry is transformed to some position in 3D space I can’t see or it was never captured from my dae files.

Can someone have a guess as to what I’m doing wrong?

Is this place abandoned?

I, too, am left wondering if these forums have been abandoned, based not only on the lack of replies, but on the low number of views for new posts.

If this is not the place to ask Collada questions then I want to know where I should go.

Consequently, I would like to know where and how to submit Collada bug reports as well.

I don’t use the dom, so can’t really help with that (don’t ask, I decided it might be fun to implement an importer from scratch, I’m still going at it).

Ok, I’m going to make the assumption you have some tree like structure you can navigate through. Also I’m going to assume you’re using some sort of transform stack (for my attempt at an explanation of what you should be doing/getting).

Ok, here’s the process, I know this is straight forward (and I’m not trying to be disparaging), but here’s how you should be processing the nodes.

Process:
Without eliminating any nodes (just to rule this out as a problem), start at the tree root and apply transformations in the root node, then multiply this with the current transform matrix (identity at root), push the result onto the transformation stack.

Next, attempt to render any geometry at the location.

For your child nodes perform the above processing for each and repeat, multiply the current transform with the node’s transform and push this onto the stack, render any geometry etc.

At the end of processing each child node, pop the transform you’ve applied from the stack and return.

Note!
If you have transforms listed something like the following for example:

<node id="Teapot" name="Teapot" type="NODE">
<translate>6 29 0</translate>
<rotate>1.0 0.0 0.0 15.55</rotate>
<rotate>0.0 1.0 0.0 57.86</rotate>
<rotate>0.0 0.0 1.0 -144.25</rotate>
<translate>1 2 3</translate>
<instance_geometry url="#Teapot-mesh">
</node>

Remember that you must combine these in reverse order to apply the transform correctly. I.e. Translate(1,2,3) will be first followed by the z-axis Rotate and so-on.

I know this isn’t exactly a dom description (and was written in a rush as I’m required at the gym about now), but I hope it helps a little.

Best of luck,
Adam

(You have to be prepared to sometimes wait a few days on these forums for a reply [I’ve found from experience], the good news is, a reply will almost always come eventually.)

Here, is the bugzilla link.

Regards,
Adam

Admin: the link provided is for COLLADA specification and schema bugs, not for COLLADA DOM or Refinery bugs.

I do use the DOM because I like open source and standards.

Anyhow :wink:

I don’t store a tree structure at all.

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.

When it comes to transformations I attempt to take advantage of the tree system already in place in the collada spec for nodes.

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 parse every node that instances geometry with this:

static void SetTransforms(
        domNode *node,
        VECTOR3 &translation,
        VECTOR3 &orientation,
        VECTOR3 &scaling)
{
        VECTOR3 ancestorTranslation(0,0,0);     //identity
        VECTOR3 ancestorOrientation(0,0,0);     //identity
        VECTOR3 ancestorScaling(1,1,1);         //identity

        if (node->getAncestor("node") != 0)
        {
                //the transformations of an ancestor are required - recurse
                //////////////////////////////////////////////////////////////////////////
                SetTransforms(
                        static_cast<domNode*>(node->getAncestor("node")),
                        ancestorTranslation,
                        ancestorOrientation,
                        ancestorScaling);
        }//end if

        /************************************************************************/
        /* ancestor transformations are complete                                */
        /************************************************************************/

        if (node->getChildrenByType<domMatrix>().getCount())
        {
                // all transformations are in a matrix
                //////////////////////////////////////////////////////////////////////////
                ParseMatrix(
                        node,
                        orientation,
                        translation);
        }
        else
        {
                // parse rotations
                //////////////////////////////////////////////////////////////////////////
                ParseOrientation(
                        node,
                        orientation);

                // parse translation
                //////////////////////////////////////////////////////////////////////////
                parseTranslation(
                        node,
                        translation);

                // parse scaling
                //////////////////////////////////////////////////////////////////////////
                parseScaling(
                        node,
                        scaling);
        }//end if

        /************************************************************************/
        /* current node transformations complete                                */
        /************************************************************************/

        // combine ancestor and current node transformations
        //////////////////////////////////////////////////////////////////////////
        translation += ancestorTranslation;

        CombineRotations(ancestorOrientation,orientation);

        scaling[0] *= ancestorScaling[0];
        scaling[1] *= ancestorScaling[1];
        scaling[2] *= ancestorScaling[2];
}

As for my error:

It relates the the “phong” element of “domProfile_COMMON” specifically the child element “transparent”. For some reason the “transparent” element isn’t being detected as a “domCommon_color_or_texture_type” so I have to wade through some indirection to get the element. When I try to get the character data from the “color” child of “transparent” I get memory access violations from the DOM.

I had this issue with the previous release of the DOM minus the memory access violations. With the latest release of the DOM I have to avoid parsing the “transparent” element all together or suffer a crash of the DOM and my application.

I am not convinced this is a DOM error but at the moment I have no other plausible explanations.

Here, is the bugzilla link.

Regards,
Adam[/quote]

Thank you very much Adam.

Admin: the link provided is for COLLADA specification and schema bugs, not for COLLADA DOM or Refinery bugs.

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

Links to:

The COLLADA DOM bug tracker
The COLLADA Refinery bug tracker

Rather than use domCommon_color_or_texture_type for transparent, usedomCommon_transparent_type, that one caught me out as well.