Announcements

Starting in December, we will archive content from the community that is 10 years and older. This FAQ provides more information.

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,551 Views
36 Replies
Replies (36)

ilan.keshet
Enthusiast
Enthusiast

@regalir wrote:

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) šŸ™‚


 If you look at the same code that 3Ds Max Exports for FBX, you will find that it does not export the deformed normals. 

So as such, I can't make any assumptions about if the normals are deformed or not deformed if I support FBX generated from any source. 

 

I still think it's completely crazy that Maya does this -- and has probably bugged out many applications that use FBX generated from maya for the last 20 years. 

 

Is there a specific way I can tell if an FBX file was generated specifically from Maya?   Also Exactly how are these deformed normals computed? because I want to see if I can reverse engineer the logic to get the correct normals. 

 

When I had examined the normals of the first frame in maya vs the normals found in the FBX they did not match exactly. 

ilan.keshet
Enthusiast
Enthusiast

@regalir wrote:

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.


I am going to have a look at this GenerateNormals function to see if I can use it. 

 

Thanks

DaveMay3D
Contributor
Contributor

No, it doesn't solve it.

 

"By design" is code for "due to bad design and laziness" and I do truly understand why it's been this way for years, a harsh reality. (I'll save my resume for a lead position at Autodesk for a time when I decide to apply.)

 

Let me guess: if they are locked, they are still wrongly rotated if attached to a bone that is not in bind pose! That would mean you're actually still wrong. Should I test this hypothesis and post my results? I mean, I'm guessing here, but I'm willing to bet on the bad design decision. If I'm wrong, then it would be just a matter of re-computing the unlocked vertices.

 

"Every 3D editing software" does re-compute normals for deformations but only Maya exports the normals this way so let's not stretch that to justify the other behavior. This weird export is just Maya. 3ds Max doesn't even do this, according to @ilan.keshet . Remember also, this is new information to you or you wouldn't have stated something that explicitly contradicts this new standpoint just yesterday. Instead your team should say, "We did this wrong, but we don't want to change it because we fear that we will break customers' import routines." Also say, "We don't mention this anywhere in the documentation yet."

 

So please save me some time and let me know how to determine whether the normals are locked in the FBX when I import it, because without that, exporting an FBX in Maya is by definition a destructive operation on the normals themselves. Correct me if I'm wrong, but normals can be individually locked. The GenerateNormals(...) function replaces ALL normals on the mesh so I cannot choose verts that are unlocked at export. This would also mean Maya itself cannot import locked normals correctly for a mesh deformed by a non-bind-pose positioned bone. The only remaining workaround would be possible only if the (1) bones are saved in their position at export, (2) the importer knows Maya exported the file and corrects for it, and (3) the import routine were to carefully un-deform just the normals using the inverse transforms. That's weird, so I doubt Maya does it. A rabbit hole found only by looking for workarounds for a bad design that Maya wants to stick with.

 

Given, I can re-compute normals for most models for my own purposes. But it's not possible for me to make an import that works as expected for someone else (in an engine) for Maya and other software unless all normals are unlocked.

 

What would be nice is to have a checkbox in Maya for this as legacy behavior and correct it in a future version. If my hypothesis above is true, it would be a bug, and an easy fix.

 

So let's confirm: is @ilan.keshet correct in saying that this is Maya export only? And are you responding on behalf of the Maya team officially, or is your work specific to the FBX SDK team?

 

Thanks


Dave

0 Likes

DaveMay3D
Contributor
Contributor

GenerateNormals() completely ignores hard edges for me, softening and distorting the normals, even when smoothing groups is turned on for the export.

 

DavePeasant_0-1658434012571.png

 

This is not a solution. 

 

@ilan.keshet is right in his post and it has probably been broken in exported files, and with no workaround it's just weird, inconsistent behavior, period. It's a mistake, a coding error. You haven't even expressed a valid reason why this behavior WOULD exist, otherwise why isn't it in 3ds Max? It isn't in 3ds Max because a different development team made it long ago and didn't make the mistake.

 

In fact I've discovered another bug in Maya's export, or perhaps a "by design" "bad design" limitation. If I attach a mesh to a bone, all hard edges are ignored on export. Is that "by design"? Or do I file a report on that also?

 

Dave

0 Likes

DaveMay3D
Contributor
Contributor

