/// <summary> /// Generates a global posture containing the list of joints with position and rotation in global space /// Required to pass on to the retargeting service. /// </summary> /// <returns></returns> public virtual MAvatarPosture GenerateGlobalPosture() { List <MJoint> Joints = new List <MJoint>(); if (this.UseVirtualRoot) { Joints = new List <MJoint>() { new MJoint("_VirtualRoot", MJointType.Root, this.RootTransform.position.ToMVector3(), this.RootTransform.rotation.ToMQuaternion()) }; } //Create a new posture MAvatarPosture globalPosture = new MAvatarPosture { AvatarID = this.AvatarID, Joints = Joints }; //Determine the joint values and write it into the posture this.Pelvis.GenerateGlobalJoints(this.bonenameMap, globalPosture.Joints); //Return the generated posture return(globalPosture); }
/// <summary> /// Basic initialization methid /// </summary> /// <param name="avatarDescription"></param> /// <param name="properties"></param> /// <returns></returns> public override MBoolResponse Initialize(MAvatarDescription avatarDescription, Dictionary <string, string> properties) { //Execute instructions on main thread this.ExecuteOnMainThread(() => { //Call the base class initialization -> Retargeting is also set up in there base.Initialize(avatarDescription, properties); this.MotionType = "idle"; this.animator = this.GetComponent <Animator>(); //Set animation mode to always animate (even if not visible) this.animator.cullingMode = AnimatorCullingMode.AlwaysAnimate; this.animator.enabled = false; this.Name = "UnityIdleMMU"; //Get the initial posture this.animator.Update(0.01f); //Get the initial posture this.initialPosture = this.GetZeroPosture(); }); return(new MBoolResponse(true)); }
/// <summary> /// Retargets the global posture to the intermediate skeleton /// </summary> /// <param name="globalTarget"></param> /// <returns></returns> public MAvatarPostureValues RetargetToIntermediate(MAvatarPosture globalTarget) { RJoint root = ((RJoint)this.skeleton.GetRoot(globalTarget.AvatarID)); bool rootFound = false; foreach (MJoint j in globalTarget.Joints) { if (j.Type != MJointType.Undefined) { RJoint rj = ((RJoint)root.GetChild(j.Type)); rj.RetargetPositionToIS(j.Position, j.Rotation); rj.RetargetRotationToIS(j.Rotation); if (!rootFound) { rootFound = true; if (j.Type == MJointType.Root) { } else { MVector3 globalPos = rj.GetGlobalPosManually(); root.SetGlobalPosManually(new MVector3(globalPos.X, 0, globalPos.Z)); //rj.SetGlobalPosManually(new MVector3(0, globalPos.Y, 0)); } } } } root.RecomputeLocalTransformations(); MAvatarPostureValues ret = new MAvatarPostureValues(globalTarget.AvatarID, root.GetAvatarPostureValues()); return(ret); }
/// <summary> /// Method sets up the retargeting of the specified avaatar using an initial posture /// </summary> /// <param name="id"></param> /// <param name="reference"></param> /// <returns></returns> public virtual MAvatarPosture SetupRetargeting(string id, MAvatarPosture reference) { this.AvatarID = id; Animator anim = this.GetComponent <Animator>(); this.animatorReference = anim; if (reference != null) { this.bonenameMap = new Dictionary <string, MJointType>(); foreach (MJoint j in reference.Joints) { if (!this.bonenameMap.ContainsKey(j.ID)) { this.bonenameMap.Add(j.ID, j.Type); } } } if (this.bonenameMap == null) { this.bonenameMap = new Dictionary <string, MJointType>(); foreach (MJointType b in humanbonemap.Keys) { bonenameMap.Add(anim.GetBoneTransform(humanbonemap[b]).name, b); } } MAvatarPosture p; if (reference != null) { retargetingService.SetupRetargeting(reference); skeleton = retargetingService.GetSkeleton(); p = reference; } else { p = this.GenerateGlobalPosture(); retargetingService.SetupRetargeting(p); skeleton = retargetingService.GetSkeleton(); } //Create an empty joint object if not defined if (this.gameJointPrefab == null) { this.gameJointPrefab = new GameObject("emptyJoint"); } if (UseSkeletonVisualization) { skelVis = new SkeletonVisualization(skeleton, retargetingService, this.Pelvis, this.bonenameMap, this.AvatarID, gameJointPrefab); } this.AssignPostureValues(this.GetPosture()); return(p); }
/// <summary> /// Performs a blending based on the from posture and the to posture. In particular a blending weight and an additional blending mask is utilized. If the blending mask is set to null, all bones with position + rotation will be used for blending. /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <param name="weight"></param> /// <param name="blendingMask"></param> /// <returns></returns> public static MAvatarPostureValues PerformBlend(IntermediateSkeleton skeleton, MAvatarPostureValues from, MAvatarPostureValues to, float weight, Dictionary <MJointType, BlendProperty> blendingMask = null) { //MAvatarPosture result = from.Clone(); MAvatarPosture zero = skeleton.GetAvatarDescription(from.AvatarID).ZeroPosture; skeleton.SetChannelData(from); List <MQuaternion> fromRot = skeleton.GetLocalJointRotations(from.AvatarID); skeleton.SetChannelData(to); List <MQuaternion> toRot = skeleton.GetLocalJointRotations(to.AvatarID); for (int i = 0; i < zero.Joints.Count; i++) { //By default belnd both position and rotation BlendProperty blendProperty = new BlendProperty(1.0f, 1.0f); MJointType joint = zero.Joints[i].Type; if (blendingMask != null && blendingMask.ContainsKey(joint)) { //Get the bone weight blendingMask.TryGetValue(joint, out blendProperty); } //Perform a linear interpolation of the position // Does not correspond to intermediate skeleton representation. // result.Joints[i].Position = result.Joints[i].Position.Lerp(to.Joints[i].Position, weight * blendProperty.PositionWeight); //Perform a slerp of the rotation skeleton.SetLocalJointRotation(to.AvatarID, joint, fromRot[i].Slerp(toRot[i], weight * blendProperty.RotationWeight)); } return(skeleton.RecomputeCurrentPostureValues(to.AvatarID)); }
public MAvatarDescription SetupRetargeting(MAvatarPosture globalTarget) { Console.WriteLine("\nSetting up retargeting"); string id = globalTarget.AvatarID; Dictionary <MJointType, string> joint_map = new Dictionary <MJointType, string>(); Dictionary <string, string> _children = new Dictionary <string, string>(); foreach (MJoint j in globalTarget.Joints) { if (j.Type != MJointType.Undefined) { joint_map.Add(j.Type, j.ID); } if (j.Parent != null && j.Parent != "") { if (_children.ContainsKey(j.Parent)) { // parent has multiple children and thus cannot be auto - aligned _children[j.Parent] = ""; } else { _children.Add(j.Parent, j.ID); } } } this.children.Add(id, _children); if (joint_mappings.ContainsKey(id)) { Console.WriteLine("Warning: Skeleton alread existing under ID " + id); this.joint_mappings[id] = joint_map; } else { this.joint_mappings.Add(id, joint_map); } if (basePostures.ContainsKey(id)) { this.basePostures[id] = globalTarget; } else { this.basePostures.Add(id, globalTarget); } MAvatarDescription desc = IntermediateSkeleton.GenerateFromDescriptionFile(id); this.skeleton.InitializeAnthropometry(desc); Console.WriteLine("Scaling Skeleton"); ((RJoint)this.skeleton.GetRoot(id)).ScaleSkeleton(globalTarget, joint_map); Console.WriteLine("Initializing Zero Posture"); this.skeleton.GetRoot(id).SetAvatarPostureValues(null); Console.WriteLine("Setting Base Reference"); ((RJoint)this.skeleton.GetRoot(id)).SetBaseReference(globalTarget); Console.WriteLine("Retargeting Successfully set up"); return(desc); }
/// <summary> /// Method to setup the actual retargeting /// </summary> protected virtual void SetupRetargeting() { //Only do the retargeting setup if not happened in before if (!setupRetargeting) { setupRetargeting = true; // find and load retargeting configuration file //Create a unique id for the avatar (only valid in the current session -> otherwise UUID required) string id = UnitySceneAccess.CreateAvatarID(); //Only load the configuration if defined if (LoadRetargetingConfiguration) { if (!System.IO.File.Exists(Application.dataPath + "/" + this.ConfigurationFilePath)) { Debug.LogError($"Problem setting up retargeting: The required file: {Application.dataPath + "/" + this.ConfigurationFilePath} is not available"); return; } string skelConf = System.IO.File.ReadAllText(Application.dataPath + "/" + this.ConfigurationFilePath); MAvatarPosture p = MMICSharp.Common.Communication.Serialization.FromJsonString <MAvatarPosture>(skelConf);//JsonConvert.DeserializeObject<MAvatarPosture>(skelConf); p.AvatarID = id; this.SetupRetargeting(id, p); this.AssignPostureValues(retargetingService.RetargetToIntermediate(p)); } //If not defined use the global posture else { this.SetupRetargeting(id); } MAvatarDescription avatarDescription = this.GetSkeletonAccess().GetAvatarDescription(id); //Create a new MAvatar (the representation within MMI framework) MAvatarPostureValues zeroPosture = this.GetSkeletonAccess().GetCurrentPostureValues(id); //Create the avatar this.MAvatar = new MAvatar() { Name = this.name, ID = id, Description = avatarDescription, PostureValues = zeroPosture, Properties = new Dictionary <string, string>(), SceneObjects = new List <string>() }; //Add the avatar to the scene access UnitySceneAccess.AddAvatar(this.MAvatar); Debug.Log("Retargeting successfully set up"); } }
/// <summary> /// Draws the given avatar posture /// </summary> /// <param name="posture"></param> /// <returns></returns> public static GameObject DrawAvatarPosture(MAvatarPosture posture) { GameObject root = new GameObject(); Dictionary <string, GameObject> transforms = new Dictionary <string, GameObject>(); if (posture == null || posture.Joints == null) { return(root); } foreach (MJoint boneTransform in posture.Joints) { //Create an empty gameobject for each bone GameObject joint = new GameObject(boneTransform.ID); joint.transform.position = boneTransform.Position.ToVector3(); joint.transform.rotation = boneTransform.Rotation.ToQuaternion(); transforms.Add(joint.name, joint); } foreach (MJoint boneTransform in posture.Joints) { GameObject joint = transforms[boneTransform.ID]; //Compute the global position if (boneTransform.Parent != null && transforms.ContainsKey(boneTransform.Parent)) { joint.transform.position = transforms[boneTransform.Parent].transform.TransformPoint(joint.transform.position); joint.transform.rotation = transforms[boneTransform.Parent].transform.rotation * joint.transform.rotation; joint.transform.parent = transforms[boneTransform.Parent].transform; } else { joint.transform.parent = root.transform; } } foreach (GameObject gameObject in transforms.Values) { if (gameObject.transform.parent != null && transforms.ContainsKey(gameObject.transform.parent.name)) { var lr = gameObject.AddComponent <LineRenderer>(); lr.material.shader = Shader.Find("Particles/Standard Surface"); lr.SetPositions(new Vector3[] { gameObject.transform.parent.position, gameObject.transform.position }); lr.startWidth = 0.02f; lr.endWidth = 0.02f; lr.startColor = Color.red; lr.endColor = Color.blue; } } return(root); }
public void SetBaseReference(MAvatarPosture posture) { foreach (MJoint j in posture.Joints) { if (j.Type != MJointType.Undefined) { RJoint rj = (RJoint)this.GetChild(j.Type); rj.SetBaseReference(j.Rotation, j.Position); } } }
private MVector3 GetFingerPosition(MAvatarPosture globalTarget, Dictionary <MJointType, string> joint_map, double z_shift) { MVector3 wristPos = getJointPosition(globalTarget, joint_map[this.parentJoint.GetMJoint().Type]);//this.parentJoint.GetGlobalPosition(); MVector3 thisPos = getJointPosition(globalTarget, joint_map[this.GetMJoint().Type]); thisPos.Y = wristPos.Y; // adjust height MVector3 newPos = new MTransform("tmp", wristPos, this.parentJoint.GetGlobalRotation()).InverseTransformPoint(thisPos); newPos.Z -= z_shift; return(newPos); }
private static MVector3 getJointPosition(MAvatarPosture globalTarget, string joint) { foreach (MJoint j in globalTarget.Joints) { if (j.ID == joint) { return(new MVector3(j.Position.X, j.Position.Y, j.Position.Z)); } } return(new MVector3(0, 0, 0)); }
/// <summary> /// Applies the transform manipulations to be reflected in the intermediate skeleton /// </summary> public virtual void ApplyTransformManipulations() { //Update the intermediate skeleton with the new values //Get the global posture MAvatarPosture globalPosture = this.GenerateGlobalPosture(); //Perform a retargeting to the intermediate skeleton MAvatarPostureValues intermediatePostureValues = retargetingService.RetargetToIntermediate(globalPosture); //Apply the posture values this.skeleton.SetChannelData(intermediatePostureValues); }
/// <summary> /// Returns the retargeted posture represented in the intermediate skeleton used in the MMI framework /// </summary> /// <returns></returns> public MAvatarPostureValues GetRetargetedPosture() { // Return retargeted posture from target Avatar to intermediate skeleton. MAvatarPosture p = this.GenerateGlobalPosture(); MAvatarPostureValues vals = this.retargetingService.RetargetToIntermediate(p); if (this.skelVis != null) { this.skelVis.AssignPostureValues(); } return(vals); }
/// <summary> /// Method sets up the retargeting of the specified avatar using the defined configuration file /// </summary> /// <param name="id"></param> /// <returns></returns> public virtual MAvatarPosture SetupRetargeting(string id) { MAvatarPosture p = null; if (System.IO.File.Exists(this.ConfigurationFilePath)) { string s = System.IO.File.ReadAllText(this.ConfigurationFilePath); p = MMICSharp.Common.Communication.Serialization.FromJsonString <MAvatarPosture>(s); //JsonConvert.DeserializeObject<MAvatarPosture>(s); p.AvatarID = id; } return(this.SetupRetargeting(id, p)); }
private static MVector3 GetRelativePositionToParent(MAvatarPosture globalTarget, string joint, string parent) { foreach (MJoint j in globalTarget.Joints) { if (j.ID == joint) { foreach (MJoint jP in globalTarget.Joints) { if (jP.ID == parent) { return(new MTransform("tmp", jP.Position, jP.Rotation).InverseTransformPoint(j.Position)); } } } } return(new MVector3(0, 0, 0)); }
/// <summary> /// Assigns the pose to the avatar. /// </summary> /// <param name="pose"></param> /// <param name="assignLocalPositions">Specifies whether the local positions are assigned as well</param> public virtual void AssignPostureValues(MAvatarPostureValues pose, bool assignLocalPositions = true) { //Perform a retargeting to the specific skeleton using the retargeting service MAvatarPosture p = this.retargetingService.RetargetToTarget(pose); //Update the values of the skeletal representation skeleton.SetChannelData(pose); //Compute the root transformation if defined /* * if (this.AutoComputeRootTransform) * { * MVector3 globalRootBonePosition = skeleton.GetRootPosition(this.AvatarID); * MQuaternion globalRootBoneRotation = skeleton.GetRootRotation(this.AvatarID); * * * //Compute the root transform * this.RootTransform.position = new Vector3((float)globalRootBonePosition.X, this.RootTransform.position.y, (float)globalRootBonePosition.Z); * //this.RootBone.transform.position = globalRootBonePosition.ToVector3(); * * * Vector3 currentEulerRoot = this.RootTransform.eulerAngles; * this.RootTransform.rotation = Quaternion.Euler(currentEulerRoot.x, globalRootBoneRotation.ToQuaternion().eulerAngles.y - 90.0f, currentEulerRoot.z); * //this.RootBone.transform.rotation = globalRootBoneRotation.ToQuaternion(); * * MTransform CharTransform = new MTransform("tmp", this.RootTransform.position.ToMVector3(), this.RootTransform.rotation.ToMQuaternion()); * } */ // Update root transform this.RootTransform.transform.position = p.Joints[0].Position.ToVector3(); this.RootTransform.transform.rotation = p.Joints[0].Rotation.ToQuaternion(); //Update the transforms/visualization by applying the global transformations this.Pelvis.ApplyGlobalJoints(p.Joints); //Update the skeleton visualization if enabled if (this.skelVis != null) { this.skelVis.root.ApplyPostureValues(); } }
/// <summary> /// Performs a blending based on the from posture and the to posture. /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <param name="weight"></param> /// <param name="rootTransform">Specifies whether the root transform is blended as well</param> /// <returns></returns> public static MAvatarPostureValues PerformBlend(IntermediateSkeleton skeleton, MAvatarPostureValues from, MAvatarPostureValues to, float weight, bool rootTransform = true) { MAvatarPosture zero = skeleton.GetAvatarDescription(from.AvatarID).ZeroPosture; skeleton.SetChannelData(from); List <MQuaternion> fromRot = skeleton.GetLocalJointRotations(from.AvatarID); skeleton.SetChannelData(to); List <MQuaternion> toRot = skeleton.GetLocalJointRotations(to.AvatarID); for (int i = 0; i < zero.Joints.Count; i++) { //By default belnd both position and rotation MJointType joint = zero.Joints[i].Type; //Perform a linear interpolation of the position // Does not correspond to intermediate skeleton representation. // result.Joints[i].Position = result.Joints[i].Position.Lerp(to.Joints[i].Position, weight * blendProperty.PositionWeight); //Perform a slerp of the rotation skeleton.SetLocalJointRotation(to.AvatarID, joint, fromRot[i].Slerp(toRot[i], weight)); } return(skeleton.RecomputeCurrentPostureValues(to.AvatarID)); /* * MAvatarPosture result = from.Clone(); * * for (int i = 0; i < result.Joints.Count; i++) * { * //Skip if root transform should be ignored * if (i == 0 && rootTransform) * result.Joints[i].Position = result.Joints[i].Position.Lerp(to.Joints[i].Position, weight); * * //Perform a slerp of the rotation * result.Joints[i].Rotation = result.Joints[i].Rotation.Slerp(to.Joints[i].Rotation, weight); * } * * return result; */ }
/// <summary> /// Returns the current posture of the avatarID in a global MAvatarPosture representation. /// (Each joint contains translation and rotation in global coordinate system) /// </summary> /// <param name="avatarID"></param> /// <returns></returns> public MAvatarPosture GetCurrentGlobalPosture(string avatarID) { MAvatarPosture globalPosture = new MAvatarPosture { AvatarID = avatarID, Joints = new List <MJoint>() }; if (this.hierarchies.ContainsKey(avatarID)) { MAvatarPosture zeroPosture = this.avatarDescriptions[avatarID].ZeroPosture; foreach (MJoint j in zeroPosture.Joints) { Joint refJoint = this.hierarchies[avatarID].GetChild(j.Type); MJoint globalJoint = new MJoint(j.ID, j.Type, refJoint.GetGlobalPosition(), refJoint.GetGlobalRotation()); globalPosture.Joints.Add(globalJoint); } } return(globalPosture); }
public MAvatarPosture RetargetToTarget(MAvatarPostureValues intermediatePostureValues) { string id = intermediatePostureValues.AvatarID; RJoint root = ((RJoint)this.skeleton.GetRoot(id)); root.SetAvatarPostureValues(intermediatePostureValues); MAvatarPosture targetOut = new MAvatarPosture(); targetOut.AvatarID = id; targetOut.Joints = new List <MJoint>(); foreach (MJoint j in this.basePostures[id].Joints) { MJoint outJ = new MJoint(); outJ.ID = j.ID; outJ.Type = j.Type; outJ.Parent = j.Parent; if (outJ.Type != MJointType.Undefined) { RJoint rj = (RJoint)root.GetChild(j.Type); outJ.Position = (rj).RetargetPositionToTarget(); outJ.Rotation = (rj).RetargetRotationToTarget(); } else { outJ.Position = j.Position; outJ.Rotation = j.Rotation; } targetOut.Joints.Add(outJ); } Dictionary <string, string> _children = this.children[id]; for (int i = 0; i < targetOut.Joints.Count; i++) { MJoint outJ = targetOut.Joints[i]; if (outJ.Type == MJointType.Undefined) { bool setRot = false; bool setPos = false; Console.WriteLine("no jointtype " + outJ.ID); if (i == 0) { // find first joint that is mapped foreach (MJoint j in targetOut.Joints) { if (j.Type != MJointType.Undefined) { outJ.Position = new MVector3(j.Position.X, 0, j.Position.Z); //j.Position.X = 0; //j.Position.Z = 0; MVector3 forward = outJ.Rotation.Multiply(new MVector3(0, 0, 1)); forward.Y = 0; forward.Normalize(); MVector3 currentForward = j.Rotation.Multiply(new MVector3(0, 0, 1)); MQuaternion drot = MVector3Extensions.FromToRotation(currentForward, forward); outJ.Rotation = drot.Multiply(j.Rotation); //outJ.Rotation = MQuaternionExtensions.Inverse(drot).Multiply(outJ.Rotation); setPos = true; setRot = true; break; } } } else { /* * This is disabled for now, as it was not working propperly. * * if(_children.ContainsKey(outJ.ID) && _children[outJ.ID] != "") * { * for(int jID = i+1; jID < targetOut.Joints.Count; jID ++) * { * MJoint j = targetOut.Joints[jID]; * if (j.ID == _children[outJ.ID]) * { * * MVector3 srcDir = new MVector3(0, 1, 0);//outJ.Rotation.Multiply(new MVector3(0, 1, 0)).Normalize * MVector3 trgDir = null; * MQuaternion parentRot = null; * if(outJ.Parent != null) * { * for(int pID = i-1; pID > 0; pID--) * { * if(targetOut.Joints[pID].ID == outJ.Parent) * { * if(targetOut.Joints[pID].Type != MJointType.Undefined) * { * parentRot = targetOut.Joints[pID].Rotation; * trgDir = MQuaternionExtensions.Inverse(parentRot).Multiply(j.Position.Subtract(outJ.Position).Normalize()); * } * } * } * } * if(trgDir != null) * { * MQuaternion rot = MVector3Extensions.FromToRotation(srcDir, trgDir); * outJ.Rotation = parentRot.Multiply(rot); * outJ.Position = null; * setRot = true; * break; * * } * * * } * } * }*/ } if (!setRot) { outJ.Rotation = null; } if (!setPos) { outJ.Position = null; } } } return(targetOut); }
public void ScaleSkeleton(MAvatarPosture globalTarget, Dictionary <MJointType, string> joint_map) { List <MJointType> spine = new List <MJointType>() { MJointType.S1L5Joint, MJointType.T12L1Joint, MJointType.T1T2Joint, MJointType.C4C5Joint, MJointType.HeadJoint }; if (spine.Contains(this.GetMJoint().Type)) { //float shoulder_height = getJointPosition(HumanBodyBones.LeftUpperArm, anim).y; double shoulder_height = getJointPosition(globalTarget, joint_map[MJointType.HeadJoint]).Y; double hip_height = getJointPosition(globalTarget, joint_map[MJointType.PelvisCentre]).Y; double spine_length = shoulder_height - hip_height; ((RJoint)this.parentJoint).boneLength = (this.GetOffsetPositions()).Multiply(spine_length).Magnitude(); this.GetOffsetPositions().X = 0; this.GetOffsetPositions().Y = 1.0; this.GetOffsetPositions().Z = 0; } if (this.joint.Type == MJointType.Root) { //MVector3 rootPos = getJointPosition(globalTarget, joint_map[MJointType.Root]); //this.SetOffsets(rootPos); } else if (this.joint.Type == MJointType.PelvisCentre) { MVector3 hips = getJointPosition(globalTarget, joint_map[MJointType.PelvisCentre]).Clone(); MVector3 shoulder = getJointPosition(globalTarget, joint_map[MJointType.LeftShoulder]); MVector3 leftupleg = getJointPosition(globalTarget, joint_map[MJointType.LeftHip]); // find the average z axis position of shoulders and hips to find initial position of hip hips.Z = (shoulder.Z + leftupleg.Z) / 2; // raise hip to the hight of the target avatars hip height. hips.Y = leftupleg.Y; MVector3 root = new MVector3(hips.X, 0, hips.Z); ((RJoint)this.parentJoint).SetOffsets(root); hips.X = 0; hips.Z = 0; this.SetOffsets(hips); } else { double factor = 0.0d; if (this.parentJoint.children.Count == 3 && this.parentJoint.children[0] != this) { // If there are two children (e.g. pelvis / upper spine), take the half distance between both children factor = GetJointDistance(globalTarget, joint_map[this.parentJoint.children[1].GetMJoint().Type], joint_map[this.parentJoint.children[2].GetMJoint().Type]) / 2.0d; } else { // If there is one child, take the parent bone length to scale target position factor = ((RJoint)this.parentJoint).boneLength; } // scale offset to scale the skeleton to match bone lengths. this.SetOffsets(this.GetOffsetPositions().Multiply(factor)); // handle special cases for shoulders and hands string jointID = this.GetMJoint().ID; if (jointID.Contains("Shoulder")) { // in case of shoulders, they have to be raised in up direction. double shoulder_height = getJointPosition(globalTarget, joint_map[this.GetMJoint().Type]).Y; double current_Pos = this.GetShoulderHeight(); shoulder_height = shoulder_height - current_Pos; this.GetOffsetPositions().Y = shoulder_height; } } if (this.children.Count > 0 && this.children[0].GetMJoint().ID.Contains("Tip")) { // Finger Tips MVector3 offsetVector = this.children[0].GetOffsetPositions(); this.boneLength = offsetVector.Magnitude(); } else { // if this is not the last joint in a sequence, scale depending on distance to child human bone if (joint_map.ContainsKey(this.children[0].GetMJoint().Type) && joint_map.ContainsKey(this.GetMJoint().Type)) { this.boneLength = GetJointDistance(globalTarget, joint_map[this.GetMJoint().Type], joint_map[this.children[0].GetMJoint().Type]); } else { this.boneLength = 0.1; } } // recurse foreach (Joint child in this.children) { if (!child.GetMJoint().ID.Contains("Tip")) { ((RJoint)(child)).ScaleSkeleton(globalTarget, joint_map); } } if (this.GetMJoint().ID.Contains("Wrist")) { MVector3 wristPos = this.GetGlobalPosition();//getJointPosition(globalTarget, joint_map[this.GetMJoint().Type]); MTransform Twrist = new MTransform("tmp", this.GetGlobalPosition(), this.GetGlobalRotation()); Joint middle = this.children[0]; Joint index = this.children[1]; Joint ring = this.children[2]; Joint little = this.children[3]; Joint thumb = this.children[4]; double middle_shift = 0.0; if (joint_map.ContainsKey(middle.GetMJoint().Type)) { MVector3 MiddlePos = ((RJoint)middle).GetFingerPosition(globalTarget, joint_map, 0); middle_shift = MiddlePos.Z; MiddlePos.Z = 0; ((RJoint)this.children[0]).SetOffsets(MiddlePos); } else { ((RJoint)this.children[0]).SetOffsets(new MVector3(0, 0.1, 0)); } if (joint_map.ContainsKey(index.GetMJoint().Type)) { MVector3 IndexPos = ((RJoint)index).GetFingerPosition(globalTarget, joint_map, middle_shift); ((RJoint)this.children[1]).SetOffsets(IndexPos); } else { ((RJoint)this.children[1]).SetOffsets(new MVector3(0, 0.1, 0.02)); } if (joint_map.ContainsKey(ring.GetMJoint().Type)) { MVector3 RingPos = ((RJoint)ring).GetFingerPosition(globalTarget, joint_map, middle_shift); ((RJoint)this.children[2]).SetOffsets(RingPos); } else { ((RJoint)this.children[2]).SetOffsets(new MVector3(0, 0.1, -0.02)); } if (joint_map.ContainsKey(little.GetMJoint().Type)) { MVector3 LittlePos = ((RJoint)little).GetFingerPosition(globalTarget, joint_map, middle_shift); ((RJoint)this.children[3]).SetOffsets(LittlePos); } else { ((RJoint)this.children[3]).SetOffsets(new MVector3(0, 0.1, -0.04)); } if (joint_map.ContainsKey(thumb.GetMJoint().Type)) { MVector3 ThumbPos = ((RJoint)thumb).GetFingerPosition(globalTarget, joint_map, middle_shift); ((RJoint)this.children[4]).SetOffsets(ThumbPos); } else { ((RJoint)this.children[4]).SetOffsets(new MVector3(0, 0.02, 0.02)); } } }
private static double GetJointDistance(MAvatarPosture globalTarget, string joint1, string joint2) { return(getJointPosition(globalTarget, joint1).Subtract(getJointPosition(globalTarget, joint2)).Magnitude()); }