Skip to content

Commit 2585ca7

Browse files
authored
Merge pull request #16 from refiaa/HotFix_meshVanishingProblem
Hot fix // mesh vanishing problem
2 parents ea4cc85 + b757a2e commit 2585ca7

6 files changed

Lines changed: 438 additions & 200 deletions

File tree

Editor/DecimaterMain.cs

Lines changed: 170 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public static void ShowWindow()
2929
{
3030
GetWindow<DecimaterMain>("Mesh Optimizer GUI");
3131
}
32-
32+
3333
private void OnEnable()
3434
{
3535
LoadShaders();
@@ -71,11 +71,7 @@ private void OnGUI()
7171
decimateLevel = EditorGUILayout.Slider("Optimize Level", decimateLevel, 0.1f, 1.0f);
7272
if (EditorGUI.EndChangeCheck())
7373
{
74-
Mesh currentMesh = GetCurrentMesh();
75-
if (currentMesh != null)
76-
{
77-
MeshRevertManager.StoreDecimateLevel(currentMesh, decimateLevel);
78-
}
74+
// NOTHING HERE
7975
}
8076

8177
GUILayout.Space(10);
@@ -84,12 +80,12 @@ private void OnGUI()
8480
ApplyDecimation();
8581
}
8682

87-
if (GUILayout.Button("Revert"))
83+
if (GUILayout.Button("Undo"))
8884
{
8985
RevertDecimation();
9086
}
9187

