FBX SDK Normals Incorrect with Skinned Meshes with animations

ilan.keshet
Enthusiast
Enthusiast

FBX SDK Normals Incorrect with Skinned Meshes with animations

ilan.keshet
Enthusiast
Enthusiast

I've made a post on this stackoverflow regarding this issue:
https://stackoverflow.com/questions/72876412/fbx-sdk-importing-normals-inconsistent-with-maya-normal...

 

In short summary, -- Exporting Skinned meshes and viewing data from FBX SDK seems to have their normals not matching Maya's Normals, while for non-skinned it matches exactly.

 

In the link above, it shows some error between normals -- but I've tried other examples where normals are just completely wrong and unusable. 

 

There was a similar post posted to this forum, here: https://forums.autodesk.com/t5/fbx-forum/maya-fbx-exporting-normal-information-disappearing/td-p/428... 

 

But no answer was really ever given. 

Was that issue resolved and perhaps there is some bug in my code? 

 

0 Likes
Reply
Accepted solutions (1)
3,527 Views
36 Replies
Replies (36)

regalir
Autodesk
Autodesk

I am not sure I understand the issue. I read your post on stackoverflow so i tried to create a sphere, and skinned it with three bones. Then I exported to the FBX file. Imported back into Maya and compared the normals on one selected face (the same on both the reference sphere and the imported one). Maya shows exactly the same values. I am attaching my data. Please note that, to have manegable numbers, after I skinned the sphere, I deleted most of the faces to remain with 5 polygons only. In the Zip file, you will find the Maya file, the Fbx file and the screen grab showing the numbers on the vertices 0,1 and 6. In the screenshot, dummy1::pSphereShape1 is the imported model. Maybe I am not doing the same exact steps that you do?

 

Anyway, something to remember, when Maya imports deformed meshes (skin, blendshapes) or having smoothing layers from an FBX file, the normals are automatically "unlocked" so Maya is free to recompute them as it sees fit. Non deformed geometries will import with "locked" normals (they show in yellow instead of green). Also, make sure you compare the normals at the same frame. Being deformed, and Maya having the freedom to recalculate them, if you compare, for example at frame 1 in Maya but at frame 0 in the FBX scene, that may explain the difference in the values (of course it depends on the deformation). In my test case, I did not animate anything.

 

Just to possibly narrow things down, please try to use the File->Import command instead of the Drag&Drop. I am not sure if the Drag&Drop is setting the FBX import exactly as the File->Import command. Worth checking! šŸ™‚

 

 

0 Likes

ilan.keshet
Enthusiast
Enthusiast

I am not talking about what the values are shown in Maya -- I'm talking about what the values are given to me by FBX SDK 2020

 

Yes I agree the values IN maya do show correctly after you redrag and drop it in.   but using the FBX SDK it gives wonky normals.

 

I provided full sample code from FBX SDK grabbing normal data from the fbx file at the Stackoverflow page.

 

I will try your sample zip file

ilan.keshet
Enthusiast
Enthusiast

--erased

0 Likes

ilan.keshet
Enthusiast
Enthusiast

I have tested with the data you have sent me, and now the normals shown in maya match with FBX SDK code. 

 

However, the file you sent me does not have any animation data inside of it. So maybe that is part of the cause. 

 

Attached is the FBX sample file I have been using generated by an artist on my team that has broken the FBX SDK.

DaveMay3D
Contributor
Contributor

I'm also using the 2020 FBX SDK and I just encountered this for my first animated skinned mesh import. It's as though the normals are being brought in as they are in world space for the first frame, rather than matching the geometry. In my case it's a mechanical bird with wings, and the animation has its wings up. When lit in my shader it's being lit as though the normals are applied with the wings up, which does not match the geometry.

 

I'm trying to figure out how I would fix this. It wouldn't make sense to have to adjust only the normals for the bind pose--or something--and not the geometry.

 

Did you come across a cause or solution? I'm perplexed on this.

0 Likes

ilan.keshet
Enthusiast
Enthusiast

I have yet to come up to a solution to this. I've been waiting for Autodesk to reply.

 

I even sent a message to a senior engineer at autodesk about this with no reply. 

ilan.keshet
Enthusiast
Enthusiast

The workaround solution im going on -- is I am requiring (for now) to send in the fbx without animations in bind pose

DaveMay3D
Contributor
Contributor

Here's my example. This is in my own shader, per-vertex lit only, with one light directly overhead. The animation starts almost in the same position with the bird's wings turned 90deg such that the "flat" side of this left wing facing toward the camera would be facing upward and lit. But I'm not applying the bone matrix to the geometry or the normals, so it shouldn't be lit now--it's like the bone is pre-applied to the normals and not the geometry. If I remove the bones from the model he drops into this position, and I would be he would be lit correctly then. Again I don't know what would change the normals without changing the attached geometry.

 

