Inside Sabertooth
Learn how Sabertooth uses 3ds Max to create 3D interactive projects, including HBO Go’s Game of Thrones interactive experience
  • 1/3
You are here: Forum Home / Autodesk® FBX® / FBX SDK / Skinning Data
  RSS 2.0 ATOM  
2 pages: 1.2 last

Skinning Data
Rate this thread
 
42196
 
Permlink of this thread  
avatar
  • L. Spiro
  • Posted: 19 April 2010 08:42 PM
  • Total Posts: 37
  • Joined: 09 April 2010 03:01 AM

After my converter (from FBX to my engine’s native format) was finished I noticed a lot of (but not all of) my animations were screwed.
The joints seem to have been converted correctly, so my primary idea is that I have not connected the skins correctly.

My code and a detailed explanation of my algorithm are here:
http://codepad.org/Mb32ao5e

I simply want to store an array such that each element in the array contains the skinning data (weight + bone-index pair) for that vertex/control point.

That is, if I have 500 vertices (control points connected by polygons to make the final object) then my array will have 500 elements, and array[230] will contain all of the influences (bone+weight) for control point #230.

Is my code doing this?
Or do I need to transform the control-point index one more time?
For example, the index of normals depends on the mapping mode.  Perhaps, once I perform this:

iInf.ui32VertIndex pcCluster->GetControlPointIndices()[K]

I need to enter a switch based on the mapping mode (of something) and convert iInf.ui32VertIndex once more to the final result.

Is there anything wrong with my concept or execution?

Regards,
L. Spiro



Replies: 1
/userdata/avatar/c6y2tieph_fbx.png

I’m not able to open your link and see your code:(
Is there any other way to let me know your code sample?
Or you can send me email:

Author: Zhihao.Li

Replied: 20 April 2010 10:23 PM  
avatar
  • adario
  • Posted: 21 April 2010 12:50 PM

Zhihao,

I have the exact same problem as the original poster—I am posting the code below in case you still can’t access the link… I hope the original poster won’t mind.  Essentially the sample code just reads the (index,weight) pairs for all clusters and skins.

After reading this information in the same way and applying it to our own scene graph, the problems mentioned by the original poster appear in our application as well: some joints are displayed correctly, others are not.  I should mention that we are using GetTransformLinkMatrix to apply the deformations…

Any ideas?

Thanks,
Dario

LSSBOOL LSSTD_CALL CSkinData::ExtractSkin( const KFbxMesh &_mObj ) {
        KFbxCluster 
pcCluster;
        
LSSUINT32 ui32TotalSkins _mObj.GetDeformerCount( KFbxDeformer::eSKIN )


        
for ( LSSUINT32 I 0ui32TotalSkins; ++I ) {
            KFbxSkin 
psSkin reinterpret_cast<KFbxSkin *>(_mObj.GetDeformer( IKFbxDeformer::eSKIN ))
            m_sName 
psSkin->GetName()
            LSSUINT32 ui32ClusterCount 
psSkin->GetClusterCount()

            
// Fill out enough influences to cover the whole geometry.
            
m_vInfluenceLists.Resize( _mObj.GetPolygonVertexCount() )

            
for ( LSSUINT32 J 0ULui32ClusterCount; ++J ) {
                pcCluster 
psSkin->GetCluster( J )

                
if ( pcCluster->GetLink() ) {
                    m_vJointNames
.Push( pcCluster->GetLink()->GetName() )


                    LSSUINT32 ui32Points 
pcCluster->GetControlPointIndicesCount()

                    
static LSSBOOL bWarnedPoints false;
                    if 
( ui32Points >= m_vInfluenceLists.Length() ) {
                        
if !bWarnedPoints ) {
                            CStd
::DebugPrintA( "Skinning data in FBX file is corrupted (influences are larger than the number of vertices).  Model may not appear correctly.\r\n" )
                            bWarnedPoints 
true;
                        
}
                        
                        
// Cap the number of points.
                        
ui32Points m_vInfluenceLists.Length()
                    }
                    
for ( LSSUINT32 K 0ULui32Points; ++K ) {
                        
// If there is actually a weight value here, add it.
                        
if ( pcCluster->GetControlPointWeights()[K] 0.0 ) {
                            LSFBX_INFLUENCE iInf
;
                            
iInf.fWeight static_cast<LSSFLOAT>(pcCluster->GetControlPointWeights()[K])
                            iInf
.ui32VertIndex pcCluster->GetControlPointIndices()[K];

                            
// Apparently some FBX files can contain invalid data here.
                            //  One of my test files was giving me vertex indices in the range of 4,000+ when there were actually
                            //  only 2,000 vertices in the whole file!
                            // Print a warning but don't crash or stop.
                            
static LSSBOOL bWarned false;
                            if 
( iInf.ui32VertIndex >= m_vInfluenceLists.Length() ) {
                                
if !bWarned ) {
                                    CStd
::DebugPrintA( "Skinning data in FBX file is corrupted (influences reference non-existant vertices).  Model may not appear correctly.\r\n" )
                                    bWarned 
true;
                                
}
                                
continue;
                            
}
                            iInf
.ui32Index J;
                            
m_vInfluenceLists[iInf.ui32VertIndex].Push( iInf )
                        }
                    }
                }
            }

            
return true;
        
}


        
return true;
    
}


