Net.Like.Xue.Tokyo/Packages-Local/Net.BITKit.Bounds.Unity/CovertMeshColliderToModel.cs

183 lines
5.8 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.IO;
using GK;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
namespace Net.Project.B.Bounds
{
public class UnityMeshColliderCovertExplorer
{
[MenuItem("Tools/Export GameObjects to Convex Mesh")]
private static void ExportConvex()
{
var go = Selection.activeGameObject;
if (!go)
{
Debug.LogError("No object selected");
return;
}
var nonConvexMesh = GetMesh(go);
var hullCalculator = new ConvexHullCalculator();
var allVertices = new List<Vector3>();
var allTriangles = new List<int>();
var allNormals = new List<Vector3>();
var vertices = new List<Vector3>();
nonConvexMesh.GetVertices(vertices);
hullCalculator.GenerateHull(vertices, true, ref allVertices, ref allTriangles,
ref allNormals);
var newMesh = new Mesh();
newMesh.SetVertices(allVertices);
newMesh.SetTriangles(allTriangles, 0);
newMesh.SetNormals(allNormals);
var newGo = new GameObject("Combined Mesh");
newGo.AddComponent<MeshFilter>().mesh = newMesh;
newGo.AddComponent<MeshRenderer>();
}
[MenuItem("Tools/Export GameObjects to Non Convex Mesh")]
private static void ExportNonConvex()
{
var go = Selection.activeGameObject;
if (!go)
{
Debug.LogError("No object selected");
return;
}
var newMesh = GetMesh(go);
var newGo = new GameObject("Combined Mesh");
newGo.AddComponent<MeshFilter>().mesh = newMesh;
newGo.AddComponent<MeshRenderer>();
}
private static Mesh GetMesh(GameObject go)
{
var hullCalculator = new ConvexHullCalculator();
var combineInstances = new List<CombineInstance>();
foreach (var collider in go.GetComponentsInChildren<Collider>())
{
switch (collider)
{
case BoxCollider boxCollider:
{
var mesh = CreateBoxMesh(boxCollider);
combineInstances.Add(new CombineInstance()
{
mesh = mesh,
transform = collider.transform.localToWorldMatrix
});
}
break;
case MeshCollider meshCollider:
{
var allVertices = new List<Vector3>();
var allTriangles = new List<int>();
var allNormals = new List<Vector3>();
var mesh = meshCollider.sharedMesh;
var vertices = new List<Vector3>();
for (var index = 0; index < vertices.Count; index++)
{
var vertex = vertices[index];
vertex = meshCollider.transform.TransformPoint(vertex);
vertices[index] = vertex;
}
mesh.GetVertices(vertices);
hullCalculator.GenerateHull(vertices, true, ref allVertices, ref allTriangles,
ref allNormals);
mesh = new Mesh
{
indexFormat = IndexFormat.UInt32
};
mesh.SetVertices(allVertices);
mesh.SetTriangles(allTriangles, 0);
mesh.SetNormals(allNormals);
combineInstances.Add(new CombineInstance()
{
mesh = mesh,
transform = meshCollider.transform.localToWorldMatrix
});
}
break;
}
}
var newMesh = new Mesh();
newMesh.CombineMeshes(combineInstances.ToArray());
return newMesh;
}
private static Mesh CreateBoxMesh(BoxCollider box)
{
var size = box.size;
var center = box.center;
var mesh = new Mesh();
Vector3[] vertices = {
// Bottom
new Vector3(-1, -1, -1),
new Vector3( 1, -1, -1),
new Vector3( 1, -1, 1),
new Vector3(-1, -1, 1),
// Top
new Vector3(-1, 1, -1),
new Vector3( 1, 1, -1),
new Vector3( 1, 1, 1),
new Vector3(-1, 1, 1),
};
int[] triangles = {
// Bottom
0, 2, 1, 0, 3, 2,
// Top
4, 5, 6, 4, 6, 7,
// Front
0, 1, 5, 0, 5, 4,
// Back
2, 3, 7, 2, 7, 6,
// Left
3, 0, 4, 3, 4, 7,
// Right
1, 2, 6, 1, 6, 5,
};
// Scale and offset vertices according to size and center
for (int i = 0; i < vertices.Length; i++)
{
vertices[i] = Vector3.Scale(vertices[i], size * 0.5f) + center;
}
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
mesh.RecalculateBounds();
return mesh;
}
}
}