Unless I’m misunderstanding, the new blend shape normal calculation options don’t have a way to retain the mesh’s base normals. This is particularly problematic when animating meshes with custom vertex normals (for things like toon shading, etc.). The editor tooltip says:
“If Import is selected and the blend shape has no normals, they will be calculated instead”
But could there not be an option for the blend shapes to retain the normals of the mesh in its default state, so that the normals don’t change at all when animating blend shapes? The way it is now, no matter what my setup is, so long as I have custom normals the blend shapes will change the normals to the calculated versions.
For reference, I’m using 3ds Max and the Morpher modifier, and I’ve turned off Smoothing Groups when exporting my FBX because it will average out the vertex normals I’ve set manually, which is undesirable.
Edit: I just checked 2018.2, and this seems to be the behaviour I’m talking about. Another option in the importer for having the blend shapes interpolate normals like this would be greatly appreciated. Something like a Legacy option would be ideal.
We are currently tracking a bug related to the FBX importer calculating normals for blend shapes even when the ‘Blend Shape Normals’ setting is set to ‘None’. You can follow that bug here. However, the ‘None’ setting should be used when the object requires no normal information, no lighting.
Regarding smoothing groups. Although this didn’t seem to have any impact on my test files, our documentation does say that smoothing groups are required for importing blendshape normals:
2018.2 has the behaviour I need. When I change the blendshape values in 2018.2, the normals/smoothing groups retain those of the base mesh. When I try to do the same in 2018.3, they will progressively change to the recalculated normals/smoothing groups.
Basically I want to preserve my custom normals/smoothing group information when my blendshapes are active, but all of the current options always end up recalculating them.
I’ve attached a quick GIF to show the problem. 2018.2 is the desired effect; 2018.3 is undesired.
In 2018.3 I was only able to get this kind of behaviour from an FBX exported from blender in ascii mode. I was unable to get this behaviour from any FBX exported from MAX.
In order to preserve custom normals in MAX while exporting morph targets (blendshapes), I actually have to not export the Smoothing Groups (I’ve shown my export settings in the attached image). Otherwise, MAX will recalculate the normals due to how the Morpher modifier works.
This trick seems to work fine in 2018.2, preserving my custom normals/smoothing groups and retaining them in the blendshapes. Could it be because of the bug you mentioned? I basically want the functionality that was default in 2018.2 (blendshapes not calculating normals at all), and perhaps that’s what the None option is supposed to do, it just doesn’t due to the bug?
There seems to be an issue with some FBX files ending up with calculated blend shape normals when they should be imported. I’ve logged some bugs against these problems but if you’re having trouble right now with blend shape normals getting recalculated (when you don’t want them to be) please take a look at this script editor script for creating a new mesh asset based on any other mesh asset (but with normals copied from the base mesh). Use it like this:
Put this script into your project.
Find the FBX that contains the incorrectly imported blend shape.
Expand the asset to show the mesh, right click on it.
Select ‘Generate Mesh With Fixed Normals’.
Use your fbx model as the basis for your character and then simply drop the exported ‘_fixed’ mesh onto the skinned mesh renderer’s mesh reference. Everything should be preserved apart from the blend shape normals which will be changed.
I hope this helps!
using UnityEngine;
using UnityEditor;
public class FixNormals
{
/*
* Set the normals for each blend shape frame to the
* same normals as the base mesh and export a new mesh
* asset with a sensible name. Select a mesh, right
* click and choose 'Generate Mesh With Fixed Normals'.
*/
[MenuItem("Assets/Generate Mesh With Fixed Normals")]
private static void FixBlendShapeNormals()
{
if(Selection.activeObject.GetType() != typeof(Mesh))
{
Debug.LogError("This isn't a mesh.");
return;
}
Debug.Log("let's fix these blendshape normals!");
Mesh selected = Selection.activeObject as Mesh;
Vector3[] deltaVertices = new Vector3[selected.vertexCount];
Vector3[] deltaNormals = new Vector3[selected.vertexCount];
Vector3[] deltaTangents = new Vector3[selected.vertexCount];
int bsc = selected.blendShapeCount;
Mesh newMesh = new Mesh();
newMesh.vertices = selected.vertices;
newMesh.uv = selected.uv;
newMesh.normals = selected.normals;
newMesh.colors = selected.colors;
newMesh.tangents = selected.tangents;
newMesh.subMeshCount = selected.subMeshCount;
//newMesh.triangles = selected.triangles;
int subMeshes = selected.subMeshCount;
for (int i = 0; i < subMeshes; i++) {
int[] tris = selected.GetTriangles(i);
newMesh.SetIndices(tris, MeshTopology.Triangles, i);
}
newMesh.name = selected.name + "_fixed";
newMesh.boneWeights = selected.boneWeights;
newMesh.bindposes = selected.bindposes;
for (int i = 0; i< bsc; i++)
{
string name = selected.GetBlendShapeName(i);
int weightCount = selected.GetBlendShapeFrameCount(i);
for (int j = 0; j < weightCount; j++)
{
float weight = selected.GetBlendShapeFrameWeight(i, j);
selected.GetBlendShapeFrameVertices(i, j, deltaVertices, deltaNormals, deltaTangents);
newMesh.AddBlendShapeFrame(name, weight, deltaVertices, selected.normals, deltaTangents);
}
}
string savePath = AssetDatabase.GetAssetPath(selected);
savePath = savePath.Substring(0, savePath.LastIndexOf('/') + 1);
string newAssetName = savePath + selected.name + "_fixed.asset";
AssetDatabase.CreateAsset(newMesh, newAssetName);
AssetDatabase.SaveAssets();
Debug.Log("Done!");
}
}
Hi @thomh_unity is there going to be a built in way to get the old behaviour back? Or do we have to use this script in order to have the blendshape normals be the same as the base normals?
Also, does that mean that now normals get blended regardless and therefore the whole operation is more expensive?
Hi thomh, I just wanted to say that the script you provided has literally saved my day!! Thank you so much!! Our project has encountered the exact same problem and this will be our temporary solution. Hopefully it will be fixed soon in 2018.3x since we will not be able to migrate our entire project to 2019.x…
This appears to be fixed in 2019.1.4f1 by setting the “Blend Shape Normals” option in the model importer settings to “None”. Thanks a ton for all your help @thomh_unity !
EDIT: Looks like they also added a “Legacy Blend Shapes” option that arguably works even better! Great work guys, thank you so much.
I am unsure if this is the same issue I am having but when I import my mesh into Unity and look at the animation preview I get strange smoothing or normal issues happening to my mesh. I check in Max and my mesh isn’t showing this. Is it something with my blend shapes or is there a export or import setting I am doing wrong?
Hello. I’m sorry to up this topic, but I’m using unity 2019.2 with Maya 2019 and still can’t import blend shape normals from Maya to Unity.
Here you can see Maya’s source before export and unity’s import
I set my blendshape normals to None and it fixed the issue, my model still has shadows. You said “However, the ‘None’ setting should be used when the object requires no normal information, no lighting” but I havent seen any issues so far.
Do you know how to make this script update the current mesh instead of making a new one?