@regalir It looks actually like that very last item where I attached to a bone was due to something in the mesh's history. I don't know what was in the history, so I can't explain it. I deleted non-deformer history, reattached, and the hard edges did come through. However, GenerateNormals() absolutely destroys it. Is there a way I can keep the hard edges and still fix the normals?

0 Likes

regalir
Autodesk
Autodesk

Let me guess: if they are locked, they are still wrongly rotated if attached to a bone that is not in bind pose!

  • This is taken from the Maya documentation: "The normal values you specify are fixed for each normal associated with the vertex or vertex/face component. This means that if you change a vertex position, normals do not change position."

 

 

And are you responding on behalf of the Maya team officially, or is your work specific to the FBX SDK team?

  • I am specifically on the FBX SDK team but I do have some knowledge of how the FBX export from Maya works!

 

 

...but only Maya exports the normals this way

  • To be honest, I believe that every program have his own way to export. If, for example, you look at 3dsMax and try to add an EditNormals operator after the Skin and ask to export, you will get a warning that the operator had to be muted (effectively, it is ignored by the export code) and you only get the original normal (the non deformed ones).

 

So let's confirm: is @ilan.keshet correct in saying that this is Maya export only?

  • No! You get a similar, although not exactly the same, result if you put the EditNormals operator before the skin and export. In this case, the exact normals that you have edited with this operator are saved in the FBX file (this is, kind of, equivalent to the Normals Lock of Maya).

 

...save me some time and let me know how to determine whether the normals are locked in the FBX

  • I believe I already mentioned this, but in the FBX there is no concept of locked/unlocked normals. You only get an array of values. The program that import the file decides if it want to lock them or not. Again, by default, when importing in Maya, the incoming normals are locked (except if it detects that the mesh is deformed in anyway). If you import in 3dsMax the operators stack will just have the mesh and the skin operator (no more EditNormals operator) because the normals from the FBX files have been "baked" directly the mesh therefore not affected by the Skin operator regardless of any animation/deformation that may affect it. To "bring back" the default behavior of unlocked normals, you have to put a new EditNormal operator after the skin one and reset the normals through the EditNormal operator.

Which brings us back to what I was saying in the first place: when you have deformers affecting a mesh, you typically want to recompute the normals based on the morphology changes and it is not that important to know what the initial normals values of the mesh were.

 

 

0 Likes

regalir
Autodesk
Autodesk

Sorry, I've written my post before yours (#25) but it took me for ever to complete it ;-).

I will need to take some time to think about your last question.

0 Likes

DaveMay3D
Contributor
Contributor

Let me guess: if they are locked, they are still wrongly rotated if attached to a bone that is not in bind pose!

  • This is taken from the Maya documentation: "The normal values you specify are fixed for each normal associated with the vertex or vertex/face component. This means that if you change a vertex position, normals do not change position."
    • Yeah, but I didn't say "moved"; I said "rotated". It's a guess, as I said. I'll do the test to see if locked normals are also mangled at the time of export.

And are you responding on behalf of the Maya team officially, or is your work specific to the FBX SDK team?

  • I am specifically on the FBX SDK team but I do have some knowledge of how the FBX export from Maya works!
    • Noted, thank you. If the problem isn't in the FBX SDK, then the Maya team should be aware of it.

...but only Maya exports the normals this way

  • To be honest, I believe that every program have his own way to export. If, for example, you look at 3dsMax and try to add an EditNormals operator after the Skin and ask to export, you will get a warning that the operator had to be muted (effectively, it is ignored by the export code) and you only get the original normal (the non deformed ones).
    • That seems better. The Maya behavior is awful and has no useful purpose.

So let's confirm: is @ilan.keshet correct in saying that this is Maya export only?

  • No! You get a similar, although not exactly the same, result if you put the EditNormals operator before the skin and export. In this case, the exact normals that you have edited with this operator are saved in the FBX file (this is, kind of, equivalent to the Normals Lock of Maya).
    • But it is Maya's export only. I'm not specifically talking about locked normals either; you are shifting the goalposts. I'm talking about normals being saved as they are on the screen (presumably still in object space but deformed) at time of export and having no relationship to the geometry or anything. So, no, @ilan.keshet is correct.

