diff --git a/Assets/UniGLTF/Runtime/UniHumanoid/SkeletonMeshUtility.cs b/Assets/UniGLTF/Runtime/UniHumanoid/SkeletonMeshUtility.cs index 3ad55a440..b99febc6e 100644 --- a/Assets/UniGLTF/Runtime/UniHumanoid/SkeletonMeshUtility.cs +++ b/Assets/UniGLTF/Runtime/UniHumanoid/SkeletonMeshUtility.cs @@ -8,75 +8,74 @@ namespace UniHumanoid { public static class SkeletonMeshUtility { + struct TSRBox + { + public Vector3 T; + public Vector3 S; + public Quaternion R; + + public Matrix4x4 ToMatrix() + { + return Matrix4x4.Rotate(R) * Matrix4x4.Scale(S) * Matrix4x4.Translate(T); + } + } + class MeshBuilder { List m_positions = new List(); List m_indices = new List(); List m_boneWeights = new List(); - public void AddBone(Vector3 head, Vector3 tail, int boneIndex, float xWidth, float zWidth) + public void AddBone(Vector3 head, Vector3 tail, int boneIndex, float width, float height, Vector3 xAxis) { - var dir = (tail - head).normalized; - Vector3 xaxis; - Vector3 zaxis; - if (Vector3.Dot(dir, Vector3.forward) >= 1.0f - float.Epsilon) + var yAxis = (tail - head).normalized; + var zAxis = Vector3.Cross(xAxis, yAxis); + xAxis = Vector3.Cross(yAxis, zAxis); + + AddBox(boneIndex, new TSRBox { - xaxis = Vector3.right; - zaxis = Vector3.down; - } - else - { - xaxis = Vector3.Cross(dir, Vector3.forward).normalized; - zaxis = Vector3.forward; - } - AddBox((head+tail)*0.5f, - xaxis*xWidth, - (tail-head)*0.5f, - zaxis*zWidth, - boneIndex); + T = new Vector3(0, 0.5f, 0), + S = new Vector3(width, (tail - head).magnitude, height), + R = new Matrix4x4( + xAxis, yAxis, zAxis, new Vector4(0, 0, 0, 1) + ).rotation, + }); } - void AddBox(Vector3 center, Vector3 xaxis, Vector3 yaxis, Vector3 zaxis, int boneIndex) + // rotation * scale * beforeTranslation + void AddBox(int boneIndex, TSRBox box) { - AddQuad( - center - yaxis - xaxis - zaxis, - center - yaxis + xaxis - zaxis, - center - yaxis + xaxis + zaxis, - center - yaxis - xaxis + zaxis, - boneIndex); - AddQuad( - center + yaxis - xaxis - zaxis, - center + yaxis + xaxis - zaxis, - center + yaxis + xaxis + zaxis, - center + yaxis - xaxis + zaxis, - boneIndex, true); - AddQuad( - center - xaxis - yaxis - zaxis, - center - xaxis + yaxis - zaxis, - center - xaxis + yaxis + zaxis, - center - xaxis - yaxis + zaxis, - boneIndex, true); - AddQuad( - center + xaxis - yaxis - zaxis, - center + xaxis + yaxis - zaxis, - center + xaxis + yaxis + zaxis, - center + xaxis - yaxis + zaxis, - boneIndex); - AddQuad( - center - zaxis - xaxis - yaxis, - center - zaxis + xaxis - yaxis, - center - zaxis + xaxis + yaxis, - center - zaxis - xaxis + yaxis, - boneIndex, true); - AddQuad( - center + zaxis - xaxis - yaxis, - center + zaxis + xaxis - yaxis, - center + zaxis + xaxis + yaxis, - center + zaxis - xaxis + yaxis, - boneIndex); + var m = box.ToMatrix(); + + // v6+---+v7 + // v2/| v3| + // +---+ | + // | +v5-+v4 + // |/ |/ + // +---+ + // v1 v0 + var s = 0.5f; + var cube = new Vector3[] + { + m.MultiplyPoint(new Vector3(+s, -s, -s)), + m.MultiplyPoint(new Vector3(-s, -s, -s)), + m.MultiplyPoint(new Vector3(-s, +s, -s)), + m.MultiplyPoint(new Vector3(+s, +s, -s)), + m.MultiplyPoint(new Vector3(+s, -s, +s)), + m.MultiplyPoint(new Vector3(-s, -s, +s)), + m.MultiplyPoint(new Vector3(-s, +s, +s)), + m.MultiplyPoint(new Vector3(+s, +s, +s)), + }; + + AddQuad(boneIndex, cube[0], cube[1], cube[2], cube[3]); + AddQuad(boneIndex, cube[1], cube[5], cube[6], cube[2]); + AddQuad(boneIndex, cube[5], cube[4], cube[7], cube[6]); + AddQuad(boneIndex, cube[4], cube[0], cube[3], cube[7]); + AddQuad(boneIndex, cube[3], cube[2], cube[6], cube[7]); + AddQuad(boneIndex, cube[4], cube[5], cube[1], cube[0]); } - void AddQuad(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3, int boneIndex, bool reverse=false) + void AddQuad(int boneIndex, Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3) { var i = m_positions.Count; m_positions.Add(v0); @@ -86,25 +85,14 @@ namespace UniHumanoid var bw = new BoneWeight { - boneIndex0=boneIndex, - weight0=1.0f, + boneIndex0 = boneIndex, + weight0 = 1.0f, }; m_boneWeights.Add(bw); m_boneWeights.Add(bw); m_boneWeights.Add(bw); m_boneWeights.Add(bw); - if (reverse) - { - m_indices.Add(i + 3); - m_indices.Add(i + 2); - m_indices.Add(i + 1); - - m_indices.Add(i + 1); - m_indices.Add(i); - m_indices.Add(i + 3); - } - else { m_indices.Add(i); m_indices.Add(i + 1); @@ -133,55 +121,59 @@ namespace UniHumanoid public HumanBodyBones Head; public HumanBodyBones Tail; public Vector3 TailOffset; - public float XWidth; - public float ZWidth; + public float Width; + public float Height; + public Vector3 XAxis; - public BoneHeadTail(HumanBodyBones head, HumanBodyBones tail, float xWidth = 0.05f, float zWidth = 0.05f) + public BoneHeadTail(HumanBodyBones head, HumanBodyBones tail, Vector3 xAxis, float width = 0.05f, float height = 0.05f) { Head = head; Tail = tail; TailOffset = Vector3.zero; - XWidth = xWidth; - ZWidth = zWidth; + XAxis = xAxis; + Width = width; + Height = height; } - public BoneHeadTail(HumanBodyBones head, Vector3 tailOffset, float xWidth = 0.05f, float zWidth = 0.05f) + public BoneHeadTail(HumanBodyBones head, Vector3 tailOffset, Vector3 xAxis, float width = 0.05f, float height = 0.05f) { Head = head; Tail = HumanBodyBones.LastBone; TailOffset = tailOffset; - XWidth = xWidth; - ZWidth = zWidth; + XAxis = xAxis; + Width = width; + Height = height; } } static BoneHeadTail[] Bones = new BoneHeadTail[] { - new BoneHeadTail(HumanBodyBones.Hips, HumanBodyBones.Spine, 0.1f, 0.06f), - new BoneHeadTail(HumanBodyBones.Spine, HumanBodyBones.Chest), - new BoneHeadTail(HumanBodyBones.Chest, HumanBodyBones.Neck, 0.1f, 0.06f), - new BoneHeadTail(HumanBodyBones.Neck, HumanBodyBones.Head, 0.03f, 0.03f), - new BoneHeadTail(HumanBodyBones.Head, new Vector3(0, 0.1f, 0), 0.1f, 0.1f), + new BoneHeadTail(HumanBodyBones.Hips, HumanBodyBones.Spine, Vector3.right, 0.2f, 0.12f), + new BoneHeadTail(HumanBodyBones.Spine, HumanBodyBones.Chest, Vector3.right), + new BoneHeadTail(HumanBodyBones.Chest, HumanBodyBones.Neck, Vector3.right, 0.2f, 0.12f), + new BoneHeadTail(HumanBodyBones.Neck, HumanBodyBones.Head, Vector3.right, 0.06f, 0.06f), + new BoneHeadTail(HumanBodyBones.Head, new Vector3(0, 0.1f, 0), Vector3.right, 0.2f, 0.2f), + new BoneHeadTail(HumanBodyBones.Head, new Vector3(0, 0, 0.1f), Vector3.right, 0.2f, 0.2f), - new BoneHeadTail(HumanBodyBones.LeftShoulder, HumanBodyBones.LeftUpperArm), - new BoneHeadTail(HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm), - new BoneHeadTail(HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand), - new BoneHeadTail(HumanBodyBones.LeftHand, new Vector3(-0.1f, 0, 0)), + new BoneHeadTail(HumanBodyBones.LeftShoulder, HumanBodyBones.LeftUpperArm, Vector3.forward), + new BoneHeadTail(HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm, Vector3.forward), + new BoneHeadTail(HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand, Vector3.forward), + new BoneHeadTail(HumanBodyBones.LeftHand, new Vector3(-0.1f, 0, 0), Vector3.forward, 0.1f, 0.02f), - new BoneHeadTail(HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg), - new BoneHeadTail(HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot), - new BoneHeadTail(HumanBodyBones.LeftFoot, HumanBodyBones.LeftToes), - new BoneHeadTail(HumanBodyBones.LeftToes, new Vector3(0, 0, 0.1f)), + new BoneHeadTail(HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg, Vector3.left), + new BoneHeadTail(HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot, Vector3.left), + new BoneHeadTail(HumanBodyBones.LeftFoot, HumanBodyBones.LeftToes, Vector3.left), + new BoneHeadTail(HumanBodyBones.LeftToes, new Vector3(0, 0, 0.03f), Vector3.left), - new BoneHeadTail(HumanBodyBones.RightShoulder, HumanBodyBones.RightUpperArm), - new BoneHeadTail(HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm), - new BoneHeadTail(HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand), - new BoneHeadTail(HumanBodyBones.RightHand, new Vector3(0.1f, 0, 0)), + new BoneHeadTail(HumanBodyBones.RightShoulder, HumanBodyBones.RightUpperArm, Vector3.back), + new BoneHeadTail(HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm, Vector3.back), + new BoneHeadTail(HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand, Vector3.back), + new BoneHeadTail(HumanBodyBones.RightHand, new Vector3(0.1f, 0, 0), Vector3.back, 0.1f, 0.02f), - new BoneHeadTail(HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg), - new BoneHeadTail(HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot), - new BoneHeadTail(HumanBodyBones.RightFoot, HumanBodyBones.RightToes), - new BoneHeadTail(HumanBodyBones.RightToes, new Vector3(0, 0, 0.1f)), + new BoneHeadTail(HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg, Vector3.left), + new BoneHeadTail(HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot, Vector3.left), + new BoneHeadTail(HumanBodyBones.RightFoot, HumanBodyBones.RightToes, Vector3.left), + new BoneHeadTail(HumanBodyBones.RightToes, new Vector3(0, 0, 0.03f), Vector3.left), }; public static SkinnedMeshRenderer CreateRenderer(Animator animator) @@ -189,24 +181,24 @@ namespace UniHumanoid var bones = animator.transform.Traverse().ToList(); var builder = new MeshBuilder(); - foreach(var headTail in Bones) + foreach (var headTail in Bones) { var head = animator.GetBoneTransform(headTail.Head); - if (head!=null) + if (head != null) { Transform tail = null; - if(headTail.Tail!= HumanBodyBones.LastBone) + if (headTail.Tail != HumanBodyBones.LastBone) { tail = animator.GetBoneTransform(headTail.Tail); } if (tail != null) { - builder.AddBone(head.position, tail.position, bones.IndexOf(head), headTail.XWidth, headTail.ZWidth); + builder.AddBone(head.position, tail.position, bones.IndexOf(head), headTail.Width, headTail.Height, headTail.XAxis); } else { - builder.AddBone(head.position, head.position + headTail.TailOffset, bones.IndexOf(head), headTail.XWidth, headTail.ZWidth); + builder.AddBone(head.position, head.position + headTail.TailOffset, bones.IndexOf(head), headTail.Width, headTail.Height, headTail.XAxis); } } else @@ -218,7 +210,7 @@ namespace UniHumanoid var mesh = builder.CreateMesh(); mesh.name = "box-man"; mesh.bindposes = bones.Select(x => - x.worldToLocalMatrix * animator.transform.localToWorldMatrix).ToArray(); + Matrix4x4.identity).ToArray(); var renderer = animator.gameObject.AddComponent(); renderer.bones = bones.ToArray(); renderer.rootBone = animator.GetBoneTransform(HumanBodyBones.Hips);