public static SMesh BakeMesh(Transform transform, Mesh mesh, bool rendererEnabled, SVector3Array customVertices = null)
 {
     SMesh surrogate = new SMesh(transform, mesh.name, mesh.GetInstanceID(), transform.gameObject.activeInHierarchy && rendererEnabled);
     surrogate.header.type = SMesh.Type.full;
     CopyMeshData(mesh, surrogate, customVertices);
     return surrogate;
 }
        public override void Dispose()
        {
            base.Dispose();

            if (header != null) header.Dispose();
            if (subMeshes != null) subMeshes.Dispose();
            if (vertices != null) vertices.Dispose();
            if (uv != null) uv.Dispose();
            if (uv1 != null) uv1.Dispose();
            if (uv2 != null) uv2.Dispose();
            if (uv3 != null) uv3.Dispose();
            if (uv4 != null) uv4.Dispose();
            if (bindPoses != null) bindPoses.Dispose();
            if (bones != null) bones.Dispose();
            if (boneWeights != null) boneWeights.Dispose();

            header = null;
            subMeshes = null;
            triangles = null;
            vertices = null;
            uv = null;
            uv1 = null;
            uv2 = null;
            uv3 = null;
            uv4 = null;
            bindPoses = null;
            bones = null;
            boneWeights = null;
        }
        /// <summary>
        /// SkinnedMeshRenderer.BakeMesh but approximately 8 to 10 times faster, due too caching and raw copy-pasting code
        /// I know it looks like copy-pasted code, and it is, but I started with one method handling one, two and four bones at once... the static lookup, passing parameters, etc took twice the calculation power it does now!
        /// </summary>
        /// <param name="renderer"></param>
        /// <param name="maxBlendWeights"></param>
        /// <returns></returns>
        public static SMesh BakeSkinnedMesh(SkinnedMeshRenderer renderer, int maxBlendWeights)
        {
            if (renderer == null)
                return null;

            Mesh mesh = SceneHierarchyCache.GetMesh(renderer);
            if (mesh == null)
                return null;

            Transform[] bones = renderer.bones;
            //BoneWeight[] weights = mesh.boneWeights; //takes 25ms!
            BoneWeight[] weights = SceneHierarchyCache.GetBoneWeights(mesh); //reduced to 0.04ms!

            if (bones == null || bones.Length == 0 || weights == null || weights.Length == 0)
                return BakeMesh(renderer.transform, mesh, renderer.enabled);

            Vector3[] vertices = mesh.vertices;
            SVector3Array vectorArray = new SVector3Array(mesh.vertices.Length);
            float[] result = vectorArray.vectorData;

            if (weights.Length != vertices.Length)
            {
                if (vBug.settings.general.debugMode)
                    Debug.Log("weights.Length != vertices.Length");
                return BakeMesh(renderer.transform, mesh, renderer.enabled);
            }

            Matrix4x4 worldToLocal = renderer.transform.worldToLocalMatrix;
            Matrix4x4[] bindposes = mesh.bindposes;
            Matrix4x4[] matrices = new Matrix4x4[bones.Length];
            int i = bones.Length;
            while (--i > -1)
                matrices[i] = worldToLocal * bones[i].localToWorldMatrix * bindposes[i];

            i = 0;
            int j = 0;
            int iMax = vertices.Length;
            int maxInfluences = Mathf.Min(maxBlendWeights, (int)QualitySettings.blendWeights);

            if(maxInfluences == 1)
            {
                while (i < iMax)
                {
                    Vector3 vertex = matrices[weights[i].boneIndex0].MultiplyPoint3x4(vertices[i]);
                    result[j++] = vertex.x;
                    result[j++] = vertex.y;
                    result[j++] = vertex.z;
                    i++;
                }
                    //result[i] = AddBoneInfluenceOne(ref vertices[i], ref matrices, ref weights[i]);
            }
            else if (maxInfluences == 2)
            {
                while (i < iMax)
                {
                    //result[i] = AddBoneInfluenceTwo(ref vertices[i], ref matrices, ref weights[i]);
                    BoneWeight boneWeight = weights[i];
                    Vector3 oV = vertices[i];
                    Vector3 v = oV;
                    float wTotal = 0f;
                    float weight0 = boneWeight.weight0;
                    float weight1 = boneWeight.weight1;

                    if (weight0 > 0f)
                    {
                        v = matrices[boneWeight.boneIndex0].MultiplyPoint3x4(oV) * weight0;
                        wTotal = weight0;
                    }
                    if (weight1 > 0f)
                    {
                        v += matrices[boneWeight.boneIndex1].MultiplyPoint3x4(oV) * weight1;
                        wTotal += weight1;
                    }
                    if (wTotal < 1f)
                        v /= wTotal;

                    result[j++] = v.x;
                    result[j++] = v.y;
                    result[j++] = v.z;
                    i++;
                }
            }
            else
            {
                while (i < iMax)
                {
                    //result[i] = AddBoneInfluenceFour(ref vertices[i], ref matrices, ref weights[i]); //BAM! doubles performance using this instead of using one AddBoneInfluence method checking thousands of times the maxInfluences
                    BoneWeight boneWeight = weights[i];
                    Vector3 oV = vertices[i];
                    Vector3 v = oV;
                    float wTotal = 0f;
                    float weight0 = boneWeight.weight0;
                    float weight1 = boneWeight.weight1;
                    float weight2 = boneWeight.weight2;
                    float weight3 = boneWeight.weight3;

                    if (weight0 > 0f)
                    {
                        v = matrices[boneWeight.boneIndex0].MultiplyPoint3x4(oV) * weight0;
                        wTotal = weight0;
                    }
                    if (weight1 > 0f)
                    {
                        v += matrices[boneWeight.boneIndex1].MultiplyPoint3x4(oV) * weight1;
                        wTotal += weight1;
                    }
                    if (weight2 > 0f)
                    {
                        v += matrices[boneWeight.boneIndex2].MultiplyPoint3x4(oV) * weight2;
                        wTotal += weight2;
                    }
                    if (weight3 > 0f)
                    {
                        v += matrices[boneWeight.boneIndex3].MultiplyPoint3x4(oV) * weight3;
                        wTotal += weight3;
                    }
                    if (wTotal < 1f)
                        v /= wTotal;

                    result[j++] = v.x;
                    result[j++] = v.y;
                    result[j++] = v.z;
                    i++;
                }
            }

            SMesh surrogate = BakeMesh(renderer.transform, mesh, renderer.enabled, vectorArray);
            return surrogate;
        }
        private static void CopyMeshData(Mesh mesh, SMesh destination, SVector3Array customVertices = null)
        {
            destination.triangles = mesh.triangles;
            destination.subMeshes = new SSubMeshArray(mesh);

            if (customVertices != null) {
                destination.vertices = customVertices;
            } else {
                destination.vertices = new SVector3Array(mesh.vertices);
            }

            if (mesh.uv != null)
                destination.uv = new SVector2Array(mesh.uv);

            #if UNITY_4_6
            if (mesh.uv1 != null)
                destination.uv1 = new SVector2Array(mesh.uv1);
            #endif
            if (mesh.uv2 != null)
                destination.uv2 = new SVector2Array(mesh.uv2);

            #if !UNITY_4_6
            if (mesh.uv3 != null)
                destination.uv3 = new SVector2Array(mesh.uv3);

            if (mesh.uv4 != null)
                destination.uv4 = new SVector2Array(mesh.uv4);
            #endif
        }