Created
June 15, 2024 21:24
-
-
Save xabblll/c0e4cfbf025a02e8dfb7a8deb17657f5 to your computer and use it in GitHub Desktop.
Unity3D - Model postprocessor for fixing blend shapes normals and tangents
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Place inside Editor folder | |
using UnityEditor; | |
using UnityEngine; | |
namespace Code.Editor | |
{ | |
public class MeshPostprocessor : AssetPostprocessor | |
{ | |
private void OnPostprocessModel(GameObject g) | |
{ | |
var smrs = g.GetComponentsInChildren<SkinnedMeshRenderer>(); | |
for (int i = 0; i < smrs.Length; i++) | |
{ | |
FixShapes(smrs[i]); | |
} | |
} | |
private struct ShapeData | |
{ | |
public string Name; | |
public float Weight; | |
public Vector3[] DeltaVertices; | |
public Vector3[] DeltaNormals; | |
public Vector3[] DeltaTangents; | |
} | |
private static void FixShapes(SkinnedMeshRenderer smr) | |
{ | |
// Looks OK, but maybe should be increased | |
const float eps = float.Epsilon; | |
var mesh = smr.sharedMesh; | |
var vertexCount = mesh.vertexCount; | |
var shapeCount = mesh.blendShapeCount; | |
var shapeDataArray = new ShapeData[shapeCount]; | |
for (int i = 0; i < shapeCount; i++) | |
{ | |
shapeDataArray[i].Name = mesh.GetBlendShapeName(i); | |
// Add support for multiple frames in one shape? | |
shapeDataArray[i].Weight = mesh.GetBlendShapeFrameWeight(i, 0); | |
shapeDataArray[i].DeltaVertices = new Vector3[vertexCount]; | |
shapeDataArray[i].DeltaNormals = new Vector3[vertexCount]; | |
shapeDataArray[i].DeltaTangents = new Vector3[vertexCount]; | |
mesh.GetBlendShapeFrameVertices(i, 0, shapeDataArray[i].DeltaVertices, shapeDataArray[i].DeltaNormals, shapeDataArray[i].DeltaTangents); | |
// Clean "empty" vertices | |
for (int j = 0; j < vertexCount; j++) | |
{ | |
if (Vector3.SqrMagnitude(shapeDataArray[i].DeltaVertices[j]) < eps) | |
{ | |
shapeDataArray[i].DeltaVertices[j] = Vector3.zero; | |
shapeDataArray[i].DeltaNormals [j] = Vector3.zero; | |
shapeDataArray[i].DeltaTangents[j] = Vector3.zero; | |
} | |
} | |
} | |
mesh.ClearBlendShapes(); | |
// Add all shapes back | |
for (int i = 0; i < shapeDataArray.Length; i++) | |
{ | |
mesh.AddBlendShapeFrame(shapeDataArray[i].Name, shapeDataArray[i].Weight, shapeDataArray[i].DeltaVertices, shapeDataArray[i].DeltaNormals, shapeDataArray[i].DeltaTangents); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Pic: blend shape moves vertices on body, hand vertices shouldn't change
This postprocessor can help fix blend shape artifacts. Basically if you import model with blend shape, some vertices with zero changes will generate garbage data, resulting in incorrect normals and tangents.
If you still having this artifact, try to increasing "eps" value