< Summary

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

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
EncodeBindPosesIntoMesh(...)0%220100%

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        {
 121            Mesh sharedMesh = skr.sharedMesh;
 122            int vertexCount = sharedMesh.vertexCount;
 123            Vector4[] bone01data = new Vector4[vertexCount];
 124            Vector4[] bone23data = new Vector4[vertexCount];
 25
 126            BoneWeight[] boneWeights = sharedMesh.boneWeights;
 27
 209628            for ( int i = 0; i < vertexCount; i ++ )
 29            {
 104730                BoneWeight boneWeight = boneWeights[i];
 104731                bone01data[i].x = boneWeight.boneIndex0;
 104732                bone01data[i].y = boneWeight.weight0;
 104733                bone01data[i].z = boneWeight.boneIndex1;
 104734                bone01data[i].w = boneWeight.weight1;
 35
 104736                bone23data[i].x = boneWeight.boneIndex2;
 104737                bone23data[i].y = boneWeight.weight2;
 104738                bone23data[i].z = boneWeight.boneIndex3;
 104739                bone23data[i].w = boneWeight.weight3;
 40            }
 41
 142            skr.sharedMesh.tangents = bone01data;
 143            skr.sharedMesh.SetUVs(1, bone23data);
 144        }
 45    }
 46
 47    public class SimpleGPUSkinning : IGPUSkinning
 48    {
 49        private static readonly int BONE_MATRICES = Shader.PropertyToID("_Matrices");
 50        private static readonly int BIND_POSES = Shader.PropertyToID("_BindPoses");
 51        private static readonly int RENDERER_WORLD_INVERSE = Shader.PropertyToID("_WorldInverse");
 52
 53        public Renderer renderer { get; }
 54
 55        private Transform[] bones;
 56        private Matrix4x4[] boneMatrices;
 57
 58        public SimpleGPUSkinning (SkinnedMeshRenderer skr, bool encodeBindPoses = true)
 59        {
 60            if ( encodeBindPoses )
 61                GPUSkinningUtils.EncodeBindPosesIntoMesh(skr);
 62
 63            boneMatrices = new Matrix4x4[skr.bones.Length];
 64
 65            GameObject go = skr.gameObject;
 66
 67            if (!go.TryGetComponent(out MeshFilter meshFilter))
 68                meshFilter = go.AddComponent<MeshFilter>();
 69
 70            meshFilter.sharedMesh = skr.sharedMesh;
 71
 72            renderer = go.AddComponent<MeshRenderer>();
 73            renderer.sharedMaterials = skr.sharedMaterials;
 74            foreach (Material material in renderer.sharedMaterials)
 75            {
 76                material.SetMatrixArray(BIND_POSES, skr.sharedMesh.bindposes.ToArray());
 77                material.EnableKeyword("_GPU_SKINNING");
 78            }
 79
 80            bones = skr.bones;
 81            meshFilter.mesh.bounds = new Bounds(new Vector3(0, 2, 0), new Vector3(1, 3, 1));
 82            UpdateMatrices();
 83
 84            Object.Destroy(skr);
 85        }
 86
 87        public void Update()
 88        {
 89            if (!renderer.isVisible)
 90                return;
 91
 92            UpdateMatrices();
 93        }
 94
 95        private void UpdateMatrices()
 96        {
 97            int bonesLength = bones.Length;
 98            for (int i = 0; i < bonesLength; i++)
 99            {
 100                Transform bone = bones[i];
 101                boneMatrices[i] = bone.localToWorldMatrix;
 102            }
 103
 104            for (int index = 0; index < renderer.sharedMaterials.Length; index++)
 105            {
 106                Material material = renderer.sharedMaterials[index];
 107                material.SetMatrix(RENDERER_WORLD_INVERSE, renderer.transform.worldToLocalMatrix);
 108                material.SetMatrixArray(BONE_MATRICES, boneMatrices);
 109            }
 110        }
 111    }
 112}