< 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:155
Line coverage:94.2% (33 of 35)
Covered branches:0
Total branches:0
Covered methods:6
Total methods:6
Method coverage:100% (6 of 6)

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
 13        void Update();
 14
 15        void Prepare(SkinnedMeshRenderer skr, bool encodeBindPoses = false);
 16    }
 17
 18    public static class GPUSkinningUtils
 19    {
 20        /// <summary>
 21        /// This must be done once per SkinnedMeshRenderer before animating.
 22        /// </summary>
 23        /// <param name="skr"></param>
 24        public static void EncodeBindPosesIntoMesh(SkinnedMeshRenderer skr)
 25        {
 26            Mesh sharedMesh = skr.sharedMesh;
 27            int vertexCount = sharedMesh.vertexCount;
 28
 29            NativeArray<Vector4> bone01data = new NativeArray<Vector4>(vertexCount, Allocator.Temp, NativeArrayOptions.U
 30            NativeArray<Vector4> bone23data = new NativeArray<Vector4>(vertexCount, Allocator.Temp, NativeArrayOptions.U
 31
 32            var bonesPerVertex = sharedMesh.GetBonesPerVertex();
 33            var boneWeightsNative = sharedMesh.GetAllBoneWeights();
 34            var boneIndex = 0;
 35
 36            for (int i = 0; i < vertexCount; i++)
 37            {
 38                byte boneCount = bonesPerVertex[i];
 39
 40                if (boneCount == 0)
 41                {
 42                    bone01data[i] = new Vector4(0, 0, 0, 0);
 43                    bone23data[i] = new Vector4(0, 0, 0, 0);
 44                }
 45                else if (boneCount == 1)
 46                {
 47                    var bw0 = boneWeightsNative[boneIndex];
 48                    bone01data[i] = new Vector4(bw0.boneIndex, bw0.weight, 0, 0);
 49                    bone23data[i] = new Vector4(0, 0, 0, 0);
 50                }
 51                else if (boneCount == 2)
 52                {
 53                    var bw0 = boneWeightsNative[boneIndex];
 54                    var bw1 = boneWeightsNative[boneIndex + 1];
 55                    bone01data[i] = new Vector4(bw0.boneIndex, bw0.weight, bw1.boneIndex, bw1.weight);
 56                    bone23data[i] = new Vector4(0, 0, 0, 0);
 57                }
 58                else if (boneCount == 3)
 59                {
 60                    var bw0 = boneWeightsNative[boneIndex];
 61                    var bw1 = boneWeightsNative[boneIndex + 1];
 62                    var bw2 = boneWeightsNative[boneIndex + 2];
 63                    bone01data[i] = new Vector4(bw0.boneIndex, bw0.weight, bw1.boneIndex, bw1.weight);
 64                    bone23data[i] = new Vector4(bw2.boneIndex, bw2.weight, 0, 0);
 65                }
 66                else if (boneCount >= 4)
 67                {
 68                    var bw0 = boneWeightsNative[boneIndex];
 69                    var bw1 = boneWeightsNative[boneIndex + 1];
 70                    var bw2 = boneWeightsNative[boneIndex + 2];
 71                    var bw3 = boneWeightsNative[boneIndex + 3];
 72                    bone01data[i] = new Vector4(bw0.boneIndex, bw0.weight, bw1.boneIndex, bw1.weight);
 73                    bone23data[i] = new Vector4(bw2.boneIndex, bw2.weight, bw3.boneIndex, bw3.weight);
 74                }
 75
 76                boneIndex += boneCount;
 77            }
 78
 79            sharedMesh.SetTangents(bone01data);
 80            sharedMesh.SetUVs(1, bone23data);
 81
 82            bone01data.Dispose();
 83            bone23data.Dispose();
 84        }
 85    }
 86
 87    public class SimpleGPUSkinning : IGPUSkinning
 88    {
 189        private static readonly int BONE_MATRICES = Shader.PropertyToID("_Matrices");
 190        private static readonly int BIND_POSES = Shader.PropertyToID("_BindPoses");
 191        private static readonly int RENDERER_WORLD_INVERSE = Shader.PropertyToID("_WorldInverse");
 92
 1493        public Renderer renderer { get; private set; }
 94
 95        private Transform[] bones;
 96        private Matrix4x4[] boneMatrices;
 97
 98        public void Prepare(SkinnedMeshRenderer skr, bool encodeBindPoses = false)
 99        {
 1100            if (encodeBindPoses)
 0101                GPUSkinningUtils.EncodeBindPosesIntoMesh(skr);
 102
 1103            boneMatrices = new Matrix4x4[skr.bones.Length];
 104
 1105            GameObject go = skr.gameObject;
 106
 1107            if (!go.TryGetComponent(out MeshFilter meshFilter))
 1108                meshFilter = go.AddComponent<MeshFilter>();
 109
 1110            meshFilter.sharedMesh = skr.sharedMesh;
 111
 1112            renderer = go.AddComponent<MeshRenderer>();
 1113            renderer.enabled = skr.enabled;
 1114            renderer.sharedMaterials = skr.sharedMaterials;
 115
 4116            foreach (Material material in renderer.sharedMaterials)
 117            {
 1118                material.SetMatrixArray(BIND_POSES, skr.sharedMesh.bindposes.ToArray());
 1119                material.EnableKeyword("_GPU_SKINNING");
 120            }
 121
 1122            bones = skr.bones;
 1123            renderer.localBounds = new Bounds(new Vector3(0, 2, 0), new Vector3(1, 3, 1));
 1124            UpdateMatrices();
 125
 1126            Object.Destroy(skr);
 1127        }
 128
 129        public void Update()
 130        {
 1131            if (!renderer.gameObject.activeInHierarchy)
 0132                return;
 133
 1134            UpdateMatrices();
 1135        }
 136
 137        private void UpdateMatrices()
 138        {
 2139            int bonesLength = bones.Length;
 140
 252141            for (int i = 0; i < bonesLength; i++)
 142            {
 124143                Transform bone = bones[i];
 124144                boneMatrices[i] = bone.localToWorldMatrix;
 145            }
 146
 8147            for (int index = 0; index < renderer.sharedMaterials.Length; index++)
 148            {
 2149                Material material = renderer.sharedMaterials[index];
 2150                material.SetMatrix(RENDERER_WORLD_INVERSE, renderer.transform.worldToLocalMatrix);
 2151                material.SetMatrixArray(BONE_MATRICES, boneMatrices);
 152            }
 2153        }
 154    }
 155}