/// <summary> /// Compute joint poses in model space given the skeleton hierarchy and /// an animation pose (local space poses) /// </summary> /// <param name="animPose">animation pose with local space transforms</param> /// <param name="poseGlobal">output transformations in model space</param> public void GetPoseInGlobalSpace(AnimationPose animPose, ref Matrix4x4[] globalPose) { // KEEP THIS check validity of the arguments int jointCount = m_aJoint.Length; if (animPose.m_aLocalPose.Length != jointCount) { Debug.LogError("[Skeleton] the AnimationPose and Skeleton don't match"); } if (globalPose.Length != jointCount) { globalPose = new Matrix4x4[jointCount]; } // TODO exercise 5.1 // You should // 1. iterate through all the joints, // 2. use the hierarchy of joints to retrieve the local transformation of each joint in the animPose, // 3. concatenate the local transformations until you reach the root joint of the skeleton (m_iParent == 255) // 4. store the resultint matrix on poseGlobal, at the same index as the joint // REPLACE with the correct code (slide 31) for (int i = 0; i < jointCount; i++) { globalPose[i] = animPose.m_aLocalPose[i].Matrix(); } }
public void Init() { // Load character mesh (saved as a serialized data structure) string meshLoadPath = Application.dataPath + "/" + meshFile; string meshString = System.IO.File.ReadAllText(meshLoadPath); modelMesh = JsonUtility.FromJson <TriangleMesh>(meshString); // Setup this game object to show the mesh, use control weights as colors weightMeshRenderer = gameObject.GetComponent <MeshRenderer>(); if (weightMeshRenderer == null) { weightMeshRenderer = gameObject.AddComponent <MeshRenderer>(); } weightMeshFilter = gameObject.GetComponent <MeshFilter>(); if (weightMeshFilter == null) { weightMeshFilter = gameObject.AddComponent <MeshFilter>(); } // Set the character mesh weightMeshFilter.sharedMesh = modelMesh.GetUnityMesh(); // Assumes that there is a material called WeightsMaterial in a Resources folder // a custom material is used so that we can render a mesh using the colors we set Material weightsMat = Resources.Load("WeightsMaterial", typeof(Material)) as Material; weightMeshRenderer.sharedMaterial = weightsMat; // Load skeleton from file (saved as a serialized data structure) string skelLoadPath = Application.dataPath + "/" + skeletonFile; string skelString = System.IO.File.ReadAllText(skelLoadPath); skeleton = JsonUtility.FromJson <Skeleton>(skelString); // Load pose from file (saved as a serialized data structure) string poseLoadPath = Application.dataPath + "/" + poseFile; string poseString = System.IO.File.ReadAllText(poseLoadPath); currentPose = JsonUtility.FromJson <AnimationPose>(poseString); // Compute the pose of all joints in model space skeleton.GetPoseInGlobalSpace(currentPose, ref modelSpacePose); // Compute the pose of the vertices of the mesh UpdateMeshVertices(modelMesh, modelSpacePose, skeleton, weightMeshFilter.sharedMesh); initialized = true; }
/// <summary> /// Compute joint poses in model space given the skeleton hierarchy and /// an animation pose (local space poses) /// </summary> /// <param name="animPose">animation pose with local space transforms</param> /// <param name="poseGlobal">output transformations in model space</param> public void GetPoseInGlobalSpace(AnimationPose animPose, ref Matrix4x4[] globalPose) { // KEEP THIS check validity of the arguments int jointCount = m_aJoint.Length; if (animPose.m_aLocalPose.Length != jointCount) { Debug.LogError("[Skeleton] the AnimationPose and Skeleton don't match"); } if (globalPose.Length != jointCount) { globalPose = new Matrix4x4[jointCount]; } // TODO exercise 5.1 // You should // 1. iterate through all the joints, // 2. use the hierarchy of joints to retrieve the local transformation of each joint in the animPose, // 3. concatenate the local transformations until you reach the root joint of the skeleton (m_iParent == 255) // 4. store the resultint matrix on poseGlobal, at the same index as the joint // (slide 31) for (int i = 0; i < jointCount; i++) { Matrix4x4 P = animPose.m_aLocalPose[i].Matrix(); byte parentId = m_aJoint[i].m_iParent; // go up the hierarchy until we reach the root while (true) { // check if it has reached the root of our hierarchy, the joint with an invalid parentID( == 255) if (parentId == 255) { break; } P = animPose.m_aLocalPose[parentId].Matrix() * P; parentId = m_aJoint[parentId].m_iParent; } globalPose[i] = P; } }
void Init() { if (animationPoses != null) { return; } // create the arm skeleton SkeletonJoint shoulder = new SkeletonJoint() { m_invBindPose = Matrix4x4.identity, m_name = "shoulder", m_iParent = 255 }; SkeletonJoint elbow = new SkeletonJoint() { m_invBindPose = Matrix4x4.identity, m_name = "elbow", m_iParent = 0 }; SkeletonJoint wrist = new SkeletonJoint() { m_invBindPose = Matrix4x4.identity, m_name = "wrist", m_iParent = 1 }; SkeletonJoint[] joints = new SkeletonJoint[3] { shoulder, elbow, wrist }; arm = new Skeleton() { m_aJoint = joints }; // create animation frame 1 (index 0) JointPose shoulder1 = new JointPose { m_rot = Quaternion.AngleAxis(0.0f, Vector3.forward), m_pos = new Vector3(0.0f, 0.0f, 0.0f), m_scale = 1.0f }; JointPose elbow1 = new JointPose { m_rot = Quaternion.AngleAxis(0.0f, Vector3.forward), m_pos = new Vector3(1.0f, 0.0f, 0.0f), m_scale = 1.0f }; JointPose wrist1 = new JointPose { m_rot = Quaternion.AngleAxis(0.0f, Vector3.forward), m_pos = new Vector3(1.0f, 0.0f, 0.0f), m_scale = 1.0f }; JointPose[] poses1 = new JointPose[3] { shoulder1, elbow1, wrist1 }; AnimationPose frame1 = new AnimationPose { m_aLocalPose = poses1 }; // create animation frame 2 (index 1) JointPose shoulder2 = new JointPose { m_rot = Quaternion.AngleAxis(60.0f, Vector3.forward), m_pos = new Vector3(0.0f, 0.0f, 0.0f), m_scale = 1.0f }; JointPose elbow2 = new JointPose { m_rot = Quaternion.AngleAxis(-75.0f, Vector3.forward), m_pos = new Vector3(1.0f, 0.0f, 0.0f), m_scale = 1.0f }; JointPose wrist2 = new JointPose { m_rot = Quaternion.AngleAxis(40.0f, Vector3.forward), m_pos = new Vector3(1.0f, 0.0f, 0.0f), m_scale = 1.0f }; JointPose[] poses2 = new JointPose[3] { shoulder2, elbow2, wrist2 }; AnimationPose frame2 = new AnimationPose { m_aLocalPose = poses2 }; // create animation frame 3 (index 2) JointPose shoulder3 = new JointPose { m_rot = Quaternion.AngleAxis(30.0f, Vector3.forward), m_pos = new Vector3(1.0f, 0.0f, 0.0f), m_scale = 1.0f }; JointPose elbow3 = new JointPose { m_rot = Quaternion.AngleAxis(-25.0f, Vector3.forward), m_pos = new Vector3(1.0f, 0.0f, 0.0f), m_scale = 1.0f }; JointPose wrist3 = new JointPose { m_rot = Quaternion.AngleAxis(10.0f, Vector3.forward), m_pos = new Vector3(1.0f, 0.0f, 0.0f), m_scale = 1.0f }; JointPose[] poses3 = new JointPose[3] { shoulder3, elbow3, wrist3 }; AnimationPose frame3 = new AnimationPose { m_aLocalPose = poses3 }; // array of animation poses, frame 1 at index 0 and frame 2 at index 1 animationPoses = new AnimationPose[3] { frame1, frame2, frame3 }; // initialize current pose to pose 1 JointPose[] poses = new JointPose[3] { shoulder1, wrist1, wrist1 }; currentPose = new AnimationPose { m_aLocalPose = poses }; }