tests/CitizenAnimationSetup/SmartPortCopiedGripTests.cs
using System.Numerics;
using HumanoidRetargeter.Maths;
using HumanoidRetargeter.Skeleton;
using HumanoidRetargeter.Target;
using HumanoidRetargeter.Tests.Skeleton;
using Xunit;
using SkeletonModel = HumanoidRetargeter.Skeleton.Skeleton;

namespace HumanoidRetargeter.Tests.Target;

public class SmartPortCopiedGripTests
{
    [Fact]
    public void NewCrossHandGoalKeepsSourceGripSeparationOnDifferentArmRestPose()
    {
        var original = TargetRig.Load(TargetRigGenerator.Generate(File.ReadAllText(SkeletonTests.FixturePath("rig_human_male.json")))).Skeleton;
        const string goal = "new_support_goal";
        var definitions = original.Bones.Select(b => new BoneDefinition(b.Name,
            b.ParentIndex < 0 ? null : original[b.ParentIndex].Name, b.RestLocal)).ToList();
        definitions.Add(new(goal, "hand_R", XForm.ToLocal(original.RestWorld[original.IndexOf("hand_R")],
            original.RestWorld[original.IndexOf("hand_L")])));
        var source = SkeletonModel.Create(definitions);
        var target = SkeletonModel.Create(original.Bones.Select(b => new BoneDefinition(b.Name,
            b.ParentIndex < 0 ? null : original[b.ParentIndex].Name,
            new XForm(b.RestLocal.Pos * (b.Name == "arm_lower_L" ? .55f : .8f), b.RestLocal.Rot * (b.Name == "arm_upper_L"
                ? Quaternion.CreateFromAxisAngle(Vector3.UnitY, .6f) : Quaternion.Identity)))).ToArray());
        var rig = new SmartPortRig(source, target, new Dictionary<string, string> { [goal] = "hand_L" });
        var pose = source.Bones.Select(b => b.RestLocal).ToArray();
        pose[source.IndexOf("arm_lower_R")].Rot *= Quaternion.CreateFromAxisAngle(Vector3.UnitY, .5f);
        var input = new Pose(pose).ToWorld(source);
        var output = new Pose(rig.Transfer(pose)).ToWorld(rig.Target);
        var expected = (input[source.IndexOf(goal)].Pos - input[source.IndexOf("hand_R")].Pos) * rig.MotionScale;
        var actual = output[rig.Target.IndexOf(goal)].Pos - output[rig.Target.IndexOf("hand_R")].Pos;
        Assert.True(Vector3.Distance(expected, actual) < .001f, $"Expected relative grip {expected}, got {actual}");
    }
}