92-
if (GUILayout.Button("Revert to Original"))
88+
if (GUILayout.Button("Reset To Original Mesh"))
9389
{
9490
RevertToOriginalMesh();
9591
}
@@ -101,15 +97,41 @@ private void OnGUI()
10197
private void ApplyDecimation()
10298
{
10399
bool isSkinnedMeshRenderer = selectedGameObject.GetComponent<SkinnedMeshRenderer>() != null;
100+
int boneCount = 0;
101+
102+
if (isSkinnedMeshRenderer)
103+
{
104+
SkinnedMeshRenderer skinnedMeshRenderer = selectedGameObject.GetComponent<SkinnedMeshRenderer>();
105+
boneCount = skinnedMeshRenderer.bones.Length;
106+
}
104107

105-
EnableReadWrite(decimatedMesh);
106-
MeshDecimaterUtility.DecimateMesh(originalMesh, decimatedMesh, decimateLevel, isSkinnedMeshRenderer, originalSubmeshCount);
108+
EnableReadWrite(originalMesh);
109+
110+
// save "level" to history
111+
MeshRevertManager.PushDecimateLevel(originalMesh, decimateLevel);
112+
113+
MeshDecimaterUtility.DecimateMesh(originalMesh, decimatedMesh, decimateLevel, isSkinnedMeshRenderer, originalSubmeshCount, boneCount);
114+
115+
decimatedMesh.RecalculateNormals();
116+
decimatedMesh.RecalculateBounds();
107117

108118
SaveDecimatedMesh();
109119

110120
MeshRevertManager.StoreOriginalMesh(decimatedMesh, originalMesh);
111121

112-
MeshRevertManager.StoreDecimateLevel(decimatedMesh, decimateLevel);
122+
EditorApplication.delayCall += () =>
123+
{
124+
ApplyMeshToRenderer(isSkinnedMeshRenderer);
125+
};
126+
127+
meshPreviewer.UpdatePreviewMesh(selectedGameObject);
128+
129+
isFirstDecimation = false;
130+
}
131+
132+
private void ApplyMeshToRenderer(bool isSkinnedMeshRenderer)
133+
{
134+
if (selectedGameObject == null) return;
113135

114136
if (selectedGameObject.GetComponent<MeshFilter>() != null)
115137
{
@@ -121,43 +143,71 @@ private void ApplyDecimation()
121143
else if (isSkinnedMeshRenderer)
122144
{
123145
SkinnedMeshRenderer skinnedMeshRenderer = selectedGameObject.GetComponent<SkinnedMeshRenderer>();
146+
147+
skinnedMeshRenderer.sharedMesh = null;
148+
124149
skinnedMeshRenderer.sharedMesh = decimatedMesh;
125150
skinnedMeshRenderer.sharedMaterials = originalMaterials;
151+
152+
skinnedMeshRenderer.updateWhenOffscreen = true;
153+
154+
Animator animator = selectedGameObject.GetComponent<Animator>();
155+
if (animator != null)
156+
{
157+
animator.Rebind();
158+
}
159+
160+
ValidateBoneWeights(skinnedMeshRenderer);
126161
}
162+
}
127163

128-
meshPreviewer.UpdatePreviewMesh(selectedGameObject);
164+
private void ValidateBoneWeights(SkinnedMeshRenderer skinnedMeshRenderer)
165+
{
166+
Mesh mesh = skinnedMeshRenderer.sharedMesh;
167+
int boneCount = skinnedMeshRenderer.bones.Length;
129168

130-
// errorめんどいの
131-
if (isFirstDecimation)
169+
for (int i = 0; i < mesh.boneWeights.Length; i++)
132170
{
133-
isFirstDecimation = false;
134-
Debug.LogWarning("First decimation performed. Applying decimation again to prevent mesh data mismatch error.");
135-
ApplyDecimation();
171+
BoneWeight bw = mesh.boneWeights[i];
172+
if (bw.boneIndex0 >= boneCount || bw.boneIndex1 >= boneCount || bw.boneIndex2 >= boneCount || bw.boneIndex3 >= boneCount)
173+
{
174+
Debug.LogError($"Invalid bone index detected in boneWeights at vertex {i}: boneIndex0={bw.boneIndex0}, boneIndex1={bw.boneIndex1}, boneIndex2={bw.boneIndex2}, boneIndex3={bw.boneIndex3}");
175+
}
136176
}
137177
}
138178

139179
private void RevertDecimation()
140180
{
141-
if (selectedGameObject.GetComponent<MeshFilter>() != null)
181+
if (originalMesh == null)
142182
{
143-
MeshFilter meshFilter = selectedGameObject.GetComponent<MeshFilter>();
144-
meshFilter.sharedMesh = originalMesh;
145-
MeshRenderer meshRenderer = selectedGameObject.GetComponent<MeshRenderer>();
146-
meshRenderer.sharedMaterials = originalMaterials;
183+
Debug.LogWarning("Original mesh not found.");
184+
return;
147185
}
148-
else if (selectedGameObject.GetComponent<SkinnedMeshRenderer>() != null)
186+
187+
float? previousDecimateLevel = MeshRevertManager.RevertDecimateLevel(originalMesh);
188+
if (previousDecimateLevel.HasValue)
149189
{
150-
SkinnedMeshRenderer skinnedMeshRenderer = selectedGameObject.GetComponent<SkinnedMeshRenderer>();
151-
skinnedMeshRenderer.sharedMesh = originalMesh;
152-
skinnedMeshRenderer.sharedMaterials = originalMaterials;
153-
}
190+
decimateLevel = previousDecimateLevel.Value;
191+
MeshRevertManager.PushDecimateLevel(originalMesh, decimateLevel);
154192

155-
decimateLevel = DEFAULT_DECIMATE_LEVEL;
156-
MeshRevertManager.StoreDecimateLevel(originalMesh, decimateLevel);
193+
ApplyDecimation();
157194

158-
meshPreviewer.UpdatePreviewMesh(selectedGameObject);
195+
Debug.Log($"Reverted to previous decimate level: {decimateLevel}");
196+
}
197+
else
198+
{
199+
if (decimateLevel == DEFAULT_DECIMATE_LEVEL)
200+
{
201+
EditorUtility.DisplayDialog("Revert Failed", "Not able to revert. Already at the default decimate level.", "OK");
202+
}
203+
else
204+
{
205+
EditorUtility.DisplayDialog("Revert Failed", "Nothing to revert.", "OK");
206+
}
207+
Debug.LogWarning("Revert failed: No previous decimate level available.");
208+
}
159209

160-
isFirstDecimation = true;
210+
meshPreviewer.UpdatePreviewMesh(selectedGameObject);
161211
}
162212

163213
private void RevertToOriginalMesh()
@@ -188,15 +238,15 @@ private void RevertToOriginalMesh()
188238
Debug.Log("Reverted to original mesh.");
189239

