Ejemplo n.º 1
0
    public void TestTransformConsistency()
    {
        var builder       = new BoneSystemBuilder();
        var bone0         = builder.AddBone("bone0", null, new Vector3(1, 0, 0), new Vector3(2, 0, 0), Vector3.Zero);
        var bone1         = builder.AddBone("bone1", bone0, new Vector3(2, 0, 0), new Vector3(3, 0, 0), Vector3.Zero);
        var bone2         = builder.AddBone("bone2", bone1, new Vector3(3, 0, 0), new Vector3(4, 0, 0), Vector3.Zero);
        var channelSystem = builder.BuildChannelSystem();
        var boneSystem    = builder.BuildBoneSystem();

        var rigidBoneSystem = new RigidBoneSystem(boneSystem);

        var baseInputs = channelSystem.MakeDefaultChannelInputs();

        bone1.Scale.SetValue(baseInputs, new Vector3(2, 3, 4));
        bone1.Translation.SetValue(baseInputs, new Vector3(4, 5, 6));
        bone2.Translation.SetValue(baseInputs, new Vector3(5, 6, 7));

        var baseOutputs = channelSystem.Evaluate(null, baseInputs);

        rigidBoneSystem.Synchronize(baseOutputs);
        var rigidBaseInputs = rigidBoneSystem.ReadInputs(baseOutputs);

        var rigidInputs = new RigidBoneSystemInputs(rigidBaseInputs);

        rigidBoneSystem.Bones[0].SetRotation(rigidInputs, Quaternion.RotationYawPitchRoll(0.1f, 0.2f, 0.3f));
        rigidBoneSystem.Bones[1].SetRotation(rigidInputs, Quaternion.RotationYawPitchRoll(0.2f, 0.3f, 0.4f));
        rigidBoneSystem.Bones[2].SetRotation(rigidInputs, Quaternion.RotationYawPitchRoll(0.3f, 0.4f, 0.5f));

        var inputs = new ChannelInputs(baseInputs);

        rigidBoneSystem.WriteInputs(inputs, baseOutputs, rigidInputs);
        var outputs = channelSystem.Evaluate(null, inputs);

        var baseTransforms = boneSystem.GetBoneTransforms(baseOutputs);
        var transforms     = boneSystem.GetBoneTransforms(outputs);

        var rigidBaseTransforms = rigidBoneSystem.GetBoneTransforms(rigidBaseInputs);
        var rigidTransforms     = rigidBoneSystem.GetBoneTransforms(rigidInputs);

        for (int transformIdx = 0; transformIdx < transforms.Length; ++transformIdx)
        {
            var baseTransform = baseTransforms[transformIdx];
            var transform     = transforms[transformIdx];

            var rigidBaseTransform = rigidBaseTransforms[transformIdx];
            var rigidTransform     = rigidTransforms[transformIdx];

            foreach (var testPoint in new [] { Vector3.Zero, Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ })
            {
                var unposedPoint = baseTransform.InverseTransform(testPoint);
                var posedPoint   = transform.Transform(unposedPoint);

                var unposedRigidPoint = rigidBaseTransform.InverseTransform(testPoint);
                var posedRigidPoint   = rigidTransform.Transform(unposedRigidPoint);

                float distance = Vector3.Distance(posedPoint, posedRigidPoint);
                Assert.AreEqual(0, distance, 1e-3);
            }
        }
    }
Ejemplo n.º 2
0
    private void CheckConsistency(ChannelOutputs channelOutputs)
    {
        var inputs = rigidBoneSystem.ReadInputs(channelOutputs);

        var boneTransformsA = boneSystem.GetBoneTransforms(channelOutputs);
        var boneTransformsB = rigidBoneSystem.GetBoneTransforms(inputs);

        for (int i = 0; i < boneSystem.Bones.Count; ++i)
        {
            var boneTransformA = boneTransformsA[i];
            var boneTransformB = boneTransformsB[i];

            var unposedCenterA = boneSystem.Bones[i].CenterPoint.GetValue(channelOutputs);
            var unposedCenterB = rigidBoneSystem.Bones[i].CenterPoint;

            foreach (var testVector in new Vector3[] { Vector3.Zero, Vector3.Right, Vector3.Up, Vector3.BackwardRH })
            {
                var transformedVectorA = boneTransformA.Transform(unposedCenterA + testVector);
                var transformedVectorB = boneTransformB.Transform(
                    unposedCenterB + boneTransformA.ScalingStage.Transform(testVector));
                float distance = Vector3.Distance(transformedVectorA, transformedVectorB);

                if (distance > 1e-3)
                {
                    throw new Exception("rigid and non-rigid bone transforms are inconsistent");
                }
            }
        }
    }