...save me some time and let me know how to determine whether the normals are locked in the FBX

  • I believe I already mentioned this, but in the FBX there is no concept of locked/unlocked normals. You only get an array of values. The program that import the file decides if it want to lock them or not. Again, by default, when importing in Maya, the incoming normals are locked (except if it detects that the mesh is deformed in anyway). If you import in 3dsMax the operators stack will just have the mesh and the skin operator (no more EditNormals operator) because the normals from the FBX files have been "baked" directly the mesh therefore not affected by the Skin operator regardless of any animation/deformation that may affect it. To "bring back" the default behavior of unlocked normals, you have to put a new EditNormal operator after the skin one and reset the normals through the EditNormal operator.
    • Therefore, exporting normals from Maya is a destructive operation when the mesh is deformed at the time of export. Thank you, you proved both of my points. I see that you are trying to explain the behavior, and missing the point. I can accept that FBX has no concept of locked/unlocked normals, but those are destroyed if you call GenerateNormals(), your workaround.
  • Which brings us back to what I was saying in the first place: when you have deformers affecting a mesh, you typically want to re-compute the normals based on the morphology changes and it is not that important to know what the initial normals values of the mesh were.
    • And if you don't want to smooth the mesh, the hard edges are lost if you re-compute the normals. Are you going to now contend that no one should have hard edges or any normals shared between vertices for a mesh that is deformed?

 

So, I'm going to try again here.

 

Everything that I am talking about which happens wrong is when the mesh is deformed (not in bind pose) at the time of export. Please keep your answers in the scope of that. When I said that the normals are wrong in that case, you said that it's not important and your workaround was to re-compute the normals. But I learned that re-computing the normals softens hard edges and throws away normals that had been locked, losing information that may be important. So that is not a solution. You have not in any way diminished my point that this is problem. You have shifted the goalposts instead.

 

It's not important for me to know the normals were locked. But I'm not necessarily limited with what I do versus Maya with a normal, so if normals were locked to make sure their states saved in that position, then I may not want to lose that information. Re-computing the normals will lose that information if I'm forced to do it by this behavior.

 

Thanks,

 

Dave

 

 

0 Likes

ilan.keshet
Enthusiast
Enthusiast

the whole entire concept of locked / unlocked normals is a broken concept, since locked normals just straight up break lighting during deformation.

 

So ComputeNormals() in that regard should only be done on skinned geometry with animation, and left otherwise. 

0 Likes

ilan.keshet
Enthusiast
Enthusiast

However, if ComputeNormalize is infact losing data on softness / hardness then yes it's completely broken function -- though I personally haven't tried using it yet, but it sounds like it's certainly causing problems with that regard. 

 

 

0 Likes

DaveMay3D
Contributor
Contributor

@regalir brought up locked normals, not me. He was suggesting that users can lock the normals and that Maya tries to keep that information, but that is mangled by GenerateNormals(). Which I can accept, that's fine. And as you are reiterating, it's not fine to be expected to call GenerateNormals() if it removes hard edges.

 

It makes me utterly curious what Maya does on import then, because it's getting the hard edges information and presumably recomputing the normals while preserving that. FbxGeometryConverter:: has functions that seem like they help. I would need edge smoothing information. This seems like a lot to do because of the Maya behavior, but if there is a way to do this I'd like to know a proper procedure. I find examples that call one function and do nothing with the information.

0 Likes

regalir
Autodesk
Autodesk