190240
decimateLevel = DEFAULT_DECIMATE_LEVEL;
191-
MeshRevertManager.StoreDecimateLevel(originalMeshFromManager, decimateLevel);
241+
MeshRevertManager.PushDecimateLevel(originalMeshFromManager, decimateLevel);
192242
meshInfoDisplay.SetOriginalMesh(originalMeshFromManager);
193243
}
194244
else
195245
{
196246
Debug.LogWarning("Original mesh not found.");
197247

198248
decimateLevel = DEFAULT_DECIMATE_LEVEL;
199-
MeshRevertManager.StoreDecimateLevel(currentMesh, decimateLevel);
249+
MeshRevertManager.PushDecimateLevel(currentMesh, decimateLevel);
200250
meshInfoDisplay.SetOriginalMesh(currentMesh);
201251
}
202252

@@ -219,18 +269,34 @@ private void UpdateSelection(GameObject newSelectedGameObject)
219269

220270
if (newSelectedGameObject != null)
221271
{
222-
MeshFilter meshFilter = newSelectedGameObject.GetComponent<MeshFilter>();
223-
SkinnedMeshRenderer skinnedMeshRenderer = newSelectedGameObject.GetComponent<SkinnedMeshRenderer>();
224-
225-
if (meshFilter != null)
272+
Mesh original = GetOriginalMesh(newSelectedGameObject);
273+
if (original != null)
226274
{
227275
selectedGameObject = newSelectedGameObject;
228-
originalMesh = meshFilter.sharedMesh;
276+
originalMesh = original;
229277
EnableReadWrite(originalMesh);
230278

231279
decimateLevel = MeshRevertManager.GetDecimateLevel(originalMesh);
232280

233-
decimatedMesh = Instantiate(originalMesh);
281+
string actualMeshName = GetActualMeshName();
282+
string originalPath = AssetDatabase.GetAssetPath(originalMesh);
283+
string directory = Path.GetDirectoryName(originalPath);
284+
string newFileName = $"{actualMeshName}{MESH_SUFFIX}.asset";
285+
string newPath = $"{directory}/{newFileName}";
286+
287+
Mesh existingDecimatedMesh = AssetDatabase.LoadAssetAtPath<Mesh>(newPath);
288+
if (existingDecimatedMesh != null)
289+
{
290+
decimatedMesh = existingDecimatedMesh;
291+
}
292+
else
293+
{
294+
decimatedMesh = new Mesh();
295+
decimatedMesh.name = $"{actualMeshName}{MESH_SUFFIX}";
296+
AssetDatabase.CreateAsset(decimatedMesh, newPath);
297+
AssetDatabase.SaveAssets();
298+
}
299+
234300
meshInfoDisplay.SetOriginalMesh(originalMesh);
235301

236302
Renderer renderer = newSelectedGameObject.GetComponent<Renderer>();
@@ -245,29 +311,36 @@ private void UpdateSelection(GameObject newSelectedGameObject)
245311
Debug.Log($"Selected Mesh: {AssetDatabase.GetAssetPath(originalMesh)}");
246312
Repaint();
247313
}
248-
else if (skinnedMeshRenderer != null)
249-
{
250-
selectedGameObject = newSelectedGameObject;
251-
originalMesh = skinnedMeshRenderer.sharedMesh;
252-
EnableReadWrite(originalMesh);
253-
254-
decimateLevel = MeshRevertManager.GetDecimateLevel(originalMesh);
255-
256-
decimatedMesh = Instantiate(originalMesh);
257-
meshInfoDisplay.SetOriginalMesh(originalMesh);
314+
}
315+
}
258316

259-
originalMaterials = skinnedMeshRenderer.sharedMaterials;
260-
originalSubmeshCount = new int[originalMesh.subMeshCount];
261-
for (int i = 0; i < originalMesh.subMeshCount; i++)
262-
{
263-
originalSubmeshCount[i] = originalMesh.GetTriangles(i).Length / 3;
264-
}
317+
private Mesh GetOriginalMesh(GameObject gameObject)
318+
{
319+
MeshFilter meshFilter = gameObject.GetComponent<MeshFilter>();
320+
if (meshFilter != null && meshFilter.sharedMesh != null)
321+
{
322+
Mesh mesh = meshFilter.sharedMesh;
323+
if (mesh.name.EndsWith(MESH_SUFFIX))
324+
{
325+
Mesh original = MeshRevertManager.GetOriginalMesh(mesh);
326+
return original != null ? original : mesh;
327+
}
328+
return mesh;
329+
}
265330

266-
Selection.activeObject = originalMesh;
267-
Debug.Log($"Selected Mesh: {AssetDatabase.GetAssetPath(originalMesh)}");
268-
Repaint();
331+
SkinnedMeshRenderer skinnedMeshRenderer = gameObject.GetComponent<SkinnedMeshRenderer>();
332+
if (skinnedMeshRenderer != null && skinnedMeshRenderer.sharedMesh != null)
333+
{
334+
Mesh mesh = skinnedMeshRenderer.sharedMesh;
335+
if (mesh.name.EndsWith(MESH_SUFFIX))
336+
{
337+
Mesh original = MeshRevertManager.GetOriginalMesh(mesh);
338+
return original != null ? original : mesh;
269339
}
340+
return mesh;
270341
}
342+
343+
return null;
271344
}
272345

