Files
2025-01-25 04:38:09 +08:00

781 lines
22 KiB
C#

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using UltimateGameTools.MeshSimplifier;
public class MeshSimplify : MonoBehaviour
{
[HideInInspector]
public Mesh m_originalMesh = null;
[HideInInspector]
public Mesh m_simplifiedMesh = null;
[HideInInspector]
public bool m_bEnablePrefabUsage = false;
[HideInInspector]
public float m_fVertexAmount = 1.0f;
[HideInInspector]
public string m_strAssetPath = null;
[HideInInspector]
public MeshSimplify m_meshSimplifyRoot;
[HideInInspector]
public List<MeshSimplify> m_listDependentChildren = new List<MeshSimplify>();
[HideInInspector]
public bool m_bExpandRelevanceSpheres = true;
public RelevanceSphere[] m_aRelevanceSpheres = null;
[SerializeField, HideInInspector]
private Simplifier m_meshSimplifier = null;
[SerializeField, HideInInspector]
private bool m_bGenerateIncludeChildren = true;
[SerializeField, HideInInspector]
private bool m_bOverrideRootSettings = false;
[SerializeField, HideInInspector]
private bool m_bUseEdgeLength = true, m_bUseCurvature = true, m_bProtectTexture = true, m_bLockBorder = true;
[SerializeField, HideInInspector]
private bool m_bDataDirty = true;
[SerializeField, HideInInspector]
private bool m_bExcludedFromTree = false;
#if UNITY_EDITOR
public void OnDrawGizmos()
{
if (m_meshSimplifyRoot != null)
{
if (m_meshSimplifyRoot.m_bExpandRelevanceSpheres == false)
{
return;
}
}
else
{
if (m_bExpandRelevanceSpheres == false)
{
return;
}
}
Gizmos.color = Color.red;
RelevanceSphere[] aRelevanceSpheres = m_meshSimplifyRoot != null ? m_meshSimplifyRoot.m_aRelevanceSpheres : m_aRelevanceSpheres;
if (aRelevanceSpheres == null)
{
return;
}
bool bDrawVertices = false;
for (int i = 0; i < UnityEditor.Selection.gameObjects.Length; i++)
{
if (((UnityEditor.Selection.gameObjects[i] == this.gameObject) && m_meshSimplifyRoot == null) || ((m_meshSimplifyRoot != null) && (UnityEditor.Selection.gameObjects[i] == m_meshSimplifyRoot.gameObject)))
{
bDrawVertices = true;
}
}
if (bDrawVertices == false)
{
return;
}
Vector3[] aVerticesWorld = Simplifier.GetWorldVertices(this.gameObject);
if(aVerticesWorld == null)
{
return;
}
Matrix4x4[] aSphereMatrices = new Matrix4x4[aRelevanceSpheres.Length];
for (int nSphere = 0; nSphere < aRelevanceSpheres.Length; nSphere++)
{
aSphereMatrices[nSphere] = Matrix4x4.TRS(aRelevanceSpheres[nSphere].m_v3Position, Quaternion.Euler(aRelevanceSpheres[nSphere].m_v3Rotation), aRelevanceSpheres[nSphere].m_v3Scale).inverse;
}
for (int nVertex = 0; nVertex < aVerticesWorld.Length; nVertex++)
{
for (int nSphere = 0; nSphere < aRelevanceSpheres.Length; nSphere++)
{
if (aRelevanceSpheres[nSphere].m_bExpanded)
{
Vector3 v3VertexSphereLocal = aSphereMatrices[nSphere].MultiplyPoint(aVerticesWorld[nVertex]);
if (v3VertexSphereLocal.magnitude <= 0.5)
{
Gizmos.DrawCube(aVerticesWorld[nVertex], Vector3.one * UnityEditor.HandleUtility.GetHandleSize(aVerticesWorld[nVertex]) * 0.05f);
break;
}
}
}
}
}
#endif
public static bool HasValidMeshData(GameObject go)
{
MeshFilter meshFilter = go.GetComponent<MeshFilter>();
if (meshFilter != null)
{
return true;
}
else
{
SkinnedMeshRenderer skin = go.GetComponent<SkinnedMeshRenderer>();
if (skin != null)
{
return true;
}
}
return false;
}
public static bool IsRootOrBelongsToTree(MeshSimplify meshSimplify, MeshSimplify root)
{
if (meshSimplify == null)
{
return false;
}
return (meshSimplify.m_bExcludedFromTree == false) && ((meshSimplify.m_meshSimplifyRoot == null) || (meshSimplify.m_meshSimplifyRoot == root) || (meshSimplify == root) || (meshSimplify.m_meshSimplifyRoot == root.m_meshSimplifyRoot));
}
public bool IsGenerateIncludeChildrenActive()
{
return m_bGenerateIncludeChildren;
}
public bool HasDependentChildren()
{
return m_listDependentChildren != null && m_listDependentChildren.Count > 0;
}
public bool HasDataDirty()
{
return m_bDataDirty;
}
public bool SetDataDirty(bool bDirty)
{
return m_bDataDirty = bDirty;
}
public bool HasNonMeshSimplifyGameObjectsInTree()
{
return HasNonMeshSimplifyGameObjectsInTreeRecursive(this, this.gameObject);
}
private bool HasNonMeshSimplifyGameObjectsInTreeRecursive(MeshSimplify root, GameObject gameObject)
{
MeshSimplify meshSimplify = gameObject.GetComponent<MeshSimplify>();
if (meshSimplify == null && HasValidMeshData(gameObject))
{
return true;
}
for (int nChild = 0; nChild < gameObject.transform.childCount; nChild++)
{
if(HasNonMeshSimplifyGameObjectsInTreeRecursive(root, gameObject.transform.GetChild(nChild).gameObject))
{
return true;
}
}
return false;
}
private void ConfigureSimplifier()
{
m_meshSimplifier.UseEdgeLength = (m_meshSimplifyRoot != null && m_bOverrideRootSettings == false) ? m_meshSimplifyRoot.m_bUseEdgeLength : m_bUseEdgeLength;
m_meshSimplifier.UseCurvature = (m_meshSimplifyRoot != null && m_bOverrideRootSettings == false) ? m_meshSimplifyRoot.m_bUseCurvature : m_bUseCurvature;
m_meshSimplifier.ProtectTexture = (m_meshSimplifyRoot != null && m_bOverrideRootSettings == false) ? m_meshSimplifyRoot.m_bProtectTexture : m_bProtectTexture;
m_meshSimplifier.LockBorder = (m_meshSimplifyRoot != null && m_bOverrideRootSettings == false) ? m_meshSimplifyRoot.m_bLockBorder : m_bLockBorder;
}
public Simplifier GetMeshSimplifier()
{
return m_meshSimplifier;
}
public void ComputeData(bool bRecurseIntoChildren, Simplifier.ProgressDelegate progress = null)
{
ComputeDataRecursive(this, this.gameObject, bRecurseIntoChildren, progress);
}
private static void ComputeDataRecursive(MeshSimplify root, GameObject gameObject, bool bRecurseIntoChildren, Simplifier.ProgressDelegate progress = null)
{
MeshSimplify meshSimplify = gameObject.GetComponent<MeshSimplify>();
if (meshSimplify == null && root.m_bGenerateIncludeChildren)
{
if (HasValidMeshData(gameObject))
{
meshSimplify = gameObject.AddComponent<MeshSimplify>();
meshSimplify.m_meshSimplifyRoot = root;
root.m_listDependentChildren.Add(meshSimplify);
}
}
if(meshSimplify != null)
{
if (IsRootOrBelongsToTree(meshSimplify, root))
{
meshSimplify.FreeData(false);
MeshFilter meshFilter = meshSimplify.GetComponent<MeshFilter>();
if (meshFilter != null && meshFilter.sharedMesh != null)
{
if (meshFilter.sharedMesh.vertexCount > 0)
{
if (meshSimplify.m_originalMesh == null)
{
meshSimplify.m_originalMesh = meshFilter.sharedMesh;
}
Simplifier[] simplifiers = meshSimplify.GetComponents<Simplifier>();
for (int c = 0; c < simplifiers.Length; c++)
{
if (Application.isEditor && Application.isPlaying == false)
{
DestroyImmediate(simplifiers[c]);
}
else
{
Destroy(simplifiers[c]);
}
}
meshSimplify.m_meshSimplifier = meshSimplify.gameObject.AddComponent<Simplifier>();
meshSimplify.m_meshSimplifier.hideFlags = HideFlags.HideInInspector;
meshSimplify.ConfigureSimplifier();
IEnumerator enumerator = meshSimplify.m_meshSimplifier.ProgressiveMesh(gameObject, meshSimplify.m_originalMesh, root.m_aRelevanceSpheres, meshSimplify.name, progress);
while (enumerator.MoveNext())
{
if (Simplifier.Cancelled)
{
return;
}
}
if (Simplifier.Cancelled)
{
return;
}
}
}
else
{
SkinnedMeshRenderer skin = meshSimplify.GetComponent<SkinnedMeshRenderer>();
if (skin != null)
{
if (skin.sharedMesh.vertexCount > 0)
{
if (meshSimplify.m_originalMesh == null)
{
meshSimplify.m_originalMesh = skin.sharedMesh;
}
Simplifier[] simplifiers = meshSimplify.GetComponents<Simplifier>();
for (int c = 0; c < simplifiers.Length; c++)
{
if (Application.isEditor && Application.isPlaying == false)
{
DestroyImmediate(simplifiers[c]);
}
else
{
Destroy(simplifiers[c]);
}
}
meshSimplify.m_meshSimplifier = meshSimplify.gameObject.AddComponent<Simplifier>();
meshSimplify.m_meshSimplifier.hideFlags = HideFlags.HideInInspector;
meshSimplify.ConfigureSimplifier();
IEnumerator enumerator = meshSimplify.m_meshSimplifier.ProgressiveMesh(gameObject, meshSimplify.m_originalMesh, root.m_aRelevanceSpheres, meshSimplify.name, progress);
while (enumerator.MoveNext())
{
if (Simplifier.Cancelled)
{
return;
}
}
if (Simplifier.Cancelled)
{
return;
}
}
}
}
meshSimplify.m_bDataDirty = false;
}
}
if(bRecurseIntoChildren)
{
for (int nChild = 0; nChild < gameObject.transform.childCount; nChild++)
{
ComputeDataRecursive(root, gameObject.transform.GetChild(nChild).gameObject, bRecurseIntoChildren, progress);
if (Simplifier.Cancelled)
{
return;
}
}
}
}
public bool HasData()
{
return (m_meshSimplifier != null && m_simplifiedMesh != null) || (m_listDependentChildren != null && m_listDependentChildren.Count != 0);
}
public bool HasSimplifiedMesh()
{
return m_simplifiedMesh != null && m_simplifiedMesh.vertexCount > 0;
}
public void ComputeMesh(bool bRecurseIntoChildren, Simplifier.ProgressDelegate progress = null)
{
ComputeMeshRecursive(this, this.gameObject, bRecurseIntoChildren, progress);
}
private static void ComputeMeshRecursive(MeshSimplify root, GameObject gameObject, bool bRecurseIntoChildren, Simplifier.ProgressDelegate progress = null)
{
MeshSimplify meshSimplify = gameObject.GetComponent<MeshSimplify>();
if (meshSimplify != null)
{
if (IsRootOrBelongsToTree(meshSimplify, root))
{
if (meshSimplify.m_meshSimplifier != null)
{
if (meshSimplify.m_simplifiedMesh)
{
meshSimplify.m_simplifiedMesh.Clear();
}
float fAmount = meshSimplify.m_fVertexAmount;
if (meshSimplify.m_bOverrideRootSettings == false && meshSimplify.m_meshSimplifyRoot != null)
{
fAmount = meshSimplify.m_meshSimplifyRoot.m_fVertexAmount;
}
if (meshSimplify.m_simplifiedMesh == null)
{
meshSimplify.m_simplifiedMesh = CreateNewEmptyMesh(meshSimplify);
}
meshSimplify.ConfigureSimplifier();
IEnumerator enumerator = meshSimplify.m_meshSimplifier.ComputeMeshWithVertexCount(gameObject, meshSimplify.m_simplifiedMesh, Mathf.RoundToInt(fAmount * meshSimplify.m_meshSimplifier.GetOriginalMeshUniqueVertexCount()), meshSimplify.name + " Simplified", progress);
while (enumerator.MoveNext())
{
if (Simplifier.Cancelled)
{
return;
}
}
if (Simplifier.Cancelled)
{
return;
}
}
}
}
if (bRecurseIntoChildren)
{
for (int nChild = 0; nChild < gameObject.transform.childCount; nChild++)
{
ComputeMeshRecursive(root, gameObject.transform.GetChild(nChild).gameObject, bRecurseIntoChildren, progress);
if (Simplifier.Cancelled)
{
return;
}
}
}
}
public void AssignSimplifiedMesh(bool bRecurseIntoChildren)
{
AssignSimplifiedMeshRecursive(this, this.gameObject, bRecurseIntoChildren);
}
private static void AssignSimplifiedMeshRecursive(MeshSimplify root, GameObject gameObject, bool bRecurseIntoChildren)
{
MeshSimplify meshSimplify = gameObject.GetComponent<MeshSimplify>();
if (meshSimplify != null)
{
if (IsRootOrBelongsToTree(meshSimplify, root))
{
if (meshSimplify.m_simplifiedMesh != null)
{
MeshFilter meshFilter = meshSimplify.GetComponent<MeshFilter>();
if (meshFilter != null)
{
meshFilter.sharedMesh = meshSimplify.m_simplifiedMesh;
}
else
{
SkinnedMeshRenderer skin = meshSimplify.GetComponent<SkinnedMeshRenderer>();
if (skin != null)
{
skin.sharedMesh = meshSimplify.m_simplifiedMesh;
}
}
}
}
}
if (bRecurseIntoChildren)
{
for (int nChild = 0; nChild < gameObject.transform.childCount; nChild++)
{
AssignSimplifiedMeshRecursive(root, gameObject.transform.GetChild(nChild).gameObject, bRecurseIntoChildren);
}
}
}
public void RestoreOriginalMesh(bool bDeleteData, bool bRecurseIntoChildren)
{
RestoreOriginalMeshRecursive(this, this.gameObject, bDeleteData, bRecurseIntoChildren);
}
private static void RestoreOriginalMeshRecursive(MeshSimplify root, GameObject gameObject, bool bDeleteData, bool bRecurseIntoChildren)
{
MeshSimplify meshSimplify = gameObject.GetComponent<MeshSimplify>();
if (meshSimplify != null)
{
if (IsRootOrBelongsToTree(meshSimplify, root))
{
if (meshSimplify.m_originalMesh != null)
{
MeshFilter meshFilter = meshSimplify.GetComponent<MeshFilter>();
if (meshFilter != null)
{
meshFilter.sharedMesh = meshSimplify.m_originalMesh;
}
else
{
SkinnedMeshRenderer skin = meshSimplify.GetComponent<SkinnedMeshRenderer>();
if (skin != null)
{
skin.sharedMesh = meshSimplify.m_originalMesh;
}
}
}
if (bDeleteData)
{
meshSimplify.FreeData(false);
meshSimplify.m_listDependentChildren.Clear();
}
}
}
if (bRecurseIntoChildren)
{
for (int nChild = 0; nChild < gameObject.transform.childCount; nChild++)
{
RestoreOriginalMeshRecursive(root, gameObject.transform.GetChild(nChild).gameObject, bDeleteData, bRecurseIntoChildren);
}
}
}
public bool HasOriginalMeshActive(bool bRecurseIntoChildren)
{
return HasOriginalMeshActiveRecursive(this, this.gameObject, bRecurseIntoChildren);
}
private static bool HasOriginalMeshActiveRecursive(MeshSimplify root, GameObject gameObject, bool bRecurseIntoChildren)
{
MeshSimplify meshSimplify = gameObject.GetComponent<MeshSimplify>();
bool bHasOriginalMeshActive = false;
if (meshSimplify != null)
{
if (IsRootOrBelongsToTree(meshSimplify, root))
{
if (meshSimplify.m_originalMesh != null)
{
MeshFilter meshFilter = meshSimplify.GetComponent<MeshFilter>();
if (meshFilter != null)
{
if(meshFilter.sharedMesh == meshSimplify.m_originalMesh)
{
bHasOriginalMeshActive = true;
}
}
else
{
SkinnedMeshRenderer skin = meshSimplify.GetComponent<SkinnedMeshRenderer>();
if (skin != null)
{
if(skin.sharedMesh == meshSimplify.m_originalMesh)
{
bHasOriginalMeshActive = true;
}
}
}
}
}
}
if (bRecurseIntoChildren)
{
for (int nChild = 0; nChild < gameObject.transform.childCount; nChild++)
{
bHasOriginalMeshActive = bHasOriginalMeshActive || HasOriginalMeshActiveRecursive(root, gameObject.transform.GetChild(nChild).gameObject, bRecurseIntoChildren);
}
}
return bHasOriginalMeshActive;
}
public bool HasVertexData(bool bRecurseIntoChildren)
{
return HasVertexDataRecursive(this, this.gameObject, bRecurseIntoChildren);
}
private static bool HasVertexDataRecursive(MeshSimplify root, GameObject gameObject, bool bRecurseIntoChildren)
{
MeshSimplify meshSimplify = gameObject.GetComponent<MeshSimplify>();
if (meshSimplify != null)
{
if (IsRootOrBelongsToTree(meshSimplify, root))
{
if (meshSimplify.m_simplifiedMesh && meshSimplify.m_simplifiedMesh.vertexCount > 0)
{
return true;
}
}
}
if (bRecurseIntoChildren)
{
for (int nChild = 0; nChild < gameObject.transform.childCount; nChild++)
{
if (HasVertexDataRecursive(root, gameObject.transform.GetChild(nChild).gameObject, bRecurseIntoChildren))
{
return true;
}
}
}
return false;
}
public int GetOriginalVertexCount(bool bRecurseIntoChildren)
{
int nVertexCount = 0;
GetOriginalVertexCountRecursive(this, this.gameObject, ref nVertexCount, bRecurseIntoChildren);
return nVertexCount;
}
private static void GetOriginalVertexCountRecursive(MeshSimplify root, GameObject gameObject, ref int nVertexCount, bool bRecurseIntoChildren)
{
MeshSimplify meshSimplify = gameObject.GetComponent<MeshSimplify>();
if (meshSimplify != null)
{
if (IsRootOrBelongsToTree(meshSimplify, root))
{
if (meshSimplify.m_originalMesh != null)
{
nVertexCount += meshSimplify.m_originalMesh.vertexCount;
}
}
}
if (bRecurseIntoChildren)
{
for (int nChild = 0; nChild < gameObject.transform.childCount; nChild++)
{
GetOriginalVertexCountRecursive(root, gameObject.transform.GetChild(nChild).gameObject, ref nVertexCount, bRecurseIntoChildren);
}
}
}
public int GetSimplifiedVertexCount(bool bRecurseIntoChildren)
{
int nVertexCount = 0;
GetSimplifiedVertexCountRecursive(this, this.gameObject, ref nVertexCount, bRecurseIntoChildren);
return nVertexCount;
}
private static void GetSimplifiedVertexCountRecursive(MeshSimplify root, GameObject gameObject, ref int nVertexCount, bool bRecurseIntoChildren)
{
MeshSimplify meshSimplify = gameObject.GetComponent<MeshSimplify>();
if (meshSimplify != null)
{
if (IsRootOrBelongsToTree(meshSimplify, root))
{
if (meshSimplify.m_simplifiedMesh != null)
{
nVertexCount += meshSimplify.m_simplifiedMesh.vertexCount;
}
}
}
if (bRecurseIntoChildren)
{
for (int nChild = 0; nChild < gameObject.transform.childCount; nChild++)
{
GetSimplifiedVertexCountRecursive(root, gameObject.transform.GetChild(nChild).gameObject, ref nVertexCount, bRecurseIntoChildren);
}
}
}
public void RemoveFromTree()
{
if (m_meshSimplifyRoot != null)
{
m_meshSimplifyRoot.m_listDependentChildren.Remove(this);
}
RestoreOriginalMesh(true, false);
m_bExcludedFromTree = true;
}
public void FreeData(bool bRecurseIntoChildren)
{
FreeDataRecursive(this, this.gameObject, bRecurseIntoChildren);
}
private static void FreeDataRecursive(MeshSimplify root, GameObject gameObject, bool bRecurseIntoChildren)
{
MeshSimplify meshSimplify = gameObject.GetComponent<MeshSimplify>();
if (meshSimplify != null)
{
if (IsRootOrBelongsToTree(meshSimplify, root))
{
if (meshSimplify.m_simplifiedMesh)
{
meshSimplify.m_simplifiedMesh.Clear();
}
Simplifier[] simplifiers = gameObject.GetComponents<Simplifier>();
for (int c = 0; c < simplifiers.Length; c++)
{
if (Application.isEditor && Application.isPlaying == false)
{
DestroyImmediate(simplifiers[c]);
}
else
{
Destroy(simplifiers[c]);
}
}
meshSimplify.m_bDataDirty = true;
}
}
if (bRecurseIntoChildren)
{
for (int nChild = 0; nChild < gameObject.transform.childCount; nChild++)
{
FreeDataRecursive(root, gameObject.transform.GetChild(nChild).gameObject, bRecurseIntoChildren);
}
}
}
private static Mesh CreateNewEmptyMesh(MeshSimplify meshSimplify)
{
if(meshSimplify.m_originalMesh == null)
{
return new Mesh();
}
Mesh meshOut = Mesh.Instantiate(meshSimplify.m_originalMesh);
meshOut.Clear();
return meshOut;
}
#if UNITY_EDITOR
public void DisablePrefabUsage(bool bRecurseIntoChildren)
{
DisablePrefabUsageRecursive(this, this.gameObject, bRecurseIntoChildren);
}
private static void DisablePrefabUsageRecursive(MeshSimplify root, GameObject gameObject, bool bRecurseIntoChildren)
{
MeshSimplify meshSimplify = gameObject.GetComponent<MeshSimplify>();
if (meshSimplify != null)
{
if (IsRootOrBelongsToTree(meshSimplify, root))
{
if (meshSimplify.m_simplifiedMesh)
{
if (UnityEditor.AssetDatabase.IsMainAsset(meshSimplify.m_simplifiedMesh) || UnityEditor.AssetDatabase.IsSubAsset(meshSimplify.m_simplifiedMesh))
{
Mesh newMesh = Instantiate(meshSimplify.m_simplifiedMesh) as Mesh;
meshSimplify.m_simplifiedMesh = newMesh;
}
}
meshSimplify.m_strAssetPath = null;
}
}
if (bRecurseIntoChildren)
{
for (int nChild = 0; nChild < gameObject.transform.childCount; nChild++)
{
DisablePrefabUsageRecursive(root, gameObject.transform.GetChild(nChild).gameObject, bRecurseIntoChildren);
}
}
}
#endif
}