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

218 lines
9.2 KiB
C#

#if UNITY_EDITOR && !FUNCELL_LAUNCHER
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;
using UnityEngine;
using System;
using System.Text;
namespace Thousandto.Launcher.ExternalLibs
{
public class GrassCombine
{
//private const string ScenePath = "GameAssets/ExportResources/Scene";
//private const string AssetPath = "Assets/GameAssets/ExportResources/scene/{0}/";
//private const string FilePath = "GameAssets/ExportResources/scene/{0}";
#region//const
//子节点数量的警告值
public const int CN_MAX_CHILD_COUNT_WANNING = 100;
//-----------------------------//
//总的顶点数量警告阀值
public const int CN_MAX_VERTEX_COUNT_WANNING = 4096;
#endregion
public static void CombineScene(string sceneName, string sPath, string aPath, string fPath)
{
DirectoryInfo directory = new DirectoryInfo(Application.dataPath + "/" + sPath);
if (directory == null)
return;
string sceneFullPath = string.Format(directory.FullName + "\\{0}.unity", sceneName);
string assetPath = string.Format(aPath, sceneName);
string filePath = string.Format(fPath, sceneName);
filePath = Application.dataPath + "/" + filePath;
Scene scene = EditorSceneManager.OpenScene(sceneFullPath, OpenSceneMode.Single);
GameObject root = GameObject.Find("SceneRoot");
if (root == null)
return;
Transform rootTrans = root.transform;
Transform grass = null;
for(int i = 0;i < rootTrans.childCount;i++)
{
var ch = rootTrans.GetChild(i);
if(ch.name.ToLower().Trim() == "grass")
{
grass = ch;
break;
}
}
if (grass == null)
return;
if (!Directory.Exists(filePath))
Directory.CreateDirectory(filePath);
for (int m = 0; m < grass.childCount; m++)
{
Transform child = grass.GetChild(m);
if (child == null)
continue;
Mesh ms = Combine(child, assetPath, filePath);
}
//string savePath = Path.Combine(assetPath, "Mesh_ScriptTable_Object_" + name + ".asset");
EditorSceneManager.SaveScene(scene);
}
private static Mesh Combine(Transform region, string assetpath, string filePath)
{
var info = MeshCombine.CreateMeshCombineInfo(region);
if (info != null)
{
List<Vector3> vList = new List<Vector3>();
List<ChildMeshDataScript> scriptList = new List<ChildMeshDataScript>();
GrassRelationScript relationScript = Thousandto.Core.Base.UnityUtils.RequireComponent<GrassRelationScript>(region.gameObject);
for (int i = 0; i < region.childCount; i++)
{
var tran = region.GetChild(i);
if (tran == null)
continue;
MeshFilter childMf = tran.GetComponent<MeshFilter>();
MeshRenderer rd = tran.GetComponent<MeshRenderer>();
if (childMf == null || rd == null)
{
UnityEngine.Debug.LogError("Grass已经合并过了");
return null;
}
int starIndex = vList.Count;
ChildMeshDataScript script = Thousandto.Core.Base.UnityUtils.RequireComponent<ChildMeshDataScript>(tran.gameObject);
if (script == null)
continue;
script.ChildMeshInfo = new RuntimeChildMesh(tran, rd.lightmapIndex, rd.lightmapScaleOffset, childMf.sharedMesh.colors);
script.ChildMeshInfo.NewVertices = new Vector3[childMf.sharedMesh.vertices.Length];
//计算顶点
for (int m = 0; m < childMf.sharedMesh.vertices.Length; m++)
{
//先把顶点转换为世界坐标
var wp = tran.localToWorldMatrix.MultiplyPoint3x4(childMf.sharedMesh.vertices[m]);
//再把顶点转换为本地坐标
var p = region.worldToLocalMatrix.MultiplyPoint3x4(wp);
vList.Add(p);
script.ChildMeshInfo.NewVertices[m] = p;
script.ChildMeshInfo.StartIndex = starIndex;
}
scriptList.Add(script);
AddColliderBox(tran.gameObject);
SetMeshRenderer(rd);
info.AddChild(tran);
}
if (scriptList.Count == CN_MAX_CHILD_COUNT_WANNING + 1)
{
Debug.LogError("RuntimeMesh Has Too Much Child Count! More then " + CN_MAX_CHILD_COUNT_WANNING);
}
relationScript.AddRelationScript(scriptList);
info.Build();
var mf = Thousandto.Core.Base.UnityUtils.RequireComponent<MeshFilter>(region.gameObject);
var render = Thousandto.Core.Base.UnityUtils.RequireComponent<MeshRenderer>(region.gameObject);
render.sharedMaterial = info.Material;
render.lightmapIndex = info.LightmapIndex;
render.lightmapScaleOffset = new Vector4(1, 1, 0, 0);
string result = SaveMeshForAsset(info.NewMesh, region.name, assetpath, filePath);
mf.sharedMesh = LoadCombineAsset(result);
relationScript.InitCombineInfo();
return info.NewMesh;
}
else
{
Debug.LogError("MeshCombineScript: not found renderer child. ");
}
return null;
}
private static string SaveMeshForObj(string name, Vector3[] tVertices, Vector2[] tUV, int[] tPolys, string path)
{
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
string savePath = Path.Combine(path, name + ".obj");
StreamWriter sw = new StreamWriter(savePath);
try
{
sw.WriteLine("# T4M File");
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
for (int i = 0; i < tVertices.Length; i++)
{
//UpdateProgress();
StringBuilder sb = new StringBuilder("v ", tVertices.Length);
sb.Append(tVertices[i].x.ToString()).Append(" ").
Append(tVertices[i].y.ToString()).Append(" ").
Append(tVertices[i].z.ToString());
sw.WriteLine(sb);
}
for (int i = 0; i < tUV.Length; i++)
{
//UpdateProgress();
StringBuilder sb = new StringBuilder("vt ", tUV.Length);
sb.Append(tUV[i].x.ToString()).Append(" ").
Append(tUV[i].y.ToString());
sw.WriteLine(sb);
}
for (int i = 0; i < tPolys.Length; i += 3)
{
//UpdateProgress();
StringBuilder sb = new StringBuilder("f ", tPolys.Length);
sb.Append(tPolys[i] + 1).Append("/").Append(tPolys[i] + 1).Append(" ").
Append(tPolys[i + 1] + 1).Append("/").Append(tPolys[i + 1] + 1).Append(" ").
Append(tPolys[i + 2] + 1).Append("/").Append(tPolys[i + 2] + 1);
sw.WriteLine(sb);
}
}
catch (Exception err)
{
Debug.Log("Error saving file: " + err.Message);
}
sw.Close();
AssetDatabase.SaveAssets();
return savePath;
}
private static string SaveMeshForAsset(Mesh ms, string name, string assetpath, string filepath)
{
if (ms == null)
return string.Empty;
string savePath = Path.Combine(assetpath, name + ".asset");
string path = assetpath + name;
if (File.Exists(path))
File.Delete(path);
AssetDatabase.CreateAsset(ms, savePath);
return savePath;
}
private static Mesh LoadCombineAsset(string path)
{
Mesh ms = AssetDatabase.LoadAssetAtPath(path, typeof(Mesh)) as Mesh;
return ms;
}
private static void AddColliderBox(GameObject go)
{
if (go == null)
return;
var collider = Thousandto.Core.Base.UnityUtils.RequireComponent<BoxCollider>(go);
collider.size = new Vector3(collider.size.x, collider.size.y, 0.2f);
collider.isTrigger = true;
}
private static void SetMeshRenderer(MeshRenderer render)
{
if (render != null) render.enabled = false;
}
}
}
#endif