Skip to content

Commit

Permalink
Merge pull request #601 from anatawa12/multi-frame-blend-shape
Browse files Browse the repository at this point in the history
fix: Multi frame blendshape broken again
  • Loading branch information
anatawa12 authored Oct 16, 2023
2 parents 61415aa + d70cad5 commit a756cee
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 39 deletions.
1 change: 1 addition & 0 deletions CHANGELOG-PRERELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog].
### Removed

### Fixed
- Multi-frame BlendShape can be broken `#601`

### Security

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog].
### Removed

### Fixed
- Multi-frame BlendShape can be broken `#601`

### Security

Expand Down
2 changes: 1 addition & 1 deletion Editor/Processors/MergeBoneProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ private void DoBoneMap2(MeshInfo2 meshInfo2, Dictionary<Transform, Transform> me
vertex.Tangent = new Vector4(tangentVec3.x, tangentVec3.y, tangentVec3.z, vertex.Tangent.w);
foreach (var frames in vertex.BlendShapes.Values)
{
for (var i = 0; i < frames.Count; i++)
for (var i = 0; i < frames.Length; i++)
{
var frame = frames[i];
frames[i] = new Vertex.BlendShapeFrame(
Expand Down
75 changes: 37 additions & 38 deletions Editor/Processors/SkinnedMeshes/MeshInfo2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,12 @@ public void ReadSkinnedMesh([NotNull] Mesh mesh)

BlendShapes.Add((shapeName, 0.0f));

var shapes = new List<Vertex.BlendShapeFrame>[Vertices.Count];

var frameCount = mesh.GetBlendShapeFrameCount(i);

var shapes = new Vertex.BlendShapeFrame[Vertices.Count][];
for (var vertex = 0; vertex < shapes.Length; vertex++)
shapes[vertex] = new Vertex.BlendShapeFrame[frameCount];

for (var frame = 0; frame < frameCount; frame++)
{
mesh.GetBlendShapeFrameVertices(i, frame, deltaVertices, deltaNormals, deltaTangents);
Expand All @@ -176,34 +179,28 @@ public void ReadSkinnedMesh([NotNull] Mesh mesh)
var deltaVertex = deltaVertices[vertex];
var deltaNormal = deltaNormals[vertex];
var deltaTangent = deltaTangents[vertex];
if (shapes[vertex] != null)
{
// this blendshape has meaning so add frame even if delta is 0
shapes[vertex].Add(new Vertex.BlendShapeFrame(weight,
deltaVertex, deltaNormal, deltaTangent));
}
else if (deltaVertex == Vector3.zero && deltaNormal == Vector3.zero &&
deltaTangent == Vector3.zero)
{
// If delta is zero, do not register frame
}
else
{
shapes[vertex] = new List<Vertex.BlendShapeFrame>(frameCount);

for (var prevFrame = 0; prevFrame < frame; prevFrame++)
shapes[vertex].Add(new Vertex.BlendShapeFrame(weight,
Vector3.zero, Vector3.zero, Vector3.zero));

shapes[vertex].Add(new Vertex.BlendShapeFrame(weight, deltaVertices[vertex],
deltaNormals[vertex], deltaTangents[vertex]));
}
shapes[vertex][frame] =
new Vertex.BlendShapeFrame(weight, deltaVertex, deltaNormal, deltaTangent);
}
}

for (var vertex = 0; vertex < shapes.Length; vertex++)
if (shapes[vertex] is List<Vertex.BlendShapeFrame> shapeFrames)
Vertices[vertex].BlendShapes[shapeName] = shapeFrames;
{
if (IsMeaningful(shapes[vertex]))
Vertices[vertex].BlendShapes[shapeName] = shapes[vertex];
}
}

bool IsMeaningful(Vertex.BlendShapeFrame[] frames)
{
foreach (var (_, position, normal, tangent) in frames)
{
if (position != Vector3.zero) return true;
if (normal != Vector3.zero) return true;
if (tangent != Vector3.zero) return true;
}

return false;
}
}

Expand Down Expand Up @@ -486,8 +483,9 @@ public void WriteToMesh(Mesh destMesh)
{
var vertex = Vertices[vertexI];

vertex.TryGetBlendShape(shapeName, weight, out var position, out var normal,
out var tangent);
vertex.TryGetBlendShape(shapeName, weight,
out var position, out var normal, out var tangent,
getDefined: true);
positions[vertexI] = position;
normals[vertexI] = normal;
tangents[vertexI] = tangent;
Expand Down Expand Up @@ -564,8 +562,8 @@ internal class Vertex
public List<(Bone bone, float weight)> BoneWeights = new List<(Bone, float)>();

// Each frame must sorted increasingly
public readonly Dictionary<string, List<BlendShapeFrame>> BlendShapes =
new Dictionary<string, List<BlendShapeFrame>>();
public readonly Dictionary<string, BlendShapeFrame[]> BlendShapes =
new Dictionary<string, BlendShapeFrame[]>();

public readonly struct BlendShapeFrame
{
Expand Down Expand Up @@ -627,7 +625,8 @@ public void SetTexCoord(int index, Vector4 value)
}
}

public bool TryGetBlendShape(string name, float weight, out Vector3 position, out Vector3 normal, out Vector3 tangent)
public bool TryGetBlendShape(string name, float weight, out Vector3 position, out Vector3 normal,
out Vector3 tangent, bool getDefined = false)
{
if (!BlendShapes.TryGetValue(name, out var frames))
{
Expand All @@ -637,15 +636,15 @@ public bool TryGetBlendShape(string name, float weight, out Vector3 position, ou
return false;
}

if (frames.Count == 0)
if (frames.Length == 0)
{
position = default;
normal = default;
tangent = default;
return false;
}

if (Mathf.Abs(weight) <= 0.0001f && ZeroForWeightZero())
if (!getDefined && Mathf.Abs(weight) <= 0.0001f && ZeroForWeightZero())
{
position = Vector3.zero;
normal = Vector3.zero;
Expand All @@ -655,7 +654,7 @@ public bool TryGetBlendShape(string name, float weight, out Vector3 position, ou

bool ZeroForWeightZero()
{
if (frames.Count == 1) return true;
if (frames.Length == 1) return true;
var first = frames.First();
var end = frames.Last();

Expand All @@ -666,7 +665,7 @@ bool ZeroForWeightZero()
return false;
}

if (frames.Count == 1)
if (frames.Length == 1)
{
// simplest and likely
var frame = frames[0];
Expand Down Expand Up @@ -707,13 +706,13 @@ bool ZeroForWeightZero()

// otherwise, lerp between two surrounding frames OR nearest two frames

for (var i = 1; i < frames.Count; i++)
for (var i = 1; i < frames.Length; i++)
{
if (weight <= frames[i].Weight)
return (frames[i - 1], frames[i]);
}

return (frames[frames.Count - 2], frames[frames.Count - 1]);
return (frames[frames.Length - 2], frames[frames.Length - 1]);
}

float InverseLerpUnclamped(float a, float b, float value) => (value - a) / (b - a);
Expand All @@ -738,7 +737,7 @@ private Vertex(Vertex vertex)
TexCoord7 = vertex.TexCoord7;
Color = vertex.Color;
BoneWeights = vertex.BoneWeights.ToList();
BlendShapes = new Dictionary<string, List<BlendShapeFrame>>(vertex.BlendShapes);
BlendShapes = new Dictionary<string, BlendShapeFrame[]>(vertex.BlendShapes);
}

public Vertex Clone() => new Vertex(this);
Expand Down

0 comments on commit a756cee

Please sign in to comment.