Thanks for the fast reply. Have you tried this in a previous SDK version?

 

DavePeasant_0-1658341859717.png

 

0 Likes

ilan.keshet
Enthusiast
Enthusiast

1. Make sure the normals you get are from FBX Bind Pose with no animations in the FBX   (Temp workaround until autodesk fixes Maya Export of FBX)  -- This problem only happens during Maya FBX Export   -- Export FBX animated file in 3Ds Max works. 

 

2. Make sure that the normals in FBX are re-computed if there is a transformation on the mesh  -- and apply updated normals via Normal Matrix   (If you are baking in the Transformation to the vertices)

 

3. Make sure that the normals you use in your shader are computed with the Inverse of the MV transform  (Normal Matrix)

 

 

--- I've only been using latest FBX 2020, -- but I don't think it is a problem with FBX SDK,  I think it is a problem with Maya Exporting, because data is correct when using 3Ds Max Skinned Animated mesh

DaveMay3D
Contributor
Contributor

Yes, just setting the mesh to the bind pose and exporting gives me correct results. Everything for me jives with what you're saying.

 

I can go back into Maya from the bind pose, turn one of those wings 90deg, and that wing is wrong again. Therefore, the normals are being written into the FBX based on the initial pose, while the geometry is not. That must certainly be something wrong in Maya if you don't encounter this in Max.

Also this issue occurs whether or not there is an animation.

 

I'm not re-computing anything in my import; I want to the normals to come from the FBX. I'm building a tree of nodes with transforms so I am not baking anything. My shader is using the world inverse transpose for the normal calculation, although so far all my transforms should be orthogonal.

 

So what do we do to get Autodesk to take a look at this issue? I'd like to be able to import just about anything without export rules special for Maya. I think I know just one person at Autodesk.

 

0 Likes

regalir
Autodesk
Autodesk

Sorry but I still don't understand what is the issue here (both for the bird model and the basic sphere sample). There have been no changes in the way we export normals for several years now so it may just be a misunderstanding of what you can expect is stored in the FBX file?

 

The geometry/normals saved to the FBX files are taken before the deformation nodes (skinCluster) so we don't depend on time based modified values. There is also a limitation about the construction nodes that still exist in the history. Normally, the FBX export will ignore these nodes but some of them may modify the retrieved data in a way incompatible with the export. FYI, it is always a good idea to "delete non-deformer history" before exporting to FBX to increase the "fidelity" of the saved data.

 

Also, how did you configured the export? Have you set some options or just with the default values? I sincerely apologize for not being more precise but, as I said in my previous post and at the beginning of this one, I really don't understand the problem :-(. It will certainly help me to give more significant answer that this one, if you can generate a very simple test case (a little bit like I did in my test.zip scene) and post the obtained results, the expected ones and include the full export process. I did not see anything wrong with the sample code posted on  stackoverflow (except maybe that all the switch/case to retrieve the normals  in the ImportMesh() function is exactly what is performed inside the GetPolygonVertexNormal() ;-))

0 Likes

ilan.keshet
Enthusiast
Enthusiast

Just one thing of note as a possible correction of what you posted. 

 

-- When I did testing, and compared with Normal Exported values -- they weren't matching the first frame in Maya.  I have no idea where these normals where coming from.   (I would go into Maya's Component editor and view the data on the first frame) 

 

Validating the normals just with a unit Sphere is the easiest, since the normal values should approximately be matching that of the position on the Sphere. 

ilan.keshet
Enthusiast
Enthusiast

I think the problem I stated was very clear. -- And I even posted an .fbx file that was generated from Maya. 

 

The Normal Data coming out of the .fbx is incorrect.   I am reading the normal data directly from FBX SDK, and it is not matching the correct values that should be in bind pose. 

 

I even have full sample code that I posted on Stackoverflow and the sample FBX file -- that even outputs the normal values where you can clearly see its broken. 

 

It is possible as to what you said about that perhaps the history or something in maya is breaking the normals when they are exported -- But the very strange thing is that the geometry (positions) are totally correct. 

0 Likes

ilan.keshet
Enthusiast
Enthusiast

@regalir wrote:

I did not see anything wrong with the sample code posted on  stackoverflow (except maybe that all the switch/case to retrieve the normals  in the ImportMesh() function is exactly what is performed inside the GetPolygonVertexNormal() ;-))




 

The reason why I had that extra code in that sample is because I was trying to see if ANYTHING I could do -- would get the correct normals, but it did not.   Normals are clearly busted from the stackoverflow post.

