MeshEditor.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEditor;
  5. public class MeshEditor : EditorWindow
  6. {
  7. private GameObject m_combineGoRoot;
  8. private bool m_click;
  9. [MenuItem("MyEditor/Combine Mesh")]
  10. static void ShowEditor()
  11. {
  12. MeshEditor combinewindow = GetWindow<MeshEditor>();
  13. combinewindow.minSize = new Vector2(700, 500);
  14. }
  15. private void OnGUI()
  16. {
  17. this.DrawWindow();
  18. if (m_click)
  19. {
  20. this.m_click = false;
  21. if (m_combineGoRoot == null)
  22. {
  23. Debug.LogError("要合并的父物体 m_combineGoRoot 不能为空 ");
  24. return;
  25. }
  26. //要合并的网格
  27. MeshFilter[] filters = m_combineGoRoot.GetComponentsInChildren<MeshFilter>();
  28. //网格合并实例
  29. CombineInstance[] combines = new CombineInstance[filters.Length];
  30. Debug.Log(" MeshFilter count " + filters.Length);
  31. //
  32. MeshRenderer[] renders = m_combineGoRoot.GetComponentsInChildren<MeshRenderer>();
  33. Debug.Log(" MeshRenderer count " + filters.Length);
  34. //存储不同的材质
  35. HashSet<Material> materialsHash = new HashSet<Material>();
  36. //存储所有要合并的贴图
  37. Texture2D[] textures = new Texture2D[filters.Length];
  38. //存储模型的uv
  39. List<Vector2[]> uvlist = new List<Vector2[]>();
  40. int uvcount = 0;
  41. for (int i = 0; i < filters.Length; i++)
  42. {
  43. combines[i].mesh = filters[i].sharedMesh;//使用编辑器执行只能使用sharemesh
  44. ///网格坐标转换
  45. combines[i].transform = m_combineGoRoot.transform.worldToLocalMatrix * filters[i].transform.localToWorldMatrix;
  46. if (!materialsHash.Contains(renders[i].material)) materialsHash.Add(renders[i].material);
  47. uvlist.Add(filters[i].sharedMesh.uv);
  48. uvcount += filters[i].sharedMesh.uv.Length;
  49. ///注意要获取的贴图所对应的属性 _BaseMap 是我当前shader中的贴图属性
  50. textures[i] = renders[i].sharedMaterial.GetTexture("_BaseMap") as Texture2D;
  51. filters[i].gameObject.SetActive(false);
  52. }
  53. //存储材质
  54. Material[] materials = new Material[materialsHash.Count];
  55. int index = 0;
  56. foreach (var mat in materialsHash)
  57. {
  58. materials[index] = mat;
  59. index++;
  60. }
  61. ///合并贴图
  62. Texture2D combinetext = new Texture2D(1024, 1024);
  63. //存放每张贴图在新贴图中所占的比例 模型uv比例为 0~1
  64. Rect[] rects = combinetext.PackTextures(textures, 0);
  65. Debug.Log(rects[0].xMax);
  66. Vector2[] uvs = new Vector2[uvcount];
  67. int j = 0;
  68. //遍历 rects rects 的数量就是filters 的数量
  69. for (int i = 0; i < filters.Length; i++)
  70. {
  71. //遍历物体uv 未合并之前的uv
  72. foreach (Vector2 uv in uvlist[i])
  73. {
  74. //对新的uv进行插值计算
  75. uvs[j].x = Mathf.Lerp(rects[i].xMin, rects[i].xMax, uv.x);
  76. uvs[j].y = Mathf.Lerp(rects[i].yMin, rects[i].yMax, uv.y);
  77. j++;
  78. }
  79. }
  80. #region
  81. Material newmat = new Material(materials[0]);
  82. newmat.CopyPropertiesFromMaterial(materials[0]);
  83. //设置材质贴图 注意材质贴图属性名称
  84. newmat.SetTexture("_BaseMap", combinetext);
  85. newmat.name = "combineMat";
  86. #endregion
  87. //给父物体添加网格组件
  88. MeshFilter filter = m_combineGoRoot.AddComponent<MeshFilter>();
  89. MeshRenderer renderer = m_combineGoRoot.AddComponent<MeshRenderer>();
  90. Mesh newmesh = new Mesh();
  91. filter.sharedMesh = newmesh;
  92. ///合并刚才的所有mesh
  93. filter.sharedMesh.CombineMeshes(combines);
  94. filter.sharedMesh.uv = uvs;
  95. m_combineGoRoot.SetActive(true);
  96. }
  97. }
  98. /// <summary>
  99. /// 绘制窗口
  100. /// </summary>
  101. private void DrawWindow()
  102. {
  103. BeginWindows();
  104. EditorGUILayout.LabelField("合并网格根节点:");
  105. m_combineGoRoot = (GameObject)EditorGUILayout.ObjectField(m_combineGoRoot, typeof(GameObject), true);
  106. this.m_click = GUILayout.Button("Combine");
  107. EndWindows();
  108. }
  109. }