Example #1
0
        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);
        }
Example #2
0
        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);
        }