Files
JJBB/Assets/Project/Script/Common/Utilities/Editor/ExtractSceneMesh.cs
2024-08-23 15:49:34 +08:00

165 lines
7.1 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Module.Log;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;
public class ExtractSceneMesh
{
[MenuItem("Scene/Extract SceneMesh Combined")]
public static void Extract()
{
if (EditorUtility.DisplayDialog("导出场景模型", "将场景的所有物体导出为合并模型?", "确认", "取消"))
{
var vertices = new List<Vector3>();
var uv = new List<Vector2>();
var normal = new List<Vector3>();
var triangles = new List<int>();
var meshFilters = Object.FindObjectsOfType<MeshFilter>();
for (var i = 0; i < meshFilters.Length; i++)
{
var filter = meshFilters[i];
if (!filter.gameObject.activeInHierarchy)
{
}
else if (filter.sharedMesh == null)
{
LogModule.ErrorLog("Filter has no mesh " + filter.transform.GetHierarchyName());
}
else if (!filter.sharedMesh.isReadable)
{
LogModule.WarningLog("Mesh isn't readable " + filter.sharedMesh.name);
}
else
{
var start = vertices.Count;
var trs = Matrix4x4.TRS(filter.transform.position, filter.transform.rotation,
filter.transform.localScale);
var meshVertices = filter.sharedMesh.vertices;
var meshUv = filter.sharedMesh.uv;
var meshNormal = filter.sharedMesh.normals;
var subMeshCount = filter.sharedMesh.subMeshCount;
for (var j = 0; j < meshVertices.Length; j++)
vertices.Add(trs.MultiplyPoint3x4(meshVertices[j]));
for (var j = 0; j < meshNormal.Length; j++)
normal.Add(filter.transform.rotation * meshNormal[j]);
for (var j = 0; j < meshUv.Length; j++)
uv.Add(meshUv[j]);
for (var k = 0; k < subMeshCount; k++)
{
var meshTriangle = filter.sharedMesh.GetTriangles(k);
for (var j = 0; j < meshTriangle.Length; j++)
triangles.Add(meshTriangle[j] + start);
}
}
}
//
// var mesh = new Mesh();
// mesh.SetVertices(vertices);
// mesh.SetNormals(normal);
// mesh.SetUVs(0, uv);
// mesh.SetTriangles(triangles, 0);
// LogModule.WarningLog("V Count " + vertices.Count);
// var meshObj = new GameObject("Mesh");
// var meshFilter = meshObj.AddComponent<MeshFilter>();
// meshFilter.sharedMesh = mesh;
// meshObj.AddComponent<MeshRenderer>();
//ObjExtractHelp.DoExport(mesh);
var sceneName = SceneManager.GetActiveScene().name;
if (string.IsNullOrEmpty(sceneName))
sceneName = "NewScene";
var path = Application.dataPath + "/_Test/SceneMesh";
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
path += "/" + sceneName + "SceneMesh.obj";
ObjExtract(vertices, uv, normal, triangles, path);
AssetDatabase.Refresh();
LogModule.WarningLog("Mesh Exported at " + path);
}
}
public static void ObjExtract(IList<Vector3> vertices, IList<Vector2> uv, IList<Vector3> normal, IList<int> triangleList, string path)
{
var builder = new StringBuilder();
var sceneName = Path.GetFileNameWithoutExtension(path);
builder.Append("#" + sceneName + ".obj"
+ "\n#" + DateTime.Now.ToLongDateString()
+ "\n#" + DateTime.Now.ToLongTimeString()
+ "\n#-------"
+ "\n\n");
builder.Append("g ").Append(sceneName).Append("\n");
builder.Append("#").Append(sceneName).Append("\n#-------").Append("\n");
foreach (var v in vertices)
builder.Append(string.Format("v {0} {1} {2}\n", -v.x, v.y, v.z));
builder.Append("\n");
foreach (var v in normal)
builder.Append(string.Format("vn {0} {1} {2}\n", -v.x, v.y, v.z));
builder.Append("\n");
foreach (var v in uv)
builder.Append(string.Format("vt {0} {1}\n", v.x, v.y));
builder.Append("\n");
builder.Append("usemtl ").Append("Dummy").Append("\n");
builder.Append("usemap ").Append("Dummy").Append("\n");
var triangles = triangleList;
for (var i = 0; i < triangles.Count; i += 3)
builder.Append(string.Format("f {0}/{0}/{0} {2}/{2}/{2} {1}/{1}/{1}\n",
triangles[i] + 1, triangles[i + 1] + 1, triangles[i + 2] + 1));
File.WriteAllText(path, builder.ToString());
}
//
// public static void MeshToString(StringBuilder builder, Mesh m)
// {
// foreach (var v in m.vertices)
// builder.Append(string.Format("v {0} {1} {2}\n", -v.x, v.y, v.z));
// builder.Append("\n");
// foreach (var v in m.normals)
// builder.Append(string.Format("vn {0} {1} {2}\n", -v.x, v.y, v.z));
// builder.Append("\n");
// foreach (var v in m.uv)
// builder.Append(string.Format("vt {0} {1}\n", v.x, v.y));
// builder.Append("\n");
// builder.Append("usemtl ").Append("Dummy").Append("\n");
// builder.Append("usemap ").Append("Dummy").Append("\n");
// var triangles = m.triangles;
// for (var i = 0; i < triangles.Length; i += 3)
// builder.Append(string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n",
// triangles[i] + 1, triangles[i + 1] + 1, triangles[i + 2] + 1));
// }
}
//
//public static class ObjExtractScript
//{
//
//}
//
//public static class ObjExtractHelp
//{
// public static void DoExport(Mesh mesh)
// {
// var builder = new StringBuilder();
// var sceneName = SceneManager.GetActiveScene().name;
// if (string.IsNullOrEmpty(sceneName))
// sceneName = "NewScene";
// builder.Append("#" + sceneName + ".obj"
// + "\n#" + DateTime.Now.ToLongDateString()
// + "\n#" + DateTime.Now.ToLongTimeString()
// + "\n#-------"
// + "\n\n");
// builder.Append("g ").Append(sceneName).Append("\n");
// builder.Append("#").Append(sceneName).Append("\n#-------").Append("\n");
// ObjExtractScript.MeshToString(builder, mesh);
// var path = Application.dataPath + "/_Test/SceneMesh";
// if (!Directory.Exists(path))
// Directory.CreateDirectory(path);
// path += "/" + sceneName + "SceneMesh.obj";
// File.WriteAllText(path, builder.ToString());
// AssetDatabase.Refresh();
// LogModule.WarningLog("Mesh Exported at " + path);
// }
//}