Horde3D

Next-Generation Graphics Engine
It is currently 25.11.2024, 08:11

All times are UTC + 1 hour




Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: 22.01.2009, 01:31 
Offline

Joined: 03.06.2008, 18:57
Posts: 19
Hello,

I have problems with conversion Collada to Horde. I have problem with facial joints. These joints have wrong position during animation (It seems that they are shifted). I was trying to look into the Collada file to see how these joints differ from other joints (which work OK) and I have found this:

Joints working correctly are defined like this:

Code:
    <node id="Pelvis-node" name="Pelvis" sid="Bone27" type="JOINT">
      <matrix>0 1 -0.000001 -0.028803 -0.004737 0.000001 0.999989 0 0.999989 0 0.004737 0 0 0 0 1</matrix>


etc.

Joints acting wrongly are defined like this:

Code:
                    <node id="Jaw_Helper-node" name="Jaw_Helper" sid="Bone103" type="JOINT">
                      <translate>0.090467 0.030082 0.000000</translate>
                      <rotate>0.579136 -0.573785 0.579114 -239.724</rotate>
                    </node>


or

Code:
                    <node id="BotLip_R-node" name="BotLip_R" sid="Bone65" type="JOINT">
                      <translate>0.072034 0.038443 -0.009772</translate>
                      <rotate>-1 0.000711 0.000708 -90.0002</rotate>
                      <node id="BotLip_C-node" name="BotLip_C" sid="Bone97" type="JOINT">
                        <translate>0.05062 0 0</translate>
                      </node>


etc.

Do you know how to fix Converter to support these Joints?

Thank you


Last edited by ii001 on 22.02.2009, 11:06, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: 22.01.2009, 03:22 
Offline

Joined: 22.11.2007, 17:05
Posts: 707
Location: Boston, MA
It might be worth a try to run your Collada file through the Collada Refinery

_________________
Tristam MacDonald - [swiftcoding]


Top
 Profile  
Reply with quote  
PostPosted: 22.01.2009, 08:14 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
Could you provide the Collada file for testing? It might be a problem in the converter when trying to create matrices. To solve your problem it might also help to enable "bake matrices" if your exporter offers this option.


Top
 Profile  
Reply with quote  
PostPosted: 29.01.2009, 17:40 
Offline

Joined: 03.06.2008, 18:57
Posts: 19
Sorry, I was busy last days so I haven't time to look at this issue. Collada Refinery tells me that everything is OK. I tried enable "bake matrices" and yes it produce nodes with correct definition but my model is still deformed during animation. I have found example where is problem even more obvious and source code where is probably solution. I have attached links to packed files where you can find Goblin.DAE. When I convert this mesh to Horde format everything looks OK but when I play animation then "neck" of goblin is much longer than should be. Packed files contain executable and source code where is animation played correctly. I am very busy during these days so I still have no time to fix this problem. I hope that next week it will be better. But meantime I will be very grateful for any idea or solution how to fix this problem.

http://benjaminnitschke.com/SkinningWithColladaModelsInXnaExecuteable.zip
http://benjaminnitschke.com/SkinningWithColladaModelsInXnaSourceCode.zip
http://benjaminnitschke.com/default,month,2007-02.aspx

Thank you


Last edited by ii001 on 21.02.2009, 23:12, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: 21.02.2009, 23:03 
Offline

Joined: 03.06.2008, 18:57
Posts: 19
I finally had time to solve this problem. Now I understand how it works much better. There is my solution:

we have to normalize weights during load of geometry. Even small error caused by small precision of uchar is visible (strange is that this problem is much more visible during software skinning (this is probably caused by FPU precision setting)). There is my patch for this problem:

egGeomery.cpp, Ln: 226 (Horde3D Beta2)

Old code:
Code:
case 5:        // Weights
    if( streamElemSize != 4 ) return raiseError( "Invalid weight stream" );
    for( uint32 j = 0; j < streamSize; ++j )
    {
        memcpy( &uc, myData, sizeof( char ) ); myData += sizeof( char ); _vertData->staticData[j].weightVec[0] = uc / 255.0f;
        memcpy( &uc, myData, sizeof( char ) ); myData += sizeof( char ); _vertData->staticData[j].weightVec[1] = uc / 255.0f;
        memcpy( &uc, myData, sizeof( char ) ); myData += sizeof( char ); _vertData->staticData[j].weightVec[2] = uc / 255.0f;
        memcpy( &uc, myData, sizeof( char ) ); myData += sizeof( char ); _vertData->staticData[j].weightVec[3] = uc / 255.0f;
    }
    break;

New code:
Code:
case 5:        // Weights
    if( streamElemSize != 4 ) return raiseError( "Invalid weight stream" );
    for( uint32 j = 0; j < streamSize; ++j )
    {
        memcpy( &uc, myData, sizeof( char ) ); myData += sizeof( char ); _vertData->staticData[j].weightVec[0] = uc / 255.0f;
        memcpy( &uc, myData, sizeof( char ) ); myData += sizeof( char ); _vertData->staticData[j].weightVec[1] = uc / 255.0f;
        memcpy( &uc, myData, sizeof( char ) ); myData += sizeof( char ); _vertData->staticData[j].weightVec[2] = uc / 255.0f;
        memcpy( &uc, myData, sizeof( char ) ); myData += sizeof( char ); _vertData->staticData[j].weightVec[3] = uc / 255.0f;

        float totalWeights = _vertData->staticData[j].weightVec[0] + _vertData->staticData[j].weightVec[1] + _vertData->staticData[j].weightVec[2] + _vertData->staticData[j].weightVec[3];

        if ( totalWeights > Math::Epsilon )
        {
            float factor = 1.0f / totalWeights;

            _vertData->staticData[j].weightVec[0] *= factor;
            _vertData->staticData[j].weightVec[1] *= factor;
            _vertData->staticData[j].weightVec[2] *= factor;
            _vertData->staticData[j].weightVec[3] *= factor;
        }
    }
    break;

This patch solves problem with my original file. But Goblin.DAE has another problem which is caused by duplicity of joint's names. I created function which detects these Joins/Meshe and creates for them new names.

ColladaConverter\converter.cpp (Horde3D Beta2)
Code:
void Converter::checkNodeName( SceneNode *node )
{
    bool jointHit = false;

    // Check Joint names
    for( unsigned int i = 0; i < _joints.size(); ++i )
    {
        if ( _joints[i]->name != node->name && strcmp( _joints[i]->name, node->name ) == 0 )
            jointHit = true;
    }

    bool meshHit = false;

    // Check Mesh names
    for( unsigned int i = 0; i < _meshes.size(); ++i )
    {
        if ( _meshes[i]->name != node->name && strcmp( _meshes[i]->name, node->name ) == 0 )
            meshHit = true;
    }

    if ( !meshHit && !jointHit )
        return;

    if( strlen( node->name ) > 200 )
        node->name[ 200 ] = 0; // Clear some space

    char newName[ 256 ];

    int count = 2;

    // Search loop
    while ( true )
    {
        bool hit = false;

        // Create new name
        sprintf( newName, "%s%d", node->name, count++ );

        // Check Joint names
        for( unsigned int i = 0; i < _joints.size(); ++i )
        {
            if ( _joints[i]->name != node->name && strcmp( _joints[i]->name, newName ) == 0 )
            {
                hit = true;
                break;
            }

        }

        if ( hit == false )
        {
            // Check Mesh names
            for( unsigned int i = 0; i < _meshes.size(); ++i )
            {
                if ( _meshes[i]->name != node->name && strcmp( _meshes[i]->name, newName ) == 0 )
                {
                    hit = true;
                    break;
                }
            }
        }

        // Is name OK?
        if ( hit == false )
            break;
    }

    char message[ 1024 ];

    // Get message
    if ( jointHit == true )
        sprintf( message, "Warning: Joint with name '%s' already exists. New name for Joint is '%s'.", node->name, newName );

    if ( meshHit == true )
        sprintf( message, "Warning: Mesh '%s' has same name as Joint. New name for Mesh is '%s'.", node->name, newName );

    // Log message
    log( message );

    // Set new name
    strcpy( node->name, newName );
}


I call this function at the beginning of the Converter::writeSGNode..
Code:
void Converter::writeSGNode( const string &modelName, SceneNode *node, unsigned int depth, ofstream &outf )
{
    // Check node name
    checkNodeName( node );
    .....

This solves problem with Goblin.DAE.

We should better normalize weights in Converter::processMeshes

Old code:
Code:
if( vertWeights.size() > 4 )
{
    v.weights[0] = 1.0f - (v.weights[1] + v.weights[2] + v.weights[3]);
}

New code:
Code:
if( vertWeights.size() > 4 )
{
    float totalWeights = v.weights[0] + v.weights[1] + v.weights[2] + v.weights[3];

    if ( totalWeights > Math::Epsilon )
    {
        float factor = 1.0f / totalWeights;

        v.weights[0] *= factor;
        v.weights[1] *= factor;
        v.weights[2] *= factor;
        v.weights[3] *= factor;
    }
    else
    {
        v.weights[0] = 1.0f;
        v.weights[1] = 0;
        v.weights[2] = 0;
        v.weights[3] = 0;
    }
}


We should sort weights every time (not only when vertWeights.size() > 4 ) because this helps as with optimization of software skinning.


Top
 Profile  
Reply with quote  
PostPosted: 22.02.2009, 22:39 
Offline
Engine Developer

Joined: 10.09.2006, 15:52
Posts: 1217
Very good, thanks a lot for investigating that problem and providing a solution!

As you propose, we really need to use proper normalization for the vertex weights. I would do that in the ColladaConverter, as you propose in your second approach. The finding with the duplicate node name is also very helpful. This will be fixed for Beta3.


Top
 Profile  
Reply with quote  
PostPosted: 22.02.2009, 23:35 
Offline

Joined: 03.06.2008, 18:57
Posts: 19
You are welcome. Horde3D Beta3 looks great. Good work everybody.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group