// Align bone with direction. private void AlignWithAxis( BoneTransformation bodyPart, Vector3 start, Vector3 end, string axis) { Vector3 axisAlign = Vector3.zero; if (axis == "x") { axisAlign = bodyPart.bodyPart.right; } else if (axis == "-x") { axisAlign = -bodyPart.bodyPart.right; } else if (axis == "y") { axisAlign = -bodyPart.bodyPart.up; } else if (axis == "-y") { axisAlign = bodyPart.bodyPart.up; } // Allign bone with appropriate direction determined by joints. Vector3 v = end - start; var q = UnityEngine.Quaternion.FromToRotation(axisAlign, v); bodyPart.bodyPart.rotation = q * bodyPart.bodyPart.rotation; }
// Finds scale factor for given bone/part of body. private float FindBoneScaleFactor(BodyParts b) { if (bodyPartCache.ContainsKey(b)) { BoneTransformation bodyPart = bodyPartCache[b].Find(item => item.action == BoneTransformation.Transformations.ScaleBetweenJoints || item.action == BoneTransformation.Transformations.ScaleBetweenJointAndMiddleJoints); if (bodyPart != null) { JointId fromJoint = bodyPart.joints[0]; JointId toJoint = bodyPart.joints[1]; Vector3 start = jointCache[fromJoint].transformation.position; Vector3 end = jointCache[toJoint].transformation.position; string axis = bodyPart.aligningAxis; float size = bodyPart.originalSize; MeshRenderer renderer = bodyPart.bodyPart.gameObject.GetComponent <MeshRenderer>(); if (renderer != null) { float distance = Vector3.Distance(end, start); float scale = distance / size; return(scale); } } } return(0.0f); }
// Move/scale/align body parts. // Move/scale/align body parts. private void MoveBones() { foreach (KeyValuePair <BodyParts, List <BoneTransformation> > entry in bodyPartCache) { foreach (BoneTransformation transformation in entry.Value) { BoneTransformation bodyPart = transformation; if (bodyPart.action == BoneTransformation.Transformations.AttachToJoint) { AttachToJointTransformation(entry.Key, bodyPart); } else if (bodyPart.action == BoneTransformation.Transformations.AttachToPositionJointAndMiddleJoints) { AttachToPositionJointAndMiddleJointsTransformation(entry.Key, bodyPart); } else if (bodyPart.action == BoneTransformation.Transformations.ScaleBetweenJoints) { ScaleBetweenJointsTransformation(bodyPart); } else if (bodyPart.action == BoneTransformation.Transformations.ScaleBetweenJointAndMiddleJoints) { ScaleBetweenJointAndMiddleJointsTransformation(bodyPart); } else if (bodyPart.action == BoneTransformation.Transformations.AlignJointToJoint) { AlignTwoJointsTransformation(bodyPart); } else if (bodyPart.action == BoneTransformation.Transformations.AlignJointToMiddleJoints) { AlignJointToMiddleJointsTransformation(bodyPart); } } } }
// Move object relativelly to attached. private void AttachToJointTransformation( BodyParts bodyPartKey, BoneTransformation bodyPart) { JointId attachedToJoint = bodyPart.joints[0]; Vector3 delta = initialBodyPartPositions[bodyPartKey] - initialJointPositions[attachedToJoint]; bodyPart.bodyPart.position = jointCache[attachedToJoint].transformation.position + delta; }
// TODO refactor tobe one with AlignWithAxis. // Align object by given axis with another objects. private void AlignTransformation(BoneTransformation bodyPart) { JointId fromJoint = bodyPart.joints[0]; JointId toJoint = bodyPart.joints[1]; Vector3 start = jointCache[fromJoint].transformation.position; Vector3 end = jointCache[toJoint].transformation.position; string axis = bodyPart.aligningAxis; AlignWithAxis(bodyPart, start, end, axis); }
private void AlignJointToMiddleJointsTransformation(BoneTransformation bodyPart) { JointId fromJoint = bodyPart.joints[0]; JointId middleJoint1 = bodyPart.joints[1]; JointId middleJoint2 = bodyPart.joints[2]; Vector3 start = jointCache[fromJoint].transformation.position; Vector3 end = (jointCache[middleJoint1].transformation.position + jointCache[middleJoint2].transformation.position) / 2; string axis = bodyPart.aligningAxis; AlignWithAxis(bodyPart, start, end, axis); }
// Rotate and scale gameobject by x axis between positions. private void ScaleBetweenJointAndMiddleJointsTransformation(BoneTransformation bodyPart) { JointId fromJoint = bodyPart.joints[0]; JointId middleJoint1 = bodyPart.joints[1]; JointId middleJoint2 = bodyPart.joints[2]; Vector3 start = jointCache[fromJoint].transformation.position; Vector3 end = (jointCache[middleJoint1].transformation.position + jointCache[middleJoint2].transformation.position) / 2; string axis = bodyPart.aligningAxis; float size = bodyPart.originalSize; ScaleBone(bodyPart, start, end, axis, size); }
private void AttachToPositionJointAndMiddleJointsTransformation( BodyParts bodyPartKey, BoneTransformation bodyPart) { JointId singleJoint = bodyPart.joints[0]; JointId middleJoint1 = bodyPart.joints[1]; JointId middleJoint2 = bodyPart.joints[2]; Vector3 singleJointPosition = jointCache[singleJoint].transformation.position; Vector3 middleJointPosition = (jointCache[middleJoint1].transformation.position + jointCache[middleJoint2].transformation.position) / 2.0f; bodyPart.bodyPart.position = (singleJointPosition + middleJointPosition) / 2.0f; }
// Rotate and scale gameobject by x axis between positions. private void ScaleTransformation(BoneTransformation bodyPart) { JointId fromJoint = bodyPart.joints[0]; JointId toJoint = bodyPart.joints[1]; Vector3 start = jointCache[fromJoint].transformation.position; Vector3 end = jointCache[toJoint].transformation.position; string axis = bodyPart.aligningAxis; float size = bodyPart.originalSize; SetBoneToPosition(bodyPart, start, end); AlignWithAxis(bodyPart, start, end, axis); ScaleBone(bodyPart, start, end, axis, size); }
// Scale bone to reflect new size between joints. private void ScaleBone( BoneTransformation bodyPart, Vector3 start, Vector3 end, string axis, float size) { MeshRenderer renderer = bodyPart.bodyPart.gameObject.GetComponent <MeshRenderer>(); if (renderer != null) { float distance = Vector3.Distance(end, start); float scale = distance / size; float scaleX = 1.0f; float scaleY = 1.0f; float scaleZ = 1.0f; if (axis.Contains("x")) { scaleX = scale; } if (axis.Contains("y")) { scaleY = scale; } if (axis.Contains("z")) { scaleZ = scale; } Vector3 origScale = bodyPart.originalLocalScale; bodyPart.bodyPart.localScale = new Vector3( origScale.x * scaleX, origScale.y * scaleY, origScale.z * scaleZ); } }
// Set position of bone to the middle of joints. private void SetBoneToPosition(BoneTransformation bodyPart, Vector3 start, Vector3 end) { bodyPart.bodyPart.position = (start + end) / 2; }