< Summary

Class:GPUSkinning.SimpleGPUSkinning
Assembly:RenderUtils
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Rendering/Utils/GPUSkinning/SimpleGPUSkinning.cs
Covered lines:32
Uncovered lines:3
Coverable lines:35
Total lines:114
Line coverage:91.4% (32 of 35)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SimpleGPUSkinning()0%110100%
Prepare(...)0%44095%
Update()0%2.062075%
UpdateMatrices()0%330100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Rendering/Utils/GPUSkinning/SimpleGPUSkinning.cs

#LineLine coverage
 1using System.Linq;
 2using UnityEngine;
 3using Object = UnityEngine.Object;
 4
 5namespace GPUSkinning
 6{
 7    public interface IGPUSkinning
 8    {
 9        Renderer renderer { get; }
 10        void Update();
 11        void Prepare(SkinnedMeshRenderer skr, bool encodeBindPoses = false);
 12    }
 13
 14    public static class GPUSkinningUtils
 15    {
 16        /// <summary>
 17        /// This must be done once per SkinnedMeshRenderer before animating.
 18        /// </summary>
 19        /// <param name="skr"></param>
 20        public static void EncodeBindPosesIntoMesh(SkinnedMeshRenderer skr)
 21        {
 22            Mesh sharedMesh = skr.sharedMesh;
 23            int vertexCount = sharedMesh.vertexCount;
 24            Vector4[] bone01data = new Vector4[vertexCount];
 25            Vector4[] bone23data = new Vector4[vertexCount];
 26
 27            BoneWeight[] boneWeights = sharedMesh.boneWeights;
 28
 29            for ( int i = 0; i < vertexCount; i ++ )
 30            {
 31                BoneWeight boneWeight = boneWeights[i];
 32                bone01data[i].x = boneWeight.boneIndex0;
 33                bone01data[i].y = boneWeight.weight0;
 34                bone01data[i].z = boneWeight.boneIndex1;
 35                bone01data[i].w = boneWeight.weight1;
 36
 37                bone23data[i].x = boneWeight.boneIndex2;
 38                bone23data[i].y = boneWeight.weight2;
 39                bone23data[i].z = boneWeight.boneIndex3;
 40                bone23data[i].w = boneWeight.weight3;
 41            }
 42
 43            skr.sharedMesh.tangents = bone01data;
 44            skr.sharedMesh.SetUVs(1, bone23data);
 45        }
 46    }
 47
 48    public class SimpleGPUSkinning : IGPUSkinning
 49    {
 150        private static readonly int BONE_MATRICES = Shader.PropertyToID("_Matrices");
 151        private static readonly int BIND_POSES = Shader.PropertyToID("_BindPoses");
 152        private static readonly int RENDERER_WORLD_INVERSE = Shader.PropertyToID("_WorldInverse");
 53
 054        public Renderer renderer { get; private set; }
 55
 56        private Transform[] bones;
 57        private Matrix4x4[] boneMatrices;
 58
 59        public void Prepare(SkinnedMeshRenderer skr, bool encodeBindPoses = false)
 60        {
 161            if ( encodeBindPoses )
 062                GPUSkinningUtils.EncodeBindPosesIntoMesh(skr);
 63
 164            boneMatrices = new Matrix4x4[skr.bones.Length];
 65
 166            GameObject go = skr.gameObject;
 67
 168            if (!go.TryGetComponent(out MeshFilter meshFilter))
 169                meshFilter = go.AddComponent<MeshFilter>();
 70
 171            meshFilter.sharedMesh = skr.sharedMesh;
 72
 173            renderer = go.AddComponent<MeshRenderer>();
 174            renderer.enabled = skr.enabled;
 175            renderer.sharedMaterials = skr.sharedMaterials;
 476            foreach (Material material in renderer.sharedMaterials)
 77            {
 178                material.SetMatrixArray(BIND_POSES, skr.sharedMesh.bindposes.ToArray());
 179                material.EnableKeyword("_GPU_SKINNING");
 80            }
 81
 182            bones = skr.bones;
 183            meshFilter.mesh.bounds = new Bounds(new Vector3(0, 2, 0), new Vector3(1, 3, 1));
 184            UpdateMatrices();
 85
 186            Object.Destroy(skr);
 187        }
 88
 89        public void Update()
 90        {
 191            if (!renderer.gameObject.activeInHierarchy)
 092                return;
 93
 194            UpdateMatrices();
 195        }
 96
 97        private void UpdateMatrices()
 98        {
 299            int bonesLength = bones.Length;
 252100            for (int i = 0; i < bonesLength; i++)
 101            {
 124102                Transform bone = bones[i];
 124103                boneMatrices[i] = bone.localToWorldMatrix;
 104            }
 105
 8106            for (int index = 0; index < renderer.sharedMaterials.Length; index++)
 107            {
 2108                Material material = renderer.sharedMaterials[index];
 2109                material.SetMatrix(RENDERER_WORLD_INVERSE, renderer.transform.worldToLocalMatrix);
 2110                material.SetMatrixArray(BONE_MATRICES, boneMatrices);
 111            }
 2112        }
 113    }
 114}