273346
private void SaveDecimatedMesh()
@@ -277,7 +350,13 @@ private void SaveDecimatedMesh()
277350
string originalPath = AssetDatabase.GetAssetPath(originalMesh);
278351
string directory = Path.GetDirectoryName(originalPath);
279352
string newFileName = $"{actualMeshName}{MESH_SUFFIX}.asset";
280-
string newPath = Path.Combine(directory, newFileName);
353+
354+
if (actualMeshName.EndsWith(MESH_SUFFIX))
355+
{
356+
newFileName = $"{RemoveDecimatedSuffix(actualMeshName)}{MESH_SUFFIX}.asset";
357+
}
358+
359+
string newPath = $"{directory}/{newFileName}";
281360

282361
Mesh existingMesh = AssetDatabase.LoadAssetAtPath<Mesh>(newPath);
283362
if (existingMesh != null)
@@ -288,6 +367,7 @@ private void SaveDecimatedMesh()
288367
}
289368
else
290369
{
370+
decimatedMesh.name = $"{RemoveDecimatedSuffix(actualMeshName)}{MESH_SUFFIX}";
291371
AssetDatabase.CreateAsset(decimatedMesh, newPath);
292372
AssetDatabase.SaveAssets();
293373
Debug.Log($"Decimated mesh saved: {newPath}");
@@ -303,18 +383,42 @@ private string GetActualMeshName()
303383
MeshFilter meshFilter = selectedGameObject.GetComponent<MeshFilter>();
304384
if (meshFilter != null && meshFilter.sharedMesh != null)
305385
{
306-
return meshFilter.sharedMesh.name;
386+
return RemoveCloneAndDecimatedSuffix(meshFilter.sharedMesh.name);
307387
}
308388

309389
SkinnedMeshRenderer skinnedMeshRenderer = selectedGameObject.GetComponent<SkinnedMeshRenderer>();
310390
if (skinnedMeshRenderer != null && skinnedMeshRenderer.sharedMesh != null)
311391
{
312-
return skinnedMeshRenderer.sharedMesh.name;
392+
return RemoveCloneAndDecimatedSuffix(skinnedMeshRenderer.sharedMesh.name);
313393
}
314394

315395
return "Unknown";
316396
}
317397

398+
private string RemoveCloneAndDecimatedSuffix(string meshName)
399+
{
400+
// erase "(Clone)"
401+
if (meshName.EndsWith("(Clone)"))
402+
{
403+
meshName = meshName.Substring(0, meshName.Length - "(Clone)".Length);
404+
}
405+
// erase "_decimated"
406+
if (meshName.EndsWith(MESH_SUFFIX))
407+
{
408+
meshName = meshName.Substring(0, meshName.Length - MESH_SUFFIX.Length);
409+
}
410+
return meshName;
411+
}
412+
413+
private string RemoveDecimatedSuffix(string meshName)
414+
{
415+
if (meshName.EndsWith(MESH_SUFFIX))
416+
{
417+
return meshName.Substring(0, meshName.Length - MESH_SUFFIX.Length);
418+
}
419+
return meshName;
420+
}
421+
318422
private Mesh GetCurrentMesh()
319423
{
320424
if (selectedGameObject != null)
@@ -339,8 +443,11 @@ private void EnableReadWrite(Mesh mesh)
339443
ModelImporter modelImporter = AssetImporter.GetAtPath(path) as ModelImporter;
340444
if (modelImporter != null)
341445
{
342-
modelImporter.isReadable = true;
343-
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
446+
if (!modelImporter.isReadable)
447+
{
448+
modelImporter.isReadable = true;
449+
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
450+
}
344451
}
345452
}
346453

0 commit comments

Comments
 (0)