From e3452bfda81803b5a950808974483109034f37c1 Mon Sep 17 00:00:00 2001 From: Albert Date: Tue, 29 May 2018 23:14:47 +0300 Subject: [PATCH 1/3] Added SkinnedMeshRendererCombiner --- .../Editor/SkinnedMeshRendererCombiner.cs | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 SimplestMeshBaker/Editor/SkinnedMeshRendererCombiner.cs diff --git a/SimplestMeshBaker/Editor/SkinnedMeshRendererCombiner.cs b/SimplestMeshBaker/Editor/SkinnedMeshRendererCombiner.cs new file mode 100644 index 0000000..8e4d566 --- /dev/null +++ b/SimplestMeshBaker/Editor/SkinnedMeshRendererCombiner.cs @@ -0,0 +1,143 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using UnityEditor; + +namespace SimplestMeshBaker +{ + //Code based on this topic: + //https://answers.unity.com/questions/625243/combining-skinned-meshes-1.html + public class SkinnedMeshRendererCombiner : MonoBehaviour + { + [MenuItem("GameObject/Combine SkinnedMeshRenderers", false, 0)] + private static void Bake(MenuCommand menuCommand) + { + if (Selection.gameObjects.Length != 1) + { + EditorUtility.DisplayDialog("Simplest Mesh Baker", "You should select one game object.", "Ok"); + return; + } + + GameObject go = Selection.gameObjects[0]; + if (go.GetComponent() != null) + { + EditorUtility.DisplayDialog("Simplest Mesh Baker", + "You should select game object with SkinnedMeshRenderer on the children, not on the current game object.", + "Ok"); + return; + } + + Vector3 startPosition = go.transform.position; + Vector3 startScale = go.transform.localScale; + Quaternion startRotation = go.transform.rotation; + + go.transform.position = Vector3.zero; + go.transform.localScale = Vector3.one; + go.transform.rotation = Quaternion.identity; + + SkinnedMeshRenderer[] skinnedMeshRenderers = go.GetComponentsInChildren(); + Dictionary> skinnedMeshRenderer = SeparateRenderers(skinnedMeshRenderers); + + foreach (var renderers in skinnedMeshRenderer) + { + Process(renderers.Value, go); + } + + go.transform.position = startPosition; + go.transform.localScale = startScale; + go.transform.rotation = startRotation; + } + + private static Dictionary> SeparateRenderers( + SkinnedMeshRenderer[] skinnedMeshRenderers) + { + Dictionary> result = new Dictionary>(); + foreach (var skinnedMeshRenderer in skinnedMeshRenderers) + { + if (!result.ContainsKey(skinnedMeshRenderer.sharedMaterial.name)) + { + result.Add(skinnedMeshRenderer.sharedMaterial.name, new List()); + } + result[skinnedMeshRenderer.sharedMaterial.name].Add(skinnedMeshRenderer); + } + return result; + } + + private static void Process(List skinnedMeshRenderers, GameObject root) + { + List toDestroy = new List(); + + List bones = new List(); + Hashtable bonesByHash = new Hashtable(); + List boneWeights = new List(); + + List combineInstances = new List(); + int boneIndex = 0; +// List bindposes = new List(); + + Material material = skinnedMeshRenderers[0].sharedMaterial; + foreach (var skinnedMeshRenderer in skinnedMeshRenderers) + { + skinnedMeshRenderer.transform.rotation = Quaternion.identity; + foreach (Transform bone in skinnedMeshRenderer.bones) + { + bones.Add(bone); +// bindposes.Add(bone.worldToLocalMatrix * root.transform.worldToLocalMatrix); + if (!bonesByHash.Contains(bone.name)) + { + bonesByHash.Add(bone.name, boneIndex); + } + boneIndex++; + } + FillData(skinnedMeshRenderer, bonesByHash, boneWeights, combineInstances); + toDestroy.Add(skinnedMeshRenderer); + } + + SkinnedMeshRenderer newRenderer = Undo.AddComponent(root); + if (newRenderer == null) + { + var newObject = new GameObject(); + Undo.RegisterCreatedObjectUndo(newObject, "New Skinned Mesh Renderer object"); + newObject.transform.SetParent(root.transform); + newRenderer = newObject.AddComponent(); + } + newRenderer.sharedMesh = new Mesh(); + newRenderer.sharedMesh.CombineMeshes(combineInstances.ToArray()); + + newRenderer.bones = bones.ToArray(); + newRenderer.sharedMesh.boneWeights = boneWeights.ToArray(); +// newRenderer.sharedMesh.bindposes = bindposes.ToArray(); + newRenderer.sharedMesh.RecalculateBounds(); + newRenderer.sharedMaterial = material; + + foreach (SkinnedMeshRenderer renderer in toDestroy) + { + Undo.DestroyObjectImmediate(renderer.gameObject); + } + } + + private static void FillData(SkinnedMeshRenderer skinnedMeshRenderer, Hashtable boneHash, + List boneWeights, List combineInstances) + { + BoneWeight[] meshBoneWeight = skinnedMeshRenderer.sharedMesh.boneWeights; + + foreach (BoneWeight weight in meshBoneWeight) + { + BoneWeight boneWeight = weight; + + boneWeight.boneIndex0 = (int) boneHash[skinnedMeshRenderer.bones[weight.boneIndex0].name]; + boneWeight.boneIndex1 = (int) boneHash[skinnedMeshRenderer.bones[weight.boneIndex1].name]; + boneWeight.boneIndex2 = (int) boneHash[skinnedMeshRenderer.bones[weight.boneIndex2].name]; + boneWeight.boneIndex3 = (int) boneHash[skinnedMeshRenderer.bones[weight.boneIndex3].name]; + + boneWeights.Add(boneWeight); + } + + CombineInstance combineInstance = new CombineInstance(); + combineInstance.mesh = skinnedMeshRenderer.sharedMesh; + + combineInstance.transform = skinnedMeshRenderer.transform.localToWorldMatrix; + combineInstances.Add(combineInstance); + } + } +} \ No newline at end of file From c017a989a68e3a8544529ef298fd689907de59a2 Mon Sep 17 00:00:00 2001 From: Albert Date: Wed, 30 May 2018 11:28:47 +0300 Subject: [PATCH 2/3] Updated class --- SimplestMeshBaker/Editor/SkinnedMeshRendererCombiner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SimplestMeshBaker/Editor/SkinnedMeshRendererCombiner.cs b/SimplestMeshBaker/Editor/SkinnedMeshRendererCombiner.cs index 8e4d566..73ef0b1 100644 --- a/SimplestMeshBaker/Editor/SkinnedMeshRendererCombiner.cs +++ b/SimplestMeshBaker/Editor/SkinnedMeshRendererCombiner.cs @@ -7,7 +7,7 @@ namespace SimplestMeshBaker { //Code based on this topic: //https://answers.unity.com/questions/625243/combining-skinned-meshes-1.html - public class SkinnedMeshRendererCombiner : MonoBehaviour + public static class SkinnedMeshRendererCombiner { [MenuItem("GameObject/Combine SkinnedMeshRenderers", false, 0)] private static void Bake(MenuCommand menuCommand) From eb2dd35b3e23fa388cea3941600fee2fc19c330d Mon Sep 17 00:00:00 2001 From: Albert Date: Sat, 28 Jul 2018 12:36:06 +0300 Subject: [PATCH 3/3] Fixed baking one object several times --- SimplestMeshBaker/Editor/MeshBaker.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/SimplestMeshBaker/Editor/MeshBaker.cs b/SimplestMeshBaker/Editor/MeshBaker.cs index 383f277..16acb08 100644 --- a/SimplestMeshBaker/Editor/MeshBaker.cs +++ b/SimplestMeshBaker/Editor/MeshBaker.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; @@ -26,6 +27,7 @@ enum Resolving [MenuItem("GameObject/Bake Meshes", false, 0)] private static void BakeMeshes(MenuCommand menuCommand) { + if (Selection.objects.Length == 0) { return; @@ -131,11 +133,13 @@ private static void BakeMeshes(MenuCommand menuCommand) if (EditorUtility.DisplayDialog("Simplest Mesh Baker", "Do you want to remove sources?", "Yes", "No")) { + HashSet gos = new HashSet(); foreach (GameObject selected in Selection.gameObjects) { - if (selected != null) + if (selected != null && !gos.Contains(selected)) { Undo.DestroyObjectImmediate(selected); + gos.Add(selected); } } }