Ejemplo n.º 3
0
    private void Solve(RigidBoneSystem boneSystem, InverseKinematicsGoal goal, RigidBoneSystemInputs inputs)
    {
        var bone = boneSystem.BonesByName[boneName];

        //get bone transforms with the current bone rotation zeroed out
        inputs.Rotations[bone.Index] = TwistSwing.Zero;
        var boneTransforms = boneSystem.GetBoneTransforms(inputs);
        var boneTransform  = boneTransforms[bone.Index];

        var worldSourcePosition  = boneTransforms[goal.SourceBone.Index].Transform(goal.SourceBone.CenterPoint + goal.UnposedSourcePosition);
        var worldTargetPosition  = goal.TargetPosition;
        var worldCenterPosition  = boneTransform.Transform(bone.CenterPoint);
        var worldSourceDirection = Vector3.Normalize(worldSourcePosition - worldCenterPosition);
        var worldTargetDirection = Vector3.Normalize(worldTargetPosition - worldCenterPosition);

        //transform source and target to bone's oriented space
        var parentTotalRotation             = bone.Parent != null ? boneTransforms[bone.Parent.Index].Rotation : Quaternion.Identity;
        var orientedSpaceToWorldTransform   = bone.OrientationSpace.Orientation.Chain(parentTotalRotation);
        var worldToOrientatedSpaceTransform = Quaternion.Invert(orientedSpaceToWorldTransform);
        var orientedSourceDirection         = Vector3.Transform(worldSourceDirection, worldToOrientatedSpaceTransform);
        var orientedTargetDirection         = Vector3.Transform(worldTargetDirection, worldToOrientatedSpaceTransform);

        CartesianAxis twistAxis           = (CartesianAxis)bone.RotationOrder.primaryAxis;
        var           newOrientedRotation = Swing.FromTo(twistAxis, orientedSourceDirection, orientedTargetDirection);

        bone.SetOrientedSpaceRotation(inputs, new TwistSwing(Twist.Zero, newOrientedRotation), true);
    }
Ejemplo n.º 4
0
    private void DoIteration(RigidBoneSystem boneSystem, InverseKinematicsGoal goal, RigidBoneSystemInputs inputs)
    {
        var boneTransforms = boneSystem.GetBoneTransforms(inputs);
        var sourcePosition = boneTransforms[goal.SourceBone.Index].Transform(goal.SourceBone.CenterPoint + goal.UnposedSourcePosition);

        float weight = 0.5f;

        for (var bone = goal.SourceBone; bone != boneSystem.RootBone && bone.Parent != boneSystem.RootBone; bone = bone.Parent)
        {
            ApplyCorrection(inputs, boneTransforms, bone, ref sourcePosition, goal.TargetPosition, weight);
        }
    }
Ejemplo n.º 5
0
    private void ApplyPositionGoal(InverseKinematicsGoal goal, RigidBoneSystemInputs inputs)
    {
        var boneTransforms = boneSystem.GetBoneTransforms(inputs);
        var centersOfMass  = GetCentersOfMass(boneTransforms);

        var sourcePosition = boneTransforms[goal.SourceBone.Index].Transform(goal.SourceBone.CenterPoint + goal.UnposedSourcePosition);

        var bones = GetBoneChain(goal.SourceBone, goal.HasOrientation).ToArray();
        //var bones = new RigidBone[] { boneSystem.BonesByName["lForearmBend"], boneSystem.BonesByName["lShldrBend"] };

        var massMoments          = GetMassMoments(boneTransforms, bones);
        var figureCenterOverride = massMoments[0].GetCenterOfMass();

        float totalRate = 0;

        var bonePartialSolutions = new BonePartialSolution[bones.Length];

        for (int i = 0; i < bones.Length; ++i)
        {
            var partialSolution = SolveSingleBone(bones[i], sourcePosition, goal.TargetPosition, massMoments, figureCenterOverride, inputs, boneTransforms);

            bonePartialSolutions[i] = partialSolution;
            totalRate += 1 / partialSolution.time;
        }

        var rootTranslationPartialSolution = SolveRootTranslation(sourcePosition, goal.TargetPosition);

        totalRate += 1 / rootTranslationPartialSolution.time;

        float time = 1 / totalRate;

        for (int i = 0; i < bones.Length; ++i)
        {
            ApplyPartialSolution(bones[i], bonePartialSolutions[i], boneTransforms, figureCenterOverride, inputs, time);
        }
        ApplyPartialSolution(rootTranslationPartialSolution, inputs, time);

        CountertransformOffChainBones(boneTransforms, centersOfMass, inputs, bones);
    }