< 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:150
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%
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 Unity.Collections;
 3using UnityEngine;
 4using UnityEngine.Profiling;
 5using Object = UnityEngine.Object;
 6
 7namespace GPUSkinning
 8{
 9    public interface IGPUSkinning
 10    {
 11        Renderer renderer { get; }
 12        void Update();
 13        void Prepare(SkinnedMeshRenderer skr, bool encodeBindPoses = false);
 14    }
 15
 16    public static class GPUSkinningUtils
 17    {
 18        /// <summary>
 19        /// This must be done once per SkinnedMeshRenderer before animating.
 20        /// </summary>
 21        /// <param name="skr"></param>
 22        public static void EncodeBindPosesIntoMesh(SkinnedMeshRenderer skr)
 23        {
 24            Mesh sharedMesh = skr.sharedMesh;
 25            int vertexCount = sharedMesh.vertexCount;
 26
 27            NativeArray<Vector4> bone01data = new NativeArray<Vector4>(vertexCount, Allocator.Temp, NativeArrayOptions.U
 28            NativeArray<Vector4> bone23data = new NativeArray<Vector4>(vertexCount, Allocator.Temp, NativeArrayOptions.U
 29
 30            var bonesPerVertex = sharedMesh.GetBonesPerVertex();
 31            var boneWeightsNative = sharedMesh.GetAllBoneWeights();
 32            var boneIndex = 0;
 33            for ( int i = 0; i < vertexCount; i ++ )
 34            {
 35                byte boneCount = bonesPerVertex[i];
 36                if (boneCount == 0)
 37                {
 38                    bone01data[i] = new Vector4(0, 0, 0, 0);
 39                    bone23data[i] = new Vector4(0, 0, 0, 0);
 40                }
 41                else if (boneCount == 1)
 42                {
 43                    var bw0 = boneWeightsNative[boneIndex];
 44                    bone01data[i] = new Vector4(bw0.boneIndex, bw0.weight, 0, 0);
 45                    bone23data[i] = new Vector4(0, 0, 0, 0);
 46                }
 47                else if (boneCount == 2)
 48                {
 49                    var bw0 = boneWeightsNative[boneIndex];
 50                    var bw1 = boneWeightsNative[boneIndex+1];
 51                    bone01data[i] = new Vector4(bw0.boneIndex, bw0.weight, bw1.boneIndex, bw1.weight);
 52                    bone23data[i] = new Vector4(0, 0, 0, 0);
 53                }
 54                else if (boneCount == 3)
 55                {
 56                    var bw0 = boneWeightsNative[boneIndex];
 57                    var bw1 = boneWeightsNative[boneIndex+1];
 58                    var bw2 = boneWeightsNative[boneIndex+2];
 59                    bone01data[i] = new Vector4(bw0.boneIndex, bw0.weight, bw1.boneIndex, bw1.weight);
 60                    bone23data[i] = new Vector4(bw2.boneIndex, bw2.weight, 0, 0);
 61                }
 62                else if (boneCount >= 4)
 63                {
 64                    var bw0 = boneWeightsNative[boneIndex];
 65                    var bw1 = boneWeightsNative[boneIndex+1];
 66                    var bw2 = boneWeightsNative[boneIndex+2];
 67                    var bw3 = boneWeightsNative[boneIndex+3];
 68                    bone01data[i] = new Vector4(bw0.boneIndex, bw0.weight, bw1.boneIndex, bw1.weight);
 69                    bone23data[i] = new Vector4(bw2.boneIndex, bw2.weight, bw3.boneIndex, bw3.weight);
 70                }
 71
 72                boneIndex += boneCount;
 73            }
 74
 75            sharedMesh.SetTangents(bone01data);
 76            sharedMesh.SetUVs(1, bone23data);
 77
 78            bone01data.Dispose();
 79            bone23data.Dispose();
 80        }
 81
 82    }
 83
 84    public class SimpleGPUSkinning : IGPUSkinning
 85    {
 186        private static readonly int BONE_MATRICES = Shader.PropertyToID("_Matrices");
 187        private static readonly int BIND_POSES = Shader.PropertyToID("_BindPoses");
 188        private static readonly int RENDERER_WORLD_INVERSE = Shader.PropertyToID("_WorldInverse");
 89
 1390        public Renderer renderer { get; private set; }
 91
 92        private Transform[] bones;
 93        private Matrix4x4[] boneMatrices;
 94
 95        public void Prepare(SkinnedMeshRenderer skr, bool encodeBindPoses = false)
 96        {
 197            if ( encodeBindPoses )
 098                GPUSkinningUtils.EncodeBindPosesIntoMesh(skr);
 99
 1100            boneMatrices = new Matrix4x4[skr.bones.Length];
 101
 1102            GameObject go = skr.gameObject;
 103
 1104            if (!go.TryGetComponent(out MeshFilter meshFilter))
 1105                meshFilter = go.AddComponent<MeshFilter>();
 106
 1107            meshFilter.sharedMesh = skr.sharedMesh;
 108
 1109            renderer = go.AddComponent<MeshRenderer>();
 1110            renderer.enabled = skr.enabled;
 1111            renderer.sharedMaterials = skr.sharedMaterials;
 4112            foreach (Material material in renderer.sharedMaterials)
 113            {
 1114                material.SetMatrixArray(BIND_POSES, skr.sharedMesh.bindposes.ToArray());
 1115                material.EnableKeyword("_GPU_SKINNING");
 116            }
 117
 1118            bones = skr.bones;
 1119            meshFilter.mesh.bounds = new Bounds(new Vector3(0, 2, 0), new Vector3(1, 3, 1));
 1120            UpdateMatrices();
 121
 1122            Object.Destroy(skr);
 1123        }
 124
 125        public void Update()
 126        {
 1127            if (!renderer.gameObject.activeInHierarchy)
 0128                return;
 129
 1130            UpdateMatrices();
 1131        }
 132
 133        private void UpdateMatrices()
 134        {
 2135            int bonesLength = bones.Length;
 252136            for (int i = 0; i < bonesLength; i++)
 137            {
 124138                Transform bone = bones[i];
 124139                boneMatrices[i] = bone.localToWorldMatrix;
 140            }
 141
 8142            for (int index = 0; index < renderer.sharedMaterials.Length; index++)
 143            {
 2144                Material material = renderer.sharedMaterials[index];
 2145                material.SetMatrix(RENDERER_WORLD_INVERSE, renderer.transform.worldToLocalMatrix);
 2146                material.SetMatrixArray(BONE_MATRICES, boneMatrices);
 147            }
 2148        }
 149    }
 150}