Okay, I think I need to "reset" the very long explanation I made previously. What I was trying to express is the fact that:

  1. there are always differences across products and the exported data is affected by what each product makes available and is accessible. The FBX format tries to reflect, as much as possible, what the user have created and want to export (including lock/unlocked normal values šŸ˜‰), but sometimes it has to make conversions and some data may be lost because not everything can be stored in the FBX format.

    And while, at first, it seems obvious that the exported normals should not be dependent on the skin deformation at a given time, I am not sure that this assumption still hold true if the deformation is actually a combination of skins, blend shapes and/or vertex caches and by the way each of these systems interact with each other. I guess that in my previous posts I created more confusion than provided answers. I apologize for that!

  2. When a skinned object is imported into Maya from an FBX file, the first thing that the Maya importer does, is to put everything in the "bindpose" then create the skin connection. If you are interested to see an implementation of the skin evaluation with the FBX SDK, you can look at the SceneContext.cxx file in the ViewScene sample. This sample does only work with the mesh points/polygons and does not manipulate the normals but I believe that it is still a good starting point for someone to modify the code and add normals as well.

  3. By default, GenerateNormals(), computes the normals for the polygon vertices. However, it also tries to respect what is defined in the SmoothingGroup elements (if present) so, if your mesh does have a mix of hard and smooth edges, GenerateNormals() should give you back something that reflects this (data may be slightly different but the visual effect should be consistent). As Dave mentioned in his last post, the FbxGeometryConverter can possibly be helpful; I believe this is how it would be used:
    FbxMesh* lMesh = lScene->GetSrcObject<FbxMesh>();
    if (lMesh)
    {
    	if (lMesh->GetElementSmoothingCount() == 0)
    	{
    		// No smoothing groups defined, let's try to create them 
    		FbxGeometryConverter lCvrtr(lSdkManager);
    
    		// first, use the currently defined normals in the mesh to generate hard/smooth edges.
    		if (lCvrtr.ComputeEdgeSmoothingFromNormals(lMesh))
    			// hard/smooth can als be converted to polygon smoothing if the destination system cannot handle edges!
    			lCvrtr.ComputePolygonSmoothingFromEdgeSmoothing(lMesh);
    	}
    
        // Now, (re)generate the normals
        lMesh->GenerateNormals(true);
    }ā€‹

    the Normals sample in the FBX SDK package illustrates how to:
        1) get normals of mesh.
        2) get smoothing info of mesh.
        3) compute smoothing info from normals.
        4) convert hard/soft edges info to smoothing group info.

  4. to answer a previous question. How to know if the file is coming from Maya? You can look at the LastSaved_ApplicationName property of the FbxDocumentInfo.
    FbxDocumentInfo* docInfo = lScene->GetSceneInfo();
    if (docInfo)
    {
    	FbxString appName = docInfo->LastSaved_ApplicationName.Get();
    	FbxString appVers = docInfo->LastSaved_ApplicationVersion.Get();
    	FBXSDK_printf("appName=%s  appvers=%s\n", appName.Buffer(), appVers.Buffer());
    }ā€‹
    Please be aware that the LastSave_ properties always exist in the FbxdocumentInfo but are not mandatory and some products can leave them empty. However, I confirm that Maya, 3dsMax and MotionBuilder, for sure, do fill them.

Hope this posts better give better answers than my previous ones!

Regards

0 Likes

ilan.keshet
Enthusiast
Enthusiast

Thank you very much for the long response -- I deeply appreciate it! I'm going to try the approach you mentioned above!

 


@regalir wrote:

And while, at first, it seems obvious that the exported normals should not be dependent on the skin deformation at a given time, I am not sure that this assumption still hold true if the deformation is actually a combination of skins, blend shapes and/or vertex caches and by the way each of these systems interact with each other. 


I still don't really understand this however. -- I do agree with you that the normals are effected by a variety of influences such as what you described, -- But the design decision by the Maya team to export the "modified" normals to FBX still doesn't make sense to me. 

 

What exactly is the use case to want the modified normals, with respect to the things you mentioned above, in FBX SDK?  I can't think of any case.  It's also tied to an arbitrary animation pose that the model may be in. 

0 Likes

DaveMay3D
Contributor
Contributor

@regalir wrote:

And while, at first, it seems obvious that the exported normals should not be dependent on the skin deformation at a given time, I am not sure that this assumption still hold true if the deformation is actually a combination of skins, blend shapes and/or vertex caches and by the way each of these systems interact with each other. I guess that in my previous posts I created more confusion than provided answers. I apologize for that!