0 Likes

ilan.keshet
Enthusiast
Enthusiast

@regalir wrote:

if you can generate a very simple test case (a little bit like I did in my test.zip scene) and post the obtained results, the expected ones and include the full export process.



Your test.zip is an invalid test case -- it doesn't have animation data in it.   The bug only happens when there is animation in the maya scene and you export to an fbx -- and you load the Fbx file using FBX SDK

ilan.keshet
Enthusiast
Enthusiast

@regalir wrote:

... post the obtained results, the expected ones and include the full export process.



I've already posted the output on the Stackoverflow post of the Unit sphere, and just by even looking at the normals its very easy to tell its broken, without even opening it in maya. 

 

Vertex Count: 0 Vertex Index: 20
Position: X: 0.293893 Y: -0.951057 Z: -0.0954916 W: 0
Normal: X: 0.298177 Y: 0.267987 Z: -0.916119 W: 1

Vertex Count: 1 Vertex Index: 0
Position: X: 0.148778 Y: -0.987688 Z: -0.0483409 W: 0
Normal: X: 0.18352 Y: 0.228479 Z: -0.956095 W: 1

Vertex Count: 2 Vertex Index: 21
Position: X: 0.25 Y: -0.951057 Z: -0.181636 W: 0
Normal: X: 0.246448 Y: 0.378525 Z: -0.892179 W: 1

 

The normals / positions should very similar, and match in sign. -- Here normals are completely off and signs are wrong. 

DaveMay3D
Contributor
Contributor

@regalir when I import @ilan.keshet 's sphere into my test engine from FBX SDK 2020.3.1, with no animation applied, I can confirm the normals are facing the wrong direction and they also have the bone's distortion from the first frame baked in. The geometry is however correct. I have not supplied any of my code or files yet, but based on the documentation I would be expecting the light to be coming from my light source directly above, since the normals would match the position information. If I remove the animation and leave the joints, the normal distortion is gone but they are facing a different but still wrong direction. If I put the mesh in bind pose before exporting, the normals match perfectly. The way I'm importing, I would expect to get the same information every time.

 

DavePeasant_0-1658353879870.png

 

DaveMay3D
Contributor
Contributor

Sorry but I still don't understand what is the issue here (both for the bird model and the basic sphere sample). There have been no changes in the way we export normals for several years now so it may just be a misunderstanding of what you can expect is stored in the FBX file?

 

Given the response I would imagine it's very possible it's been wrong for several years. There appears to be something about Maya FBX export in contradiction to your statement:

 

The geometry/normals saved to the FBX files are taken before the deformation nodes (skinCluster) so we don't depend on time based modified values.

 

@ilan.keshet seems to have proven that with the sphere example. Indeed the normals, unlike geometry, seem to be baked to the position they are in at the time of export regardless of the animation. That's what I'm observing at least. Default FBX export options, no history.

 

I tend to import everything in its bind pose on the first frame. From my understanding, popular game engines write their own FBX importers. I didn't run into this until I had an animated file where the first frame was not in the bind pose.

 

If I export the same animated file, but right before I export I put the skeleton in bind pose, I get correct normals:

 

DavePeasant_0-1658357772379.png

 

Per your statement I would expect this result no matter what position I have the joints in. (Again this is a single combined mesh so that really shows the deformation is being applied ONLY to the normals.)

 

Thanks for your responses.

 

 

0 Likes

regalir
Autodesk
Autodesk

Okay guys, I dig deep into the history of the code and after several hours of investigations I have to come to the conclusion you already came to, and that is that Maya export the "modified" normals. I went back about 20 years in the code and I confirm that this is "by design". Let me try to explain the reasons we export unmodified vertices but modified normals.

 

As I wrote in previous posts, we do indeed save the geometry coordinates before any deformation occurs. The particular thing with the normals is that, as you may already know, in Maya you can actually lock individual vertices normals and mix hard/smooth surfaces. When we export such geometries to FBX we try to respect the values the user defined (an explicitly set value = locked) and we have to get them from the deformed geometry because this is where they are stored. I also mentioned that, typically, normals need to be re-computed every time the deformations are evaluated so "it does not really matter what is their initial value" (the only exception would be if you want to keep "locked" values but, of course in this case the rendering will look "weird" while the skin is deformed). Yes, I know, this is not the best answer, but is also pretty much what every 3D editing software does! (I mean, re-compute the normals based on the deformations) šŸ™‚

 

It probably won't help much in your case but, for what is worth, in the FBX SDK we have the function FbxMesh::GenerateNormals(...) that can be used to compute vertex normals on the mesh based on its topology.

 

Hope this helped to clarify the current results

Regards