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 }