protected override GPUBoneWeight[] BuildWeights() { CheckInit(); var vertices = mesh.vertices; var weights = new GPUBoneWeight[mesh.vertexCount]; for (int i = 0, n = vertices.Length; i < n; i++) { var p = vertices[i]; var u = 1f + followingBoneCount - ((p.y - min.y) / unitLength); if (u > 0f) { var lu = Mathf.FloorToInt(u); var cu = Mathf.CeilToInt(u); var t = Mathf.Clamp01(u - lu); weights[i].boneIndex0 = (uint)lu; weights[i].weight0 = 1f - t; weights[i].boneIndex1 = (uint)cu; weights[i].weight1 = t; } else { weights[i].boneIndex0 = 0; weights[i].weight0 = 1f; weights[i].boneIndex1 = 0; weights[i].weight1 = 0f; } } return(weights); }
protected override GPUBoneWeight[] BuildWeights() { var bounds = mesh.bounds; Vector3 min = bounds.min, max = bounds.max; // To avoid bind a head bone to vertices, set followingBoneCount to boneCount - 2. var followingBoneCount = boneCount - 2; var unit = (max.y - min.y) / followingBoneCount; var vertices = mesh.vertices; var weights = new GPUBoneWeight[mesh.vertexCount]; for (int i = 0, n = vertices.Length; i < n; i++) { var p = vertices[i]; // 1f offset avoids binding a head bone. var u = 1f + followingBoneCount - ((p.y - min.y) / unit); if (u > 0f) { var lu = Mathf.FloorToInt(u); var cu = Mathf.CeilToInt(u); var t = Mathf.Clamp01(u - lu); weights[i].boneIndex0 = (uint)lu; weights[i].weight0 = 1f - t; weights[i].boneIndex1 = (uint)cu; weights[i].weight1 = t; } else { // tip case (u <= 0f) weights[i].boneIndex0 = 0; weights[i].weight0 = 1f; weights[i].boneIndex1 = 0; weights[i].weight1 = 0f; } } return(weights); }
void Start() { renderer = GetComponent <Renderer>(); material = renderer.material; var filter = GetComponent <MeshFilter>(); var mesh = filter.sharedMesh; var bounds = mesh.bounds; var center = bounds.center; Vector3 min = bounds.min, max = bounds.max; var unit = (max.y - min.y) / (division - 1); var vertices = mesh.vertices; var weights = new GPUBoneWeight[mesh.vertexCount]; for (int i = 0, n = vertices.Length; i < n; i++) { var p = vertices[i]; var u = (division - 1) - (p.y - min.y) / unit; if (u > 0f) { var lu = Mathf.FloorToInt(u); var cu = Mathf.CeilToInt(u); var t = u - lu; weights[i].boneIndex0 = (uint)lu; weights[i].weight0 = 1f - t; weights[i].boneIndex1 = (uint)cu; weights[i].weight1 = t; } else { // tip case (u <= 0f) weights[i].boneIndex0 = 0; weights[i].weight0 = 1; weights[i].boneIndex1 = 0; weights[i].weight1 = 0; } } weightBuffer = new ComputeBuffer(mesh.vertexCount, Marshal.SizeOf(typeof(GPUBoneWeight))); weightBuffer.SetData(weights); boneBuffer = new ComputeBuffer(division, Marshal.SizeOf(typeof(GPUBone))); for (int i = 0; i < division; i++) { var bone = new GameObject("Bone" + i); bones.Add(bone.transform); if (i == 0) { // root bone bone.transform.SetParent(transform, false); bone.transform.localPosition = new Vector3(center.x, max.y, center.z); } else { bone.transform.SetParent(bones[i - 1].transform, false); bone.transform.localPosition = new Vector3(0, -unit, 0); } // keep local and global initial transform locals.Add(new TRS(bone.transform.localPosition, bone.transform.localRotation, bone.transform.localScale)); globals.Add(new TRS(bone.transform)); } material.SetBuffer(kWeightsKey, weightBuffer); material.SetBuffer(kBonesKey, boneBuffer); material.SetInt(kBonesCountKey, division); material.SetFloat(kBonesCountInvKey, 1f / division); // bind initial matrix for bones material.SetMatrix(kBindMatrixKey, transform.localToWorldMatrix); material.SetMatrix(kBindMatrixInvKey, transform.worldToLocalMatrix); }