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"); } } } }
public InverseKinematicsPerformanceDemo() { var figureDir = UnpackedArchiveDirectory.Make(new System.IO.DirectoryInfo("work/figures/genesis-3-female")); var channelSystemRecipe = Persistance.Load <ChannelSystemRecipe>(figureDir.File("channel-system-recipe.dat")); channelSystem = channelSystemRecipe.Bake(null); var boneSystemRecipe = Persistance.Load <BoneSystemRecipe>(figureDir.File("bone-system-recipe.dat")); boneSystem = boneSystemRecipe.Bake(channelSystem.ChannelsByName); var inverterParameters = Persistance.Load <InverterParameters>(figureDir.File("inverter-parameters.dat")); rigidBoneSystem = new RigidBoneSystem(boneSystem); goalProvider = new DemoInverseKinematicsGoalProvider(rigidBoneSystem); solver = new HarmonicInverseKinematicsSolver(rigidBoneSystem, inverterParameters.BoneAttributes); var pose = Persistance.Load <List <Pose> >(figureDir.File("animations/idle.dat"))[0]; var channelInputs = channelSystem.MakeDefaultChannelInputs(); new Poser(channelSystem, boneSystem).Apply(channelInputs, pose, DualQuaternion.Identity); var channelOutputs = channelSystem.Evaluate(null, channelInputs); rigidBoneSystem.Synchronize(channelOutputs); initialInputs = rigidBoneSystem.ReadInputs(channelOutputs); }
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); } } }
public void Update(FrameUpdateParameters updateParameters, ChannelInputs channelInputs, ControlVertexInfo[] previousFrameControlVertexInfos) { var channelOutputs = channelSystem.Evaluate(null, channelInputs); boneSystem.Synchronize(channelOutputs); var baseInputs = boneSystem.ReadInputs(channelOutputs); var resultInputs = boneSystem.ApplyDeltas(baseInputs, poseDeltas); List <InverseKinematicsGoal> goals = goalProvider.GetGoals(updateParameters, resultInputs, previousFrameControlVertexInfos); solver.Solve(boneSystem, goals, resultInputs); poseDeltas = boneSystem.CalculateDeltas(baseInputs, resultInputs); boneSystem.WriteInputs(channelInputs, channelOutputs, resultInputs); }