It seems obvious because it's correct. The assumption does hold true, end of story. You can't defend the indefensible and no amount of word salad can change it. (All those systems interacting! You mean the systems I'm also doing in my own engine? And so on.)

 

But this is a Maya bug, and not the FBX SDK at all obviously. Your team has been winning for a long time, otherwise support for FBX wouldn't be critical in every 3D package and engine.

 

What's likely is someone from Alias in 2002 or something had a late night out partying on LotR money and wrote the data out from the deformed normals array and not the mesh, clocked out and called it a day.

 

When Alias wrote the OBJ export, there was no skinning, so they would have used the deformed normals, because had to use the deformed geometry. When it came time to write the FBX export, they perhaps copied code and used the deformed normals by mistake.

 

It was never corrected because it's probably rarely encountered. Most skinned meshes are going to be put into bind pose for export, and a lot of times animations are placed in separate files. But my example is just a simple animated mesh in one file, and it breaks.

 

Having calculated deformations for one pose on import is totally useless to 100% of people importing from FBX, so Maya should make a correction. Otherwise, why not deform the geometry too? Because it doesn't make sense. You'd have to unwind all deformations to get the geometry, what a pain! Just like you have to unwind all deformations to get the normals. Doesn't make sense.

 

I'm concerned that the solution proposed calculates the smoothing based on deformed normals. It's probably fine, but I can see theoretical issues where normals could be smoothed when they weren't supposed to be. Hmm. I'm surprised FBX doesn't know about hard/soft edges and they have to be computed from normals in the first place. Such dirty workarounds for one mistake!

 

And thanks for your help. This workaround is probably satisfactory, but I'll need to try it. I know you are trying to solve an issue for us rather than take a challenge to the Maya team. They wouldn't be able to defend it but they have a big ship that moves slowly and they probably wouldn't prioritize a fix even if they acknowledge it. But I would be happy to still report it to them and it would be interesting to see their answer.

 

Let me put the cherry on top for you and for @ilan.keshet also. Here's Blender importing a Maya mesh (not using FBX SDK) and the normals are wrong in the exact same way as in my engine:

 

DavePeasant_1-1658852721006.png

 

 

In the above example, you can see that Blender then deforms the mesh into the pose, meaning the normals are now double-transformed (creating the very dark wing). Blender's devs didn't catch the issue; @ilan.keshet and I did.

 

Blender offers the option to not accept the normals, in which case Blender re-computes the normals:

 

DavePeasant_0-1658852661099.png

 

 

...and hard edges are lost... ooooof!

 

So they are trusting the export purely as FBX describes it. They may be unaware of the Maya export issue, but it would require something like what we're discussing to work around it, at least partly.

 

But no workaround appears to solve the matter. All of this can be avoided if the normals were not baked, and it would be nice to see future versions of Maya not have this problem. All our suffering would end!

 

Dave

 

0 Likes

DaveMay3D
Contributor
Contributor
@regalir wrote:

 

By default, GenerateNormals(), computes the normals for the polygon vertices. However, it also tries to respect what is defined in the SmoothingGroup elements (if present) so, if your mesh does have a mix of hard and smooth edges, GenerateNormals() should give you back something that reflects this (data may be slightly different but the visual effect should be consistent). As Dave mentioned in his last post, the FbxGeometryConverter can possibly be helpful; I believe this is how it would be used:

 

FbxMesh* lMesh = lScene->GetSrcObject<FbxMesh>();
if (lMesh)
{
	if (lMesh->GetElementSmoothingCount() == 0)
	{
		// No smoothing groups defined, let's try to create them 
		FbxGeometryConverter lCvrtr(lSdkManager);

		// first, use the currently defined normals in the mesh to generate hard/smooth edges.
		if (lCvrtr.ComputeEdgeSmoothingFromNormals(lMesh))
			// hard/smooth can als be converted to polygon smoothing if the destination system cannot handle edges!
			lCvrtr.ComputePolygonSmoothingFromEdgeSmoothing(lMesh);
	}

    // Now, (re)generate the normals
    lMesh->GenerateNormals(true);
}ā€‹

 

the Normals sample in the FBX SDK package illustrates how to:
    1) get normals of mesh.
    2) get smoothing info of mesh.
    3) compute smoothing info from normals.
    4) convert hard/soft edges info to smoothing group info.

- - -

 

This example doesn't solve the problem and the Normals sample doesn't do it either.

 

From testing, I observe GetElementSmoothingCount() returns non-zero if I have "Smoothing Groups" turned on in Maya on export.

 

If GetElementSmoothingCount() returns non-zero, with your code example, GenerateNormals(true) will calculate normals by face, so there is a faceted appearance (no smoothing). If I remove the conditional here (or if I simply have "Smoothing Groups" turned off in Maya on export) ComputeEdgeSmoothingFromNormals does add a "by edge" smoothing element, ComputePolygonSmoothingFromEdgeSmoothing converts the smoothing element to "by polygon", and then GenerateNormals(true) totally ignores all that information, wipes out all hard edges and smoothing groups, and smooths the mesh (averaging normals at each control point).

 

I've tried using ComputeEdgeSmoothingFromNormals without ComputePolygonSmoothingFromEdgeSmoothing, and GenerateNormals(true) still wipes out any smoothing information.

 

In fact, in all cases and at all times, if there is smoothing information on the mesh when GenerateNormals(true) runs, it destroys all smoothing information and simply averages all normals to smooth the mesh.

 

Additionally GenerateNormals(true, true) destroys smoothing information in all cases.

 

For testing I created a series of bool values to toggle which functions run. No combination will recompute normals using existing edge smoothing. The only way the edge smoothing shows up is if I simply never GenerateNormals(...), in which case we're back to the original issue: normals will be wrong (in world space) if the mesh was exported while posed differently than bind pose (the original Maya bug).

 

