Missing normal indexing when reading vertex cache

Missing normal indexing when reading vertex cache

maikenDWNGK
Participant Participant
1,513 Views
4 Replies
Message 1 of 5

Missing normal indexing when reading vertex cache

maikenDWNGK
Participant
Participant

Hi there

I'm investigating FBX files using vertex cache files from Maya (.mcx) and have a great success on deforming vertices.

Now I'm stuck with the normals. I can't figure out the right mapping compared to the vertices in the same file.

 

I have a model of a deforming cube made in Maya (attached file) and the number of control points are 8, which matches the number of vertices in the cache file. For indexing these vertices the FbxMesh::GetPolygonVertices() works perfect.

However, when getting the normals from the cache I can't find the right indices for mapping this to the geometry.

The number of normals are 24 (three per control point here) but with a 12 triangle geometry I don't see how I can match the normals to this.

This example, https://help.autodesk.com/view/FBX/2020/ENU/?guid=FBX_Developer_Help_cpp_ref_import_scene_2_display_... states in a comment, that "the normal data is per-polygon per-vertex". That's not what I get from the cache file. I've checked that polygon size is 3 so you would think the number of normals should 36 (12 * 3). This is the case when reading normal information from the geometry in the fbx file but the vertex cache yields different.

 

I hope somebody is able to point me in the right direction.

 

Regards, Maiken

0 Likes
Accepted solutions (1)
1,514 Views
4 Replies
Replies (4)
Message 2 of 5

regalir
Autodesk
Autodesk
Accepted solution

Hi,

 

I think that the numbers are correct! The FBX terminology uses the "Control Point" to refer to the actual 3D coordinate of a point and "Vertex" to refer to the point of the polygon. Therefore, a cube have 8 control points, 6 polygons (four sided faces), so 6 x 4=24 vertices and, thus, 24 normals (when defined by polygon vertex). In the case of a Maya cache file, the normals channel is always defining normals by polygon vertex, hence the 24 values you saw.

 

I believe the following code snipped should work to access them (I haven't thoroughly tested it but I think it is okay ;-))

 

        if (lMesh)
        {
            int nbCtrlPoints = lMesh->GetControlPointsCount();
            int nbPolygons = lMesh->GetPolygonCount();
            int pvc = lMesh->GetPolygonVertexCount();

            FbxTime time(0);
            FbxVertexCacheDeformer* lDeform = lMesh->GetSrcObject< FbxVertexCacheDeformer>(0);
            FbxCache* lCache = lDeform->GetCache();
            lCache->OpenFileForRead();
            float* data = (float*)FbxMalloc(3 * pvc * sizeof(float));
            lCache->Read(1, time, data, pvc);

            for (int p = 0; p < nbPolygons; p++)
            {
                int psize = lMesh->GetPolygonSize(p);
                int indexStart = lMesh->GetPolygonVertexIndex(p);
                for (int pv = 0; pv < psize; pv++)
                {
                    int vtx = (indexStart + pv)*3;
                    FbxVector4 n(data[vtx], data[vtx + 1], data[vtx + 2]);
                    FBXSDK_printf("normal on polygon: %d  vtx:%d  index=%d  Normal=%f,%f,%f\n",
                            p, pv, vtx, n[0], n[1], n[2]);

                }
            }
        }

 

0 Likes
Message 3 of 5

maikenDWNGK
Participant
Participant

Thank you for the quick reply!

 

Unfortunately the proposed solution did not solve my problem.

It makes perfect sense that an cube consisting of 6 faces (all quads) have 24 normals. But this is not the case in the attached file. When the file is read using the API the number of polygons is 12 (not 6) and the size is 3, meaning it is all triangles.

The number of normals are retrieved using the GetChannelPointCount on the cache, like this:

int channelNo = 1;
FxbTime time(0);
unsigned int dataCount;
cache->GetChannelPointCount(channelNo, time, dataCount);

// Read normals
float *data = new float[dataCount * 3];
bool successfulRead = cache->Read(channelNo, time, data, dataCount);

 The number of normals are 24 and reading data with any other number will return false and the data array will be garbage.

 

Do you know why this discrepancy occurs?

0 Likes
Message 4 of 5

regalir
Autodesk
Autodesk

I think your importer does the extra step of triangulating. This would explain why you have 12 polygons instead of 6.

I inspected the "unmodified" data in the FBX file directly and it is indeed defining quad polygons. However, I cannot see what kind of triangulation is performed. The FbxGeometryConverter::Triangulate() does not modify the Maya cache files so, while it is true that the following calls:

 

int nbCtrlPoints = lMesh->GetControlPointsCount();
int nbPolygons = lMesh->GetPolygonCount();
int pvc = lMesh->GetPolygonVertexCount();

 

would return (8,6,24) on the original data, and (8,12,36) on the triangulated FbxMesh, the following loop:

unsigned int count;
for (int j = 0; j < lCache->GetChannelCount(); j++)
{
    lCache->GetAnimationRange(j, st, et);
    lCache->GetChannelPointCount(j, st, count);
}

 

will return count=8 on channel 0 and count=24 on channel 1 wheter the FbxMesh have been triangulated or not!

BTW, using time=0, does "fail" for me; the call to GetChannelPointCount(j, time, count), return false because 0 is outside the animation range and the count value is left at whatever was set before the call.

 

0 Likes
Message 5 of 5

maikenDWNGK
Participant
Participant

Thank you very much!

 

It turned out the mesh was indeed triangulated and after removing this everything worked.

 

/Maiken

0 Likes