From 434d97a43f674bd0c7c6f2faf5a3c56b9cc59903 Mon Sep 17 00:00:00 2001 From: Refia <112306763+refiaa@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:45:42 +0900 Subject: [PATCH 1/4] bug hotfix --- Editor/DecimaterMain.cs | 185 +++++++++++++---- Runtime/MeshDecimaterUtility.cs | 354 ++++++++++++++++++++------------ 2 files changed, 360 insertions(+), 179 deletions(-) diff --git a/Editor/DecimaterMain.cs b/Editor/DecimaterMain.cs index 446efe2..ded0d7f 100644 --- a/Editor/DecimaterMain.cs +++ b/Editor/DecimaterMain.cs @@ -29,7 +29,7 @@ public static void ShowWindow() { GetWindow("Mesh Optimizer GUI"); } - + private void OnEnable() { LoadShaders(); @@ -71,10 +71,9 @@ private void OnGUI() decimateLevel = EditorGUILayout.Slider("Optimize Level", decimateLevel, 0.1f, 1.0f); if (EditorGUI.EndChangeCheck()) { - Mesh currentMesh = GetCurrentMesh(); - if (currentMesh != null) + if (originalMesh != null) { - MeshRevertManager.StoreDecimateLevel(currentMesh, decimateLevel); + MeshRevertManager.StoreDecimateLevel(originalMesh, decimateLevel); } } @@ -101,15 +100,40 @@ private void OnGUI() private void ApplyDecimation() { bool isSkinnedMeshRenderer = selectedGameObject.GetComponent() != null; + int boneCount = 0; + + if (isSkinnedMeshRenderer) + { + SkinnedMeshRenderer skinnedMeshRenderer = selectedGameObject.GetComponent(); + boneCount = skinnedMeshRenderer.bones.Length; + } + + EnableReadWrite(originalMesh); - EnableReadWrite(decimatedMesh); - MeshDecimaterUtility.DecimateMesh(originalMesh, decimatedMesh, decimateLevel, isSkinnedMeshRenderer, originalSubmeshCount); + MeshDecimaterUtility.DecimateMesh(originalMesh, decimatedMesh, decimateLevel, isSkinnedMeshRenderer, originalSubmeshCount, boneCount); + + decimatedMesh.RecalculateNormals(); + decimatedMesh.RecalculateBounds(); SaveDecimatedMesh(); MeshRevertManager.StoreOriginalMesh(decimatedMesh, originalMesh); - MeshRevertManager.StoreDecimateLevel(decimatedMesh, decimateLevel); + MeshRevertManager.StoreDecimateLevel(originalMesh, decimateLevel); + + EditorApplication.delayCall += () => + { + ApplyMeshToRenderer(isSkinnedMeshRenderer); + }; + + meshPreviewer.UpdatePreviewMesh(selectedGameObject); + + isFirstDecimation = false; + } + + private void ApplyMeshToRenderer(bool isSkinnedMeshRenderer) + { + if (selectedGameObject == null) return; if (selectedGameObject.GetComponent() != null) { @@ -121,18 +145,36 @@ private void ApplyDecimation() else if (isSkinnedMeshRenderer) { SkinnedMeshRenderer skinnedMeshRenderer = selectedGameObject.GetComponent(); + + skinnedMeshRenderer.sharedMesh = null; + skinnedMeshRenderer.sharedMesh = decimatedMesh; skinnedMeshRenderer.sharedMaterials = originalMaterials; + + skinnedMeshRenderer.updateWhenOffscreen = true; + + Animator animator = selectedGameObject.GetComponent(); + if (animator != null) + { + animator.Rebind(); + } + + ValidateBoneWeights(skinnedMeshRenderer); } + } - meshPreviewer.UpdatePreviewMesh(selectedGameObject); + private void ValidateBoneWeights(SkinnedMeshRenderer skinnedMeshRenderer) + { + Mesh mesh = skinnedMeshRenderer.sharedMesh; + int boneCount = skinnedMeshRenderer.bones.Length; - // errorめんどいの - if (isFirstDecimation) + for (int i = 0; i < mesh.boneWeights.Length; i++) { - isFirstDecimation = false; - Debug.LogWarning("First decimation performed. Applying decimation again to prevent mesh data mismatch error."); - ApplyDecimation(); + BoneWeight bw = mesh.boneWeights[i]; + if (bw.boneIndex0 >= boneCount || bw.boneIndex1 >= boneCount || bw.boneIndex2 >= boneCount || bw.boneIndex3 >= boneCount) + { + Debug.LogError($"Invalid bone index detected in boneWeights at vertex {i}: boneIndex0={bw.boneIndex0}, boneIndex1={bw.boneIndex1}, boneIndex2={bw.boneIndex2}, boneIndex3={bw.boneIndex3}"); + } } } @@ -219,18 +261,34 @@ private void UpdateSelection(GameObject newSelectedGameObject) if (newSelectedGameObject != null) { - MeshFilter meshFilter = newSelectedGameObject.GetComponent(); - SkinnedMeshRenderer skinnedMeshRenderer = newSelectedGameObject.GetComponent(); - - if (meshFilter != null) + Mesh original = GetOriginalMesh(newSelectedGameObject); + if (original != null) { selectedGameObject = newSelectedGameObject; - originalMesh = meshFilter.sharedMesh; + originalMesh = original; EnableReadWrite(originalMesh); decimateLevel = MeshRevertManager.GetDecimateLevel(originalMesh); - decimatedMesh = Instantiate(originalMesh); + string actualMeshName = GetActualMeshName(); + string originalPath = AssetDatabase.GetAssetPath(originalMesh); + string directory = Path.GetDirectoryName(originalPath); + string newFileName = $"{actualMeshName}{MESH_SUFFIX}.asset"; + string newPath = $"{directory}/{newFileName}"; + + Mesh existingDecimatedMesh = AssetDatabase.LoadAssetAtPath(newPath); + if (existingDecimatedMesh != null) + { + decimatedMesh = existingDecimatedMesh; + } + else + { + decimatedMesh = new Mesh(); + decimatedMesh.name = $"{actualMeshName}{MESH_SUFFIX}"; + AssetDatabase.CreateAsset(decimatedMesh, newPath); + AssetDatabase.SaveAssets(); + } + meshInfoDisplay.SetOriginalMesh(originalMesh); Renderer renderer = newSelectedGameObject.GetComponent(); @@ -245,29 +303,36 @@ private void UpdateSelection(GameObject newSelectedGameObject) Debug.Log($"Selected Mesh: {AssetDatabase.GetAssetPath(originalMesh)}"); Repaint(); } - else if (skinnedMeshRenderer != null) - { - selectedGameObject = newSelectedGameObject; - originalMesh = skinnedMeshRenderer.sharedMesh; - EnableReadWrite(originalMesh); - - decimateLevel = MeshRevertManager.GetDecimateLevel(originalMesh); - - decimatedMesh = Instantiate(originalMesh); - meshInfoDisplay.SetOriginalMesh(originalMesh); + } + } - originalMaterials = skinnedMeshRenderer.sharedMaterials; - originalSubmeshCount = new int[originalMesh.subMeshCount]; - for (int i = 0; i < originalMesh.subMeshCount; i++) - { - originalSubmeshCount[i] = originalMesh.GetTriangles(i).Length / 3; - } + private Mesh GetOriginalMesh(GameObject gameObject) + { + MeshFilter meshFilter = gameObject.GetComponent(); + if (meshFilter != null && meshFilter.sharedMesh != null) + { + Mesh mesh = meshFilter.sharedMesh; + if (mesh.name.EndsWith(MESH_SUFFIX)) + { + Mesh original = MeshRevertManager.GetOriginalMesh(mesh); + return original != null ? original : mesh; + } + return mesh; + } - Selection.activeObject = originalMesh; - Debug.Log($"Selected Mesh: {AssetDatabase.GetAssetPath(originalMesh)}"); - Repaint(); + SkinnedMeshRenderer skinnedMeshRenderer = gameObject.GetComponent(); + if (skinnedMeshRenderer != null && skinnedMeshRenderer.sharedMesh != null) + { + Mesh mesh = skinnedMeshRenderer.sharedMesh; + if (mesh.name.EndsWith(MESH_SUFFIX)) + { + Mesh original = MeshRevertManager.GetOriginalMesh(mesh); + return original != null ? original : mesh; } + return mesh; } + + return null; } private void SaveDecimatedMesh() @@ -277,7 +342,13 @@ private void SaveDecimatedMesh() string originalPath = AssetDatabase.GetAssetPath(originalMesh); string directory = Path.GetDirectoryName(originalPath); string newFileName = $"{actualMeshName}{MESH_SUFFIX}.asset"; - string newPath = Path.Combine(directory, newFileName); + + if (actualMeshName.EndsWith(MESH_SUFFIX)) + { + newFileName = $"{RemoveDecimatedSuffix(actualMeshName)}{MESH_SUFFIX}.asset"; + } + + string newPath = $"{directory}/{newFileName}"; Mesh existingMesh = AssetDatabase.LoadAssetAtPath(newPath); if (existingMesh != null) @@ -288,6 +359,7 @@ private void SaveDecimatedMesh() } else { + decimatedMesh.name = $"{RemoveDecimatedSuffix(actualMeshName)}{MESH_SUFFIX}"; AssetDatabase.CreateAsset(decimatedMesh, newPath); AssetDatabase.SaveAssets(); Debug.Log($"Decimated mesh saved: {newPath}"); @@ -303,18 +375,42 @@ private string GetActualMeshName() MeshFilter meshFilter = selectedGameObject.GetComponent(); if (meshFilter != null && meshFilter.sharedMesh != null) { - return meshFilter.sharedMesh.name; + return RemoveCloneAndDecimatedSuffix(meshFilter.sharedMesh.name); } SkinnedMeshRenderer skinnedMeshRenderer = selectedGameObject.GetComponent(); if (skinnedMeshRenderer != null && skinnedMeshRenderer.sharedMesh != null) { - return skinnedMeshRenderer.sharedMesh.name; + return RemoveCloneAndDecimatedSuffix(skinnedMeshRenderer.sharedMesh.name); } return "Unknown"; } + private string RemoveCloneAndDecimatedSuffix(string meshName) + { + // erase "(Clone)" + if (meshName.EndsWith("(Clone)")) + { + meshName = meshName.Substring(0, meshName.Length - "(Clone)".Length); + } + // erase "_decimated" + if (meshName.EndsWith(MESH_SUFFIX)) + { + meshName = meshName.Substring(0, meshName.Length - MESH_SUFFIX.Length); + } + return meshName; + } + + private string RemoveDecimatedSuffix(string meshName) + { + if (meshName.EndsWith(MESH_SUFFIX)) + { + return meshName.Substring(0, meshName.Length - MESH_SUFFIX.Length); + } + return meshName; + } + private Mesh GetCurrentMesh() { if (selectedGameObject != null) @@ -339,8 +435,11 @@ private void EnableReadWrite(Mesh mesh) ModelImporter modelImporter = AssetImporter.GetAtPath(path) as ModelImporter; if (modelImporter != null) { - modelImporter.isReadable = true; - AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate); + if (!modelImporter.isReadable) + { + modelImporter.isReadable = true; + AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate); + } } } diff --git a/Runtime/MeshDecimaterUtility.cs b/Runtime/MeshDecimaterUtility.cs index f70345b..62aa62f 100644 --- a/Runtime/MeshDecimaterUtility.cs +++ b/Runtime/MeshDecimaterUtility.cs @@ -1,5 +1,7 @@ using UnityEngine; using UnityMeshSimplifier; +using System.Collections.Generic; +using System.Linq; /* using UnityMeshSimplifier from github.com/Whinarn/UnityMeshSimplifier @@ -7,140 +9,220 @@ public static class MeshDecimaterUtility { - public static void DecimateMesh(Mesh originalMesh, Mesh decimatedMesh, float decimateLevel, bool isSkinnedMeshRenderer, int[] originalSubmeshCount) - { - try - { - MeshSimplifier meshSimplifier = new MeshSimplifier(); - meshSimplifier.Initialize(originalMesh); - - meshSimplifier.PreserveBorderEdges = true; - meshSimplifier.PreserveUVSeamEdges = true; - - meshSimplifier.SimplifyMesh(decimateLevel); - - Mesh simplifiedMesh = meshSimplifier.ToMesh(); - - decimatedMesh.Clear(); - decimatedMesh.vertices = simplifiedMesh.vertices; - decimatedMesh.normals = simplifiedMesh.normals; - decimatedMesh.uv = simplifiedMesh.uv; - decimatedMesh.tangents = simplifiedMesh.tangents; - - decimatedMesh.subMeshCount = originalMesh.subMeshCount; - for (int i = 0; i < originalMesh.subMeshCount; i++) - { - int[] triangles = simplifiedMesh.GetTriangles(i); - int targetTriangleCount = Mathf.CeilToInt(originalSubmeshCount[i] * decimateLevel); - if (triangles.Length > targetTriangleCount * 3) - { - System.Array.Resize(ref triangles, targetTriangleCount * 3); - } - decimatedMesh.SetTriangles(triangles, i); - } - - if (isSkinnedMeshRenderer) - { - if (originalMesh.bindposes != null && originalMesh.boneWeights != null && originalMesh.boneWeights.Length == originalMesh.vertexCount) - { - decimatedMesh.bindposes = originalMesh.bindposes; - decimatedMesh.boneWeights = CopyBoneWeights(originalMesh, simplifiedMesh); - } - - CopyBlendShapes(originalMesh, simplifiedMesh, decimatedMesh); - } - else - { - CopyBlendShapes(originalMesh, simplifiedMesh, decimatedMesh); - } - - decimatedMesh.RecalculateBounds(); - decimatedMesh.RecalculateNormals(); - decimatedMesh.RecalculateTangents(); - } - catch(System.Exception ex) - { - Debug.LogError($"Decimation failed: {ex.Message}"); - } - } - - private static void CopyBlendShapes(Mesh sourceMesh, Mesh simplifiedMesh, Mesh targetMesh) - { - Vector3[] originalVertices = sourceMesh.vertices; - Vector3[] simplifiedVertices = simplifiedMesh.vertices; - int[] closestVertexMap = new int[simplifiedVertices.Length]; - - for (int i = 0; i < simplifiedVertices.Length; i++) - { - closestVertexMap[i] = FindClosestVertex(originalVertices, simplifiedVertices[i]); - } - - for (int i = 0; i < sourceMesh.blendShapeCount; i++) - { - string shapeName = sourceMesh.GetBlendShapeName(i); - int frameCount = sourceMesh.GetBlendShapeFrameCount(i); - - for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) - { - float frameWeight = sourceMesh.GetBlendShapeFrameWeight(i, frameIndex); - Vector3[] deltaVertices = new Vector3[simplifiedVertices.Length]; - Vector3[] deltaNormals = new Vector3[simplifiedVertices.Length]; - Vector3[] deltaTangents = new Vector3[simplifiedVertices.Length]; - - SimplifyBlendShapeFrame(sourceMesh, i, frameIndex, closestVertexMap, deltaVertices, deltaNormals, deltaTangents); - targetMesh.AddBlendShapeFrame(shapeName, frameWeight, deltaVertices, deltaNormals, deltaTangents); - } - } - } - - private static void SimplifyBlendShapeFrame(Mesh originalMesh, int shapeIndex, int frameIndex, int[] closestVertexMap, Vector3[] deltaVertices, Vector3[] deltaNormals, Vector3[] deltaTangents) - { - Vector3[] originalDeltaVertices = new Vector3[originalMesh.vertexCount]; - Vector3[] originalDeltaNormals = new Vector3[originalMesh.vertexCount]; - Vector3[] originalDeltaTangents = new Vector3[originalMesh.vertexCount]; - - originalMesh.GetBlendShapeFrameVertices(shapeIndex, frameIndex, originalDeltaVertices, originalDeltaNormals, originalDeltaTangents); - - for (int i = 0; i < closestVertexMap.Length; i++) - { - int closestVertexIndex = closestVertexMap[i]; - deltaVertices[i] = originalDeltaVertices[closestVertexIndex]; - deltaNormals[i] = originalDeltaNormals[closestVertexIndex]; - deltaTangents[i] = originalDeltaTangents[closestVertexIndex]; - } - } - - private static int FindClosestVertex(Vector3[] vertices, Vector3 targetVertex) - { - int closestIndex = 0; - float closestDistance = Vector3.Distance(vertices[0], targetVertex); - - for (int i = 1; i < vertices.Length; i++) - { - float distance = Vector3.Distance(vertices[i], targetVertex); - if (distance < closestDistance) - { - closestIndex = i; - closestDistance = distance; - } - } - - return closestIndex; - } - - private static BoneWeight[] CopyBoneWeights(Mesh originalMesh, Mesh simplifiedMesh) - { - Vector3[] originalVertices = originalMesh.vertices; - Vector3[] simplifiedVertices = simplifiedMesh.vertices; - BoneWeight[] originalBoneWeights = originalMesh.boneWeights; - BoneWeight[] simplifiedBoneWeights = new BoneWeight[simplifiedVertices.Length]; - - for (int i = 0; i < simplifiedVertices.Length; i++) - { - int closestVertexIndex = FindClosestVertex(originalVertices, simplifiedVertices[i]); - simplifiedBoneWeights[i] = originalBoneWeights[closestVertexIndex]; - } - - return simplifiedBoneWeights; - } + public static void DecimateMesh(Mesh originalMesh, Mesh decimatedMesh, float decimateLevel, bool isSkinnedMeshRenderer, int[] originalSubmeshCount, int boneCount) + { + try + { + MeshSimplifier meshSimplifier = new MeshSimplifier(); + meshSimplifier.Initialize(originalMesh); + + meshSimplifier.PreserveBorderEdges = true; + meshSimplifier.PreserveUVSeamEdges = true; + + meshSimplifier.SimplifyMesh(decimateLevel); + + Mesh simplifiedMesh = meshSimplifier.ToMesh(); + + decimatedMesh.Clear(); + decimatedMesh.vertices = simplifiedMesh.vertices; + decimatedMesh.normals = simplifiedMesh.normals; + decimatedMesh.uv = simplifiedMesh.uv; + decimatedMesh.tangents = simplifiedMesh.tangents; + + decimatedMesh.subMeshCount = originalMesh.subMeshCount; + for (int i = 0; i < originalMesh.subMeshCount; i++) + { + int[] triangles = simplifiedMesh.GetTriangles(i); + int targetTriangleCount = Mathf.CeilToInt(originalSubmeshCount[i] * decimateLevel); + if (triangles.Length > targetTriangleCount * 3) + { + System.Array.Resize(ref triangles, targetTriangleCount * 3); + } + decimatedMesh.SetTriangles(triangles, i); + } + + if (isSkinnedMeshRenderer) + { + if (originalMesh.bindposes != null && originalMesh.boneWeights != null && originalMesh.boneWeights.Length == originalMesh.vertexCount) + { + decimatedMesh.bindposes = originalMesh.bindposes; + decimatedMesh.boneWeights = CopyBoneWeights(originalMesh, simplifiedMesh, boneCount); + } + + CopyBlendShapes(originalMesh, simplifiedMesh, decimatedMesh); + } + else + { + CopyBlendShapes(originalMesh, simplifiedMesh, decimatedMesh); + } + + decimatedMesh.RecalculateBounds(); + decimatedMesh.RecalculateNormals(); + decimatedMesh.RecalculateTangents(); + } + catch (System.Exception ex) + { + Debug.LogError($"Decimation failed: {ex.Message}"); + } + } + + private static void CopyBlendShapes(Mesh sourceMesh, Mesh simplifiedMesh, Mesh targetMesh) + { + Vector3[] originalVertices = sourceMesh.vertices; + Vector3[] simplifiedVertices = simplifiedMesh.vertices; + int[] closestVertexMap = new int[simplifiedVertices.Length]; + + for (int i = 0; i < simplifiedVertices.Length; i++) + { + closestVertexMap[i] = FindClosestVertex(originalVertices, simplifiedVertices[i]); + } + + for (int i = 0; i < sourceMesh.blendShapeCount; i++) + { + string shapeName = sourceMesh.GetBlendShapeName(i); + int frameCount = sourceMesh.GetBlendShapeFrameCount(i); + + for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) + { + float frameWeight = sourceMesh.GetBlendShapeFrameWeight(i, frameIndex); + Vector3[] deltaVertices = new Vector3[simplifiedVertices.Length]; + Vector3[] deltaNormals = new Vector3[simplifiedVertices.Length]; + Vector3[] deltaTangents = new Vector3[simplifiedVertices.Length]; + + SimplifyBlendShapeFrame(sourceMesh, i, frameIndex, closestVertexMap, deltaVertices, deltaNormals, deltaTangents); + targetMesh.AddBlendShapeFrame(shapeName, frameWeight, deltaVertices, deltaNormals, deltaTangents); + } + } + } + + private static void SimplifyBlendShapeFrame(Mesh originalMesh, int shapeIndex, int frameIndex, int[] closestVertexMap, Vector3[] deltaVertices, Vector3[] deltaNormals, Vector3[] deltaTangents) + { + Vector3[] originalDeltaVertices = new Vector3[originalMesh.vertexCount]; + Vector3[] originalDeltaNormals = new Vector3[originalMesh.vertexCount]; + Vector3[] originalDeltaTangents = new Vector3[originalMesh.vertexCount]; + + originalMesh.GetBlendShapeFrameVertices(shapeIndex, frameIndex, originalDeltaVertices, originalDeltaNormals, originalDeltaTangents); + + for (int i = 0; i < closestVertexMap.Length; i++) + { + int closestVertexIndex = closestVertexMap[i]; + deltaVertices[i] = originalDeltaVertices[closestVertexIndex]; + deltaNormals[i] = originalDeltaNormals[closestVertexIndex]; + deltaTangents[i] = originalDeltaTangents[closestVertexIndex]; + } + } + + private static int FindClosestVertex(Vector3[] vertices, Vector3 targetVertex) + { + int closestIndex = 0; + float closestDistance = Vector3.Distance(vertices[0], targetVertex); + + for (int i = 1; i < vertices.Length; i++) + { + float distance = Vector3.Distance(vertices[i], targetVertex); + if (distance < closestDistance) + { + closestIndex = i; + closestDistance = distance; + } + } + + return closestIndex; + } + + private static BoneWeight[] CopyBoneWeights(Mesh originalMesh, Mesh simplifiedMesh, int boneCount) + { + Vector3[] originalVertices = originalMesh.vertices; + BoneWeight[] originalBoneWeights = originalMesh.boneWeights; + Vector3[] simplifiedVertices = simplifiedMesh.vertices; + BoneWeight[] simplifiedBoneWeights = new BoneWeight[simplifiedVertices.Length]; + + float influenceRadius = 0.1f; + + for (int i = 0; i < simplifiedVertices.Length; i++) + { + Vector3 simplifiedVertex = simplifiedVertices[i]; + List nearbyBoneWeights = new List(); + + for (int j = 0; j < originalVertices.Length; j++) + { + float distance = Vector3.Distance(simplifiedVertex, originalVertices[j]); + if (distance <= influenceRadius) + { + nearbyBoneWeights.Add(originalBoneWeights[j]); + } + } + + if (nearbyBoneWeights.Count == 0) + { + simplifiedBoneWeights[i] = new BoneWeight(); + } + else + { + Dictionary boneWeightDict = new Dictionary(); + + foreach (var bw in nearbyBoneWeights) + { + AddBoneWeight(boneWeightDict, bw.boneIndex0, bw.weight0, boneCount); + AddBoneWeight(boneWeightDict, bw.boneIndex1, bw.weight1, boneCount); + AddBoneWeight(boneWeightDict, bw.boneIndex2, bw.weight2, boneCount); + AddBoneWeight(boneWeightDict, bw.boneIndex3, bw.weight3, boneCount); + } + + var sortedBones = boneWeightDict.OrderByDescending(bw => bw.Value).Take(4).ToList(); + BoneWeight newBoneWeight = new BoneWeight(); + float weightSum = sortedBones.Sum(bw => bw.Value); + + for (int k = 0; k < sortedBones.Count; k++) + { + int boneIndex = sortedBones[k].Key; + float normalizedWeight = sortedBones[k].Value / weightSum; + + if (boneIndex >= boneCount) + { + Debug.LogWarning($"Bone index {boneIndex} is out of range ({boneCount}). Clamping to 0."); + boneIndex = 0; + } + + switch (k) + { + case 0: + newBoneWeight.boneIndex0 = boneIndex; + newBoneWeight.weight0 = normalizedWeight; + break; + case 1: + newBoneWeight.boneIndex1 = boneIndex; + newBoneWeight.weight1 = normalizedWeight; + break; + case 2: + newBoneWeight.boneIndex2 = boneIndex; + newBoneWeight.weight2 = normalizedWeight; + break; + case 3: + newBoneWeight.boneIndex3 = boneIndex; + newBoneWeight.weight3 = normalizedWeight; + break; + } + } + + simplifiedBoneWeights[i] = newBoneWeight; + } + } + + return simplifiedBoneWeights; + } + + private static void AddBoneWeight(Dictionary dict, int boneIndex, float weight, int boneCount) + { + if (boneIndex < 0 || boneIndex >= boneCount) return; + + if (dict.ContainsKey(boneIndex)) + { + dict[boneIndex] += weight; + } + else + { + dict[boneIndex] = weight; + } + } } From bf6468f046ff03cefd3fa6bc46d42bf78a49f68f Mon Sep 17 00:00:00 2001 From: Refia <112306763+refiaa@users.noreply.github.com> Date: Tue, 22 Oct 2024 00:00:11 +0900 Subject: [PATCH 2/4] revert login enhanced --- Editor/DecimaterMain.cs | 52 +++++++++++++++++++++---------------- Editor/MeshRevertManager.cs | 27 ++++++++++++++++++- 2 files changed, 56 insertions(+), 23 deletions(-) diff --git a/Editor/DecimaterMain.cs b/Editor/DecimaterMain.cs index ded0d7f..4f7332d 100644 --- a/Editor/DecimaterMain.cs +++ b/Editor/DecimaterMain.cs @@ -71,10 +71,7 @@ private void OnGUI() decimateLevel = EditorGUILayout.Slider("Optimize Level", decimateLevel, 0.1f, 1.0f); if (EditorGUI.EndChangeCheck()) { - if (originalMesh != null) - { - MeshRevertManager.StoreDecimateLevel(originalMesh, decimateLevel); - } + // NOTHING HERE } GUILayout.Space(10); @@ -110,6 +107,9 @@ private void ApplyDecimation() EnableReadWrite(originalMesh); + // save "level" to history + MeshRevertManager.PushDecimateLevel(originalMesh, decimateLevel); + MeshDecimaterUtility.DecimateMesh(originalMesh, decimatedMesh, decimateLevel, isSkinnedMeshRenderer, originalSubmeshCount, boneCount); decimatedMesh.RecalculateNormals(); @@ -119,8 +119,6 @@ private void ApplyDecimation() MeshRevertManager.StoreOriginalMesh(decimatedMesh, originalMesh); - MeshRevertManager.StoreDecimateLevel(originalMesh, decimateLevel); - EditorApplication.delayCall += () => { ApplyMeshToRenderer(isSkinnedMeshRenderer); @@ -180,26 +178,36 @@ private void ValidateBoneWeights(SkinnedMeshRenderer skinnedMeshRenderer) private void RevertDecimation() { - if (selectedGameObject.GetComponent() != null) + if (originalMesh == null) { - MeshFilter meshFilter = selectedGameObject.GetComponent(); - meshFilter.sharedMesh = originalMesh; - MeshRenderer meshRenderer = selectedGameObject.GetComponent(); - meshRenderer.sharedMaterials = originalMaterials; + Debug.LogWarning("Original mesh not found."); + return; } - else if (selectedGameObject.GetComponent() != null) + + float? previousDecimateLevel = MeshRevertManager.RevertDecimateLevel(originalMesh); + if (previousDecimateLevel.HasValue) { - SkinnedMeshRenderer skinnedMeshRenderer = selectedGameObject.GetComponent(); - skinnedMeshRenderer.sharedMesh = originalMesh; - skinnedMeshRenderer.sharedMaterials = originalMaterials; - } + decimateLevel = previousDecimateLevel.Value; + MeshRevertManager.PushDecimateLevel(originalMesh, decimateLevel); - decimateLevel = DEFAULT_DECIMATE_LEVEL; - MeshRevertManager.StoreDecimateLevel(originalMesh, decimateLevel); + ApplyDecimation(); - meshPreviewer.UpdatePreviewMesh(selectedGameObject); + Debug.Log($"Reverted to previous decimate level: {decimateLevel}"); + } + else + { + if (decimateLevel == DEFAULT_DECIMATE_LEVEL) + { + EditorUtility.DisplayDialog("Revert Failed", "Not able to revert. Already at the default decimate level.", "OK"); + } + else + { + EditorUtility.DisplayDialog("Revert Failed", "Nothing to revert.", "OK"); + } + Debug.LogWarning("Revert failed: No previous decimate level available."); + } - isFirstDecimation = true; + meshPreviewer.UpdatePreviewMesh(selectedGameObject); } private void RevertToOriginalMesh() @@ -230,7 +238,7 @@ private void RevertToOriginalMesh() Debug.Log("Reverted to original mesh."); decimateLevel = DEFAULT_DECIMATE_LEVEL; - MeshRevertManager.StoreDecimateLevel(originalMeshFromManager, decimateLevel); + MeshRevertManager.PushDecimateLevel(originalMeshFromManager, decimateLevel); meshInfoDisplay.SetOriginalMesh(originalMeshFromManager); } else @@ -238,7 +246,7 @@ private void RevertToOriginalMesh() Debug.LogWarning("Original mesh not found."); decimateLevel = DEFAULT_DECIMATE_LEVEL; - MeshRevertManager.StoreDecimateLevel(currentMesh, decimateLevel); + MeshRevertManager.PushDecimateLevel(currentMesh, decimateLevel); meshInfoDisplay.SetOriginalMesh(currentMesh); } diff --git a/Editor/MeshRevertManager.cs b/Editor/MeshRevertManager.cs index 4ce67d5..cbda7ec 100644 --- a/Editor/MeshRevertManager.cs +++ b/Editor/MeshRevertManager.cs @@ -5,6 +5,7 @@ public static class MeshRevertManager { private static Dictionary originalMeshMap = new Dictionary(); + private static Dictionary> decimateLevelHistoryMap = new Dictionary>(); public static void StoreOriginalMesh(Mesh decimatedMesh, Mesh originalMesh) { @@ -52,11 +53,16 @@ private static string GetMeshUniqueID(Mesh mesh) } } - public static void StoreDecimateLevel(Mesh mesh, float decimateLevel) + public static void PushDecimateLevel(Mesh mesh, float decimateLevel) { string uniqueID = GetMeshUniqueID(mesh); if (!string.IsNullOrEmpty(uniqueID)) { + if (!decimateLevelHistoryMap.ContainsKey(uniqueID)) + { + decimateLevelHistoryMap[uniqueID] = new Stack(); + } + decimateLevelHistoryMap[uniqueID].Push(decimateLevel); EditorPrefs.SetFloat("DecimateLevel_" + uniqueID, decimateLevel); } } @@ -70,4 +76,23 @@ public static float GetDecimateLevel(Mesh mesh) } return 1.0f; } + + public static float? RevertDecimateLevel(Mesh mesh) + { + string uniqueID = GetMeshUniqueID(mesh); + if (!string.IsNullOrEmpty(uniqueID) && decimateLevelHistoryMap.ContainsKey(uniqueID)) + { + var stack = decimateLevelHistoryMap[uniqueID]; + if (stack.Count > 1) + { + stack.Pop(); + + float previousLevel = stack.Peek(); + EditorPrefs.SetFloat("DecimateLevel_" + uniqueID, previousLevel); + + return previousLevel; + } + } + return null; + } } From e0d6be2acbb1aa152d95ad60a0636ccc54d41ad4 Mon Sep 17 00:00:00 2001 From: Refia <112306763+refiaa@users.noreply.github.com> Date: Tue, 22 Oct 2024 00:04:32 +0900 Subject: [PATCH 3/4] Version and GUI name --- Editor/DecimaterMain.cs | 4 ++-- VERSION | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 VERSION diff --git a/Editor/DecimaterMain.cs b/Editor/DecimaterMain.cs index 4f7332d..e0f92c5 100644 --- a/Editor/DecimaterMain.cs +++ b/Editor/DecimaterMain.cs @@ -80,12 +80,12 @@ private void OnGUI() ApplyDecimation(); } - if (GUILayout.Button("Revert")) + if (GUILayout.Button("Undo")) { RevertDecimation(); } - if (GUILayout.Button("Revert to Original")) + if (GUILayout.Button("Reset To Original Mesh")) { RevertToOriginalMesh(); } diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..ecc017d --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.0.9.2 \ No newline at end of file From b757a2edf524512efec49072f44159d7c43429aa Mon Sep 17 00:00:00 2001 From: Refia <112306763+refiaa@users.noreply.github.com> Date: Tue, 22 Oct 2024 00:10:08 +0900 Subject: [PATCH 4/4] README --- README.jp.md | 12 ++++++++++++ README.md | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/README.jp.md b/README.jp.md index 6f8e50a..33225ba 100644 --- a/README.jp.md +++ b/README.jp.md @@ -140,6 +140,18 @@ v0.0.9.1: > Minor Bug fixes +v0.0.9.2: + +> Bug fix ; +> +> - Fix Mesh vanishing problem cause by `(Clone)` and `_Decimated`. +> +> - Fix SkinMeshRenderer issue in apply optimization +> +> - Fix Revert Button to undo +> +> - Change name of some GUI (`Revert` to `Undo`, `Revert to Original` to `Reset To Original Mesh`) + ``` work confirmed in diff --git a/README.md b/README.md index 36b785d..7b57e84 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,17 @@ v0.0.9.1: > Minor Bug fixes +v0.0.9.2: + +> Bug fix ; +> +> - Fix Mesh vanishing problem cause by `(Clone)` and `_Decimated`. +> +> - Fix SkinMeshRenderer issue in apply optimization +> +> - Fix Revert Button to undo +> +> - Change name of some GUI (`Revert` to `Undo`, `Revert to Original` to `Reset To Original Mesh`) ``` work confirmed in