Fix Multi Blend 2D node if all blend points are on the same line

#719
This commit is contained in:
Wojtek Figat
2022-06-14 20:46:55 +02:00
parent 2bf6fac77d
commit 3925c6221c
2 changed files with 60 additions and 13 deletions

View File

@@ -216,15 +216,17 @@ bool AnimGraphBase::onNodeLoaded(Node* n)
Delaunay2D::Triangulate(vertices, triangles);
if (triangles.Count() == 0)
{
switch (vertices.Count())
// Insert dummy triangles to have something working (eg. blend points are on the same axis)
int32 verticesLeft = vertices.Count();
while (verticesLeft >= 3)
{
case 1:
triangles.Add(Delaunay2D::Triangle(0, 0, 0));
break;
case 2:
triangles.Add(Delaunay2D::Triangle(0, 1, 0));
break;
verticesLeft -= 3;
triangles.Add(Delaunay2D::Triangle(verticesLeft, verticesLeft + 1, verticesLeft + 2));
}
if (verticesLeft == 1)
triangles.Add(Delaunay2D::Triangle(0, 0, 0));
else if (verticesLeft == 2)
triangles.Add(Delaunay2D::Triangle(0, 1, 0));
}
// Store triangles vertices indices (map the back to the anim node slots)

View File

@@ -1225,9 +1225,9 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
break;
}
const auto v0 = points[1] - points[0];
const auto v1 = points[2] - points[0];
const auto v2 = p - points[0];
auto v0 = points[1] - points[0];
auto v1 = points[2] - points[0];
auto v2 = p - points[0];
const float d00 = Float2::Dot(v0, v0);
const float d01 = Float2::Dot(v0, v1);
@@ -1237,8 +1237,53 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
const float coeff = (d00 * d11 - d01 * d01);
if (Math::IsZero(coeff))
{
// Use only vertex A for invalid triangle
value = SampleAnimation(node, loop, data.Length, startTimePos, bucket.TimePosition, newTimePos, aAnim, aData.W);
const bool xAxis = Math::IsZero(v0.X) && Math::IsZero(v1.X);
const bool yAxis = Math::IsZero(v0.Y) && Math::IsZero(v1.Y);
if (xAxis || yAxis)
{
if (yAxis)
{
// Use code for X-axis case so swap coordinates
Swap(v0.X, v0.Y);
Swap(v1.X, v1.Y);
Swap(v2.X, v2.Y);
Swap(p.X, p.Y);
}
// Use 1D blend if points are on the same line (degenerated triangle)
// TODO: simplify this code
if (v1.Y >= v0.Y)
{
if (p.Y < v0.Y && v1.Y >= v0.Y)
{
const float alpha = p.Y / v0.Y;
value = SampleAnimationsWithBlend(node, loop, data.Length, startTimePos, bucket.TimePosition, newTimePos, aAnim, bAnim, aData.W, bData.W, alpha);
}
else
{
const float alpha = (p.Y - v0.Y) / (v1.Y - v0.Y);
value = SampleAnimationsWithBlend(node, loop, data.Length, startTimePos, bucket.TimePosition, newTimePos, bAnim, cAnim, bData.W, cData.W, alpha);
}
}
else
{
if (p.Y < v1.Y)
{
const float alpha = p.Y / v1.Y;
value = SampleAnimationsWithBlend(node, loop, data.Length, startTimePos, bucket.TimePosition, newTimePos, aAnim, cAnim, aData.W, cData.W, alpha);
}
else
{
const float alpha = (p.Y - v1.Y) / (v0.Y - v1.Y);
value = SampleAnimationsWithBlend(node, loop, data.Length, startTimePos, bucket.TimePosition, newTimePos, cAnim, bAnim, cData.W, bData.W, alpha);
}
}
}
else
{
// Use only vertex A for invalid triangle
value = SampleAnimation(node, loop, data.Length, startTimePos, bucket.TimePosition, newTimePos, aAnim, aData.W);
}
break;
}
const float v = (d11 * d20 - d01 * d21) / coeff;
@@ -1280,7 +1325,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
}
}
// Check if use the closes sample
// Check if use the closest sample
if ((void*)value == nullptr && hasBest)
{
const auto aAnim = node->Assets[bestAnims[0]].As<Animation>();