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

196 lines
7.1 KiB
C#

#if UNITY_EDITOR && !FUNCELL_LAUNCHER
using System.Collections.Generic;
using UnityEngine;
namespace Thousandto.Launcher.ExternalLibs
{
/// <summary>
/// 网格组合的类
/// </summary>
public class MeshCombine
{
//子节点数量的警告值
public const int CN_MAX_CHILD_COUNT_WANNING = 100;
//总的顶点数量警告阀值
public const int CN_MAX_VERTEX_COUNT_WANNING = 4096;
//所在的transform
public Transform Transform { get; private set; }
//能被组合的材质信息
public Material Material { get; private set; }
//litmap所在的索引
public int LightmapIndex { get; private set; }
//能被组合的子信息
public List<ChildMesh> ChildList { get; private set; }
//-----------------------------//
//生成的新的网格
public Mesh NewMesh { get; private set; }
//生成的心的顶点
public Vector3[] NewVertices { get; private set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="tran">当前节点的Transform</param>
/// <param name="mat">所有合并的子对象的材质</param>
public MeshCombine(Transform tran, Material mat,int litmapIndex)
{
LightmapIndex = litmapIndex;
Transform = tran;
Material = mat;
ChildList = new List<ChildMesh>();
}
/// <summary>
/// //添加子节点
/// </summary>
/// <param name="tran"></param>
/// <returns>如果添加成功就返回true</returns>
public ChildMesh AddChild(Transform tran)
{
var mf = tran.GetComponent<MeshFilter>();
var render = tran.GetComponent<MeshRenderer>();
if (mf != null && render != null)
{
var mat = render.sharedMaterial;
var mesh = mf.sharedMesh;
if (mat == Material && mesh != null)
{
if (mesh.isReadable)
{
var child = new ChildMesh(tran, mesh,render);
ChildList.Add(child);
#if UNITY_EDITOR
if (ChildList.Count == CN_MAX_CHILD_COUNT_WANNING + 1)
{
Debug.LogError("RuntimeMesh Has Too Much Child Count! More then "+ CN_MAX_CHILD_COUNT_WANNING);
}
UnityEngine.Object.DestroyImmediate((tran.gameObject.GetComponent<MeshFilter>()));
UnityEngine.Object.DestroyImmediate((tran.gameObject.GetComponent<MeshRenderer>()));
#endif
return child;
}
#if UNITY_EDITOR
else
{
Debug.LogError("Mesh is not readable!" + tran.name);
}
#endif
}
}
return null;
}
//创建Mesh
public void Build()
{
List<Vector3> vList = new List<Vector3>();
List<int> idxList = new List<int>();
List<Color> cList = new List<Color>();
List<Vector2> uvList = new List<Vector2>();
List<Vector2> uv1List = new List<Vector2>();
List<Vector2> uv2List = new List<Vector2>();
var allChild = ChildList;
//判断是否处理
bool doUV2 = LightmapIndex >= 0;
for (int i = 0; i < allChild.Count; i++)
{
var subMesh = allChild[i].Mesh;
var vert = subMesh.vertices;
var idx = subMesh.GetIndices(0);
var cls = subMesh.colors;
var uvs = subMesh.uv;
var uv1s = subMesh.uv2;
if (doUV2)
{
if (uv1s.Length == 0)
{
uv1s = new Vector2[uvs.Length];
for (int v = 0; v < uv1s.Length; v++) { uv1s[v] = uvs[v]; }
}
if (allChild[i].LightmapIndex != LightmapIndex)
{
Debug.LogError("Lightmap索引不同.");
}
else
{
var ltinfo = allChild[i].LightmapScaleOffset;
var scale = new Vector2(ltinfo.x, ltinfo.y);
var offset = new Vector2(ltinfo.z, ltinfo.w);
for (int v = 0; v < uv1s.Length; v++)
{
uv1s[v].x = uv1s[v].x * scale.x;
uv1s[v].y = uv1s[v].y * scale.y;
uv1s[v] = offset + uv1s[v];
}
}
}
allChild[i].NewVertices = new Vector3[vert.Length];
allChild[i].StartIndex = vList.Count;
//重新计算索引
for (int j = 0; j < idx.Length; j++)
{
idx[j] += vList.Count;
}
//计算顶点
for (int m = 0; m < vert.Length; m++)
{
//先把顶点转换为世界坐标
var wp = allChild[i].Transform.localToWorldMatrix.MultiplyPoint3x4(vert[m]);
//再把顶点转换为本地坐标
var p = Transform.worldToLocalMatrix.MultiplyPoint3x4(wp);
vList.Add(p);
allChild[i].NewVertices[m] = p;
}
idxList.AddRange(idx);
cList.AddRange(cls);
uvList.AddRange(uvs);
uv1List.AddRange(uv1s);
}
//生成新的网格
NewVertices = vList.ToArray();
var finalMesh = new Mesh();
finalMesh.MarkDynamic();
finalMesh.name = Transform.name + "_" + Material.name + "_" + LightmapIndex;
finalMesh.vertices = NewVertices;
finalMesh.SetIndices(idxList.ToArray(), MeshTopology.Triangles, 0);
finalMesh.colors = cList.ToArray();
finalMesh.uv = uvList.ToArray();
finalMesh.uv2 = uv1List.ToArray();
finalMesh.RecalculateBounds();
finalMesh.RecalculateNormals();
NewMesh = finalMesh;
if (NewVertices.Length > CN_MAX_VERTEX_COUNT_WANNING)
{
UnityEngine.Debug.LogError("New RuntimeMesh Has Too Much Vertex Count! " + NewVertices.Length);
}
}
//创建一个网格组合信息
public static MeshCombine CreateMeshCombineInfo(Transform current)
{
for (int i = 0; i < current.childCount; i++)
{
var tran = current.GetChild(i);
var render = tran.GetComponent<MeshRenderer>();
if (render != null && render.sharedMaterial != null)
{
return new MeshCombine(current, render.sharedMaterial,render.lightmapIndex);
}
}
return null;
}
}
}
#endif