GenerateNormals(...) is supposed to respect smoothing elements but it does not. I have not inspected whether the smoothing elements are actually valid, but I did at least verify that "by edge" does create 0 and 1 values, and "by polygon" smoothing elements generates smoothing group IDs, so I suspect they are valid and GenerateNormals(...) isn't doing what it's documented to do.

 

Thanks,

 

Dave

0 Likes

ilan.keshet
Enthusiast
Enthusiast
Accepted solution

I have managed to solve the problem finally... after much discussion + testing.

In recap, the problem exists strictly in Maya's FBX Export. -- Maya's raw normals attempts to keep locked normals and such -- and works great when it comes to static geometry, -- but exports deformed normals if mesh is skinned. 

The solution is to be able to Generate the normals based upon smoothing information in the mesh. 

 

The posed solution that reglir has given, -- is the right idea, -- except the fact that the GenerateNormals() function provided by FBX has a critical bug in it -- It works in most cases, but in the case of Dave's model he was showing fails miserably.

 

The case where the FbxMesh GenerateNormals fails can be described in the image below, where the red line is a hard edge, and the rest are all soft edges. 

 

unknown.png

In this case, there are 3 polygons above that should be smoothed together, -- and 3 polygons below that should be smoothed together. Unfortunately, -- in this case the FbxMesh GenerateNormals function fails, and instead shares 1 normal with all 6 of the triangles. 

 

How did I go about figuring this out?

 

Well, I decided to rewrite the entire GenerateNormals myself using the smoothing information, -- and managed to produce the exact same bug that FbxMesh's GenerateNormals does --

 

After figuring out this bug, then I handled this case in code, and it fixed everything that Dave was mentioning. 

 

Results:

Using Fbx's GenerateNormals (and also I produced this before handling the case listed above)

ilankeshet_1-1663974018232.png

 

Using my GenerateNormals:

ilankeshet_2-1663974152378.png

As you can see the hard edge in the wing is missing in the top picture. 

 

 

I used https://knowledge.autodesk.com/support/maya/learn-explore/caas/sfdcarticles/sfdcarticles/How-Maya-co...   as a reference on how to write the code -- though this reference in itself has bugs in it. 

 

Here is the algorithm that I used that did work:

 

 

 

 

 

 

SharedEdge //This contains all vertexIds that are on the an Edge
{
   startControlPointIndex = -1
   startVertexId = -1
   startVertexId2 = -1
   endControlPointIndex = -1
   endVertexId = -1
   endVertexId2 = -1
};

Clear Normals IndexArray / DirectArray
normals->SetMappingMode(FbxGeometryElement::eByPolygonVertex);
normals->SetReferenceMode(FbxGeometryElement::eIndexToDirect);

map<int, SharedEdge> smoothEdges{};

Loop over all polygon vertices and build the smoothEdges map with key being edgeIndex, and a SmoothedEdge 
   edgeIndex can be found using:   mesh->GetMeshEdgeIndexForPolygon
   Check if edge is smooth using SmoothingGroups 

Loop over all edges in SharedEdge map
   Group startVertexId + startVertexId2 in same shared normal grouping
   Group endVertexId + endVertexId2 in same shared normal grouping

Loop over all groupings found
   Add a Normal into the Direct Array + link to this index from the group

Loop over all polygons
   if (vertexId is a sharedSmoothNormal)
      compute: normals[normalIndex] += faceNormal * vertexAngle * faceArea;
   else
      Add a shared normal into the direct array (Hard Normal) 
      normals[normalIndex] = faceNormal

Finally, and as a last step, ensure all smoothed shared normals have been properly normalized. 

 

 

 

 

 

 

 

 

 

 

        

0 Likes

DaveMay3D
Contributor
Contributor

@regalir, I can confirm @ilan.keshet 's post. He was able to recalculate normals properly when GenerateNormals() would not, while following your procedure. The procedure would work, but GenerateNormals() does not work. For my mesh, it completely smooths every vertex, even though there is correct edge-based smoothing data in the FBX (and converting to polygon smoothing doesn't work either).

 

I followed essentially the same algorithm with different structures and had success.

 

DavePeasant_0-1663977755128.png

 

So, the correct answer is... write it yourself. Then, why doesn't GenerateNormals() work as described?

 

Dave

0 Likes