< Summary

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

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SimpleGPUSkinning()0%110100%
SimpleGPUSkinning(...)0%440100%
Update()0%2.52050%
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    }
 12
 13    public static class GPUSkinningUtils
 14    {
 15        /// <summary>
 16        /// This must be done once per SkinnedMeshRenderer before animating.
 17        /// </summary>
 18        /// <param name="skr"></param>
 19        public static void EncodeBindPosesIntoMesh(SkinnedMeshRenderer skr)
 20        {
 21            Mesh sharedMesh = skr.sharedMesh;
 22            int vertexCount = sharedMesh.vertexCount;
 23            Vector4[] bone01data = new Vector4[vertexCount];
 24            Vector4[] bone23data = new Vector4[vertexCount];
 25
 26            BoneWeight[] boneWeights = sharedMesh.boneWeights;
 27
 28            for ( int i = 0; i < vertexCount; i ++ )
 29            {
 30                BoneWeight boneWeight = boneWeights[i];
 31                bone01data[i].x = boneWeight.boneIndex0;
 32                bone01data[i].y = boneWeight.weight0;
 33                bone01data[i].z = boneWeight.boneIndex1;
 34                bone01data[i].w = boneWeight.weight1;
 35
 36                bone23data[i].x = boneWeight.boneIndex2;
 37                bone23data[i].y = boneWeight.weight2;
 38                bone23data[i].z = boneWeight.boneIndex3;
 39                bone23data[i].w = boneWeight.weight3;
 40            }
 41
 42            skr.sharedMesh.tangents = bone01data;
 43            skr.sharedMesh.SetUVs(1, bone23data);
 44        }
 45    }
 46
 47    public class SimpleGPUSkinning : IGPUSkinning
 48    {
 149        private static readonly int BONE_MATRICES = Shader.PropertyToID("_Matrices");
 150        private static readonly int BIND_POSES = Shader.PropertyToID("_BindPoses");
 151        private static readonly int RENDERER_WORLD_INVERSE = Shader.PropertyToID("_WorldInverse");
 52
 253        public Renderer renderer { get; }
 54
 55        private Transform[] bones;
 56        private Matrix4x4[] boneMatrices;
 57
 158        public SimpleGPUSkinning (SkinnedMeshRenderer skr, bool encodeBindPoses = true)
 59        {
 160            if ( encodeBindPoses )
 161                GPUSkinningUtils.EncodeBindPosesIntoMesh(skr);
 62
 163            boneMatrices = new Matrix4x4[skr.bones.Length];
 64
 165            GameObject go = skr.gameObject;
 66
 167            if (!go.TryGetComponent(out MeshFilter meshFilter))
 168                meshFilter = go.AddComponent<MeshFilter>();
 69
 170            meshFilter.sharedMesh = skr.sharedMesh;
 71
 172            renderer = go.AddComponent<MeshRenderer>();
 173            renderer.sharedMaterials = skr.sharedMaterials;
 474            foreach (Material material in renderer.sharedMaterials)
 75            {
 176                material.SetMatrixArray(BIND_POSES, skr.sharedMesh.bindposes.ToArray());
 177                material.EnableKeyword("_GPU_SKINNING");
 78            }
 79
 180            bones = skr.bones;
 181            meshFilter.mesh.bounds = new Bounds(new Vector3(0, 2, 0), new Vector3(1, 3, 1));
 182            UpdateMatrices();
 83
 184            Object.Destroy(skr);
 185        }
 86
 87        public void Update()
 88        {
 189            if (!renderer.isVisible)
 190                return;
 91
 092            UpdateMatrices();
 093        }
 94
 95        private void UpdateMatrices()
 96        {
 197            int bonesLength = bones.Length;
 12698            for (int i = 0; i < bonesLength; i++)
 99            {
 62100                Transform bone = bones[i];
 62101                boneMatrices[i] = bone.localToWorldMatrix;
 102            }
 103
 4104            for (int index = 0; index < renderer.sharedMaterials.Length; index++)
 105            {
 1106                Material material = renderer.sharedMaterials[index];
 1107                material.SetMatrix(RENDERER_WORLD_INVERSE, renderer.transform.worldToLocalMatrix);
 1108                material.SetMatrixArray(BONE_MATRICES, boneMatrices);
 109            }
 1110        }
 111    }
 112}