Replies: 1
/userdata/avatar/c6y2tieph_fbx.png

Got it. Thank you adario. I’m looking into the question.

Author: Zhihao.Li

Replied: 22 April 2010 11:10 PM  
avatar
  • L. Spiro
  • Posted: 23 April 2010 02:31 AM

No I don’t mind, especially if it helps to find a solution.
I just posted it on the other site thinking it was a bit bloated for here, but it seems not so bad.

Regards,
L. Spiro



Replies: 0
avatar

Can someone post an example of a .fbx file that does not work?  I can test it with my importer.



Replies: 0
avatar
  • L. Spiro
  • Posted: 24 April 2010 07:49 PM

The file fails pretty hard for me.

http://memoryhacking.com/Misc/TestData.rar

Regards,
L. Spiro



Replies: 0
avatar

This .fbx file animates in my import app the same way it does in Maya, so I suspect your import code.  I’ll take a look at it soon.

My viewer app is in pieces right now, but you can see it in wire frame (attached).  Hit ‘f’ for wireframe. F1 for some more controls. WASD navigation.



Attachment Attachment
Replies: 0
avatar

I suspect that you are splitting verts because some elements have KFbxLayerElement::eBY_POLYGON_VERTEX specified (like different normals for the same position)

You have to remap the split vert indices back to the original control points for the skinning to work.



Replies: 0
avatar
  • L. Spiro
  • Posted: 26 April 2010 05:02 AM

That sounds similar to what I thought was wrong originally, but how do I do that?
Sorry, I am new to the FBX SDK.

Regards,
L. Spiro



Replies: 1
/userdata/avatar/3yvwf23us_doug100x100.png

This remapping is not an FBX function.  When you process a control index, you want the mapping of the control index to all the split verts:

typedef std::vector<std::vector<int>> ControlPointRemap;

ControlPointRemap controlPointRemap;

 if 
( bSplitVerts)
 {
   controlPointRemap
.resize(pMesh->GetControlPointsCount())
   
for (int lPolygonIndex 0lPolygonIndex lPolygonCountlPolygonIndex++)
   {
     int lPolygonSize 
pMesh->GetPolygonSize(lPolygonIndex)

     
for (int lVertexIndex 0lVertexIndex lPolygonSizelVertexIndex++)
     {
       int lControlPointIndex 
pMesh->GetPolygonVertex(lPolygonIndexlVertexIndex)

       controlPointRemap[lControlPointIndex]
.push_back(lPolygonIndex lVertexIndex)
     }
   }

 }

so when you refer to a control ID, get the list of all the split verts from

std::vector<int> & splitPointVector controlPointRemap[lControlPointIndex];

each of those verts need to be added to the bone.

Author: Doug Rogers

Replied: 26 April 2010 06:13 AM  
avatar

Maybe I did it wrong; it did not work for me.

/**
 * Extract skinning information from a geometry node.
 *
 * \param _mObj The object from which to extract skinning data.
 * \return Returns true if there are no memory failures.
 */
LSSBOOL LSSTD_CALL CSkinData::ExtractSkin( const KFbxMesh &_mObj ) {
    KFbxCluster 
pcCluster;
    
LSSUINT32 ui32TotalSkins _mObj.GetDeformerCount( KFbxDeformer::eSKIN )

    
// Create a list of split vertices.
    
CVector<CVector<LSSUINT32LSSUINT32>> vContPointRemap;

    
// How do I know if they are split?  Could not find the flag in the documentation.
    
if ( true/*bSplitVerts*/ ) {
        vContPointRemap
.Resize( _mObj.GetControlPointsCount() )
        LSSUINT32 ui32PolyCount 
_mObj.GetPolygonCount()
        
for ( LSSUINT32 I 0ULui32PolyCountI++ ) {
            LSSUINT32 lPolygonSize 
_mObj.GetPolygonSize( I )

            
for ( LSSUINT32 ui32VertIndex 0ULui32VertIndex lPolygonSizeui32VertIndex++ ) {
                LSSUINT32 lControlPointIndex 
_mObj.GetPolygonVertex( Iui32VertIndex )

                vContPointRemap[lControlPointIndex]
.Push( I 3UL ui32VertIndex )
            }
        }

    }


    
for ( LSSUINT32 I 0ui32TotalSkins; ++I ) {
        KFbxSkin 
psSkin reinterpret_cast<KFbxSkin *>(_mObj.GetDeformer( IKFbxDeformer::eSKIN ))
        m_sName 
psSkin->GetName()
        LSSUINT32 ui32ClusterCount 
psSkin->GetClusterCount()

        
// Fill out enough influences to cover the whole geometry.
        
m_vInfluenceLists.Resize( _mObj.GetPolygonVertexCount() )

        
for ( LSSUINT32 J 0ULui32ClusterCount; ++J ) {
            pcCluster 
psSkin->GetCluster( J )

            
if ( pcCluster->GetLink() ) {
                m_vJointNames
.Push( pcCluster->GetLink()->GetName() )


                LSSUINT32 ui32Points 
pcCluster->GetControlPointIndicesCount()

                
static LSSBOOL bWarnedPoints false;
                if 
( ui32Points >= m_vInfluenceLists.Length() ) {
                    
if !bWarnedPoints ) {
                        CStd
::DebugPrintA( "Skinning data in FBX file is corrupted (influences are larger than the number of vertices).  Model may not appear correctly.\r\n" )
                        bWarnedPoints 
true;
                    
}
                    
                    
// Cap the number of points.
                    
ui32Points m_vInfluenceLists.Length()
                }
                
for ( LSSUINT32 K 0ULui32Points; ++K ) {
                    
// If there is actually a weight value here, add it.
                    
if ( pcCluster->GetControlPointWeights()[K] 0.0 ) {
                        LSFBX_INFLUENCE iInf
;
                        
iInf.fWeight static_cast<LSSFLOAT>(pcCluster->GetControlPointWeights()[K])
                        iInf
.ui32VertIndex pcCluster->GetControlPointIndices()[K];

                        
// Apparently some FBX files can contain invalid data here.
                        //    One of my test files was giving me vertex indices in the range of 4,000+ when there were actually
                        //    only 2,000 vertices in the whole file!
                        // Print a warning but don't crash or stop.
                        
static LSSBOOL bWarned false;
                        if 
( iInf.ui32VertIndex >= m_vInfluenceLists.Length() || iInf.ui32VertIndex >= vContPointRemap.Length() ) {
                            
if !bWarned ) {
                                CStd
::DebugPrintA( "Skinning data in FBX file is corrupted (influences reference non-existant vertices).  Model may not appear correctly.\r\n" )
                                bWarned 
true;
                            
}
                            
continue;
                        
}

                        iInf
.ui32Index J;


                        
//m_vInfluenceLists[iInf.ui32VertIndex].Push( iInf )
                        // Apply to all split vertices as well.
                        
CVector<LSSUINT32LSSUINT32> & vSplits vContPointRemap[iInf.ui32VertIndex];
                        for 
( LSSUINT32 M 0ULvSplits.Length() ++M ) {
                            iInf
.ui32VertIndex vSplits[M];
                            
m_vInfluenceLists[iInf.ui32VertIndex].Push( iInf )
                        }
                    }
                }
            }
        }

        
return true;
    
}


    
return true;
}

The result from this change is a huge mess, not resembling the original data in any way.
Did I do it wrong?  (Well obviously I did.)
CVector<> here is obviously the same thing as std::vector<>.

Thank you,
L. Spiro



Replies: 1
/userdata/avatar/3yvwf23us_doug100x100.png

Splitting verts is done in my app if any of the elements specify: KFbxLayerElement::eBY_POLYGON_VERTEX, meaning they refer to a vertex, not a control point.
So I do a scan of all the attributes to check for this.

This is assuming that lPolygonSize is always 3, so only triangles are supported.

vContPointRemap[lControlPointIndex].Push( I 3UL ui32VertIndex )

If you split verts, all the rest of your pipeline has to refer to the split verts, not the control points.
for example:

if (bSplit)
 m_Vertices
.resize(lPolygonCount 3)
 
else
 
m_Vertices.resize(lControlPointsCount)

and anything else that refers to the control points has to be remapped as well.

Author: Doug Rogers

Replied: 02 May 2010 03:45 AM  
avatar
  • adario
  • Posted: 03 May 2010 05:16 AM

Doug,

While the original poster’s file does indeed animate fine in your viewer, I am attaching an archive containing two files that do not animate properly—the deformations are clearly broken.
Although the deformations look different in my own viewer, they are broken as well: I would be curious to know whether (1) you have any idea what might be wrong with these files and (2) you have a possible solution.

Thanks,
Dario



Attachment Attachment
Replies: 1
/userdata/avatar/3yvwf23us_doug100x100.png

(1) you have any idea what might be wrong with these files

The animation time lines do not start at 0.0

(2) you have a possible solution.

Clamp the time to the animation interval.

I did that and they animated correctly.

Author: Doug Rogers

Replied: 03 May 2010 07:10 AM  
avatar

Here is the updated FBXViewer.exe that shows the models animating properly.



Attachment Attachment
Replies: 0
2 pages: 1.2 last