JisolGame/JNFrame2/Assets/JNGame/Map/DotRecast/DotRecastController.cs
PC-20230316NUNE\Administrator 894100ae37 提交Unity 联机Pro
2024-08-17 14:27:18 +08:00

214 lines
7.1 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using DotRecast.Core.Numerics;
using DotRecast.Detour;
using DotRecast.Recast.Geom;
using DotRecast.Recast.Toolset;
using DotRecast.Recast.Toolset.Builder;
using JNGame.Map.DotRecast.Util;
using JNGame.Math;
using UnityEngine;
using UnityEngine.AI;
namespace JNGame.Map.DotRecast
{
public class DotRecastController : MonoBehaviour
{
public LayerMask layerMask;
private Mesh debugMesh;
private DtNavMesh dtNavMesh;
private List<Mesh> debugPathMeshs;
public void Save()
{
if (debugMesh is null)
{
Debug.Log("[DotRecast] 未生成地形 请生成地形.");
return;
}
var data = new MeshData(debugMesh);
File.WriteAllText(UnityEngine.Application.dataPath + "/Resources/map1.json", JsonUtility.ToJson(data));
Debug.Log("[DotRecast] 保存成功.");
}
public void Load()
{
debugMesh = this.Merge();
var data = new MeshData(debugMesh);
var vertices = new LFloat[data.vertices.Length * 3];
for (int i = 0; i < data.vertices.Length; ++i)
{
vertices[i * 3 + 0] = (LFloat)data.vertices[i].x;
vertices[i * 3 + 1] = (LFloat)data.vertices[i].y;
vertices[i * 3 + 2] = (LFloat)data.vertices[i].z;
}
var bmin = RcVecUtils.Create(vertices);
var bmax = RcVecUtils.Create(vertices);
for (int i = 1; i < vertices.Length / 3; i++)
{
bmin = RcVecUtils.Min(bmin, vertices, i * 3);
bmax = RcVecUtils.Max(bmax, vertices, i * 3);
}
var geom = new DefaultInputGeomProvider(vertices,data.triangles);
var builder = new TileNavMeshBuilder();
var settings = new RcNavMeshBuildSettings();
settings.cellSize = (LFloat)1f;
var result = builder.Build(geom, settings);
dtNavMesh = result.NavMesh;
debugPathMeshs = new List<Mesh>();
for (int i = 0; i < dtNavMesh.GetMaxTiles(); ++i)
{
DtMeshTile tile = dtNavMesh.GetTile(i);
if (tile != null && tile.data != null)
{
DrawMeshTile(tile);
}
}
Debug.Log("[DotRecast] 加载完成.");
}
private void DrawMeshTile(DtMeshTile tile)
{
List<Vector3> vertices = new List<Vector3>();
//Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < tile.data.header.polyCount; ++i)
{
DtPoly p = tile.data.polys[i];
if (p.GetPolyType() == DtPolyTypes.DT_POLYTYPE_OFFMESH_CONNECTION)
{
continue;
}
if (tile.data.detailMeshes != null)
{
DtPolyDetail pd = tile.data.detailMeshes[i];
for (int j = 0; j < pd.triCount; ++j)
{
int t = (pd.triBase + j) * 4;
for (int k = 0; k < 3; ++k)
{
int v = tile.data.detailTris[t + k];
if (v < p.vertCount)
{
vertices.Add(new Vector3(tile.data.verts[p.verts[v] * 3], tile.data.verts[p.verts[v] * 3 + 1] + 0.1f,
tile.data.verts[p.verts[v] * 3 + 2]));
}
else
{
vertices.Add(new Vector3(tile.data.detailVerts[(pd.vertBase + v - p.vertCount) * 3],
tile.data.detailVerts[(pd.vertBase + v - p.vertCount) * 3 + 1],
tile.data.detailVerts[(pd.vertBase + v - p.vertCount) * 3 + 2]));
}
}
}
}
}
List<Vector3[]> vertices3 = new List<Vector3[]>();
for (int i = 0; i < vertices.Count; i += 3)
{
vertices3.Add(new []{vertices[i], vertices[i + 1], vertices[i + 2]});
}
int triCount = vertices3.Count;
Vector3[] verts = new Vector3[3 * triCount];
int[] tris = new int[3* triCount];
Color[] colors = new Color[3*triCount];
for (int i=0;i<triCount;++i){
int v = i*3;
for (int j=0;j<3;++j){
verts[v+j] = vertices3[i][j];
tris[v+j] = v+j;
colors[v+j] = Color.white;
}
}
Mesh mesh1 = new Mesh();
mesh1.vertices = verts;
mesh1.triangles = tris;
mesh1.colors = colors;
mesh1.RecalculateNormals();
debugPathMeshs.Add(mesh1);
}
private Mesh Merge()
{
//获取所有子物体的网格过滤器组件
MeshFilter[] meshFilters = FindObjectsOfType<MeshFilter>(true).Where(mf => ((1 << mf.gameObject.layer) & layerMask) > 0).ToArray();
//创建一个新的合并后的网格
Mesh mergedMesh = new Mesh();
//创建一个合并用的网格数组
CombineInstance[] combine = new CombineInstance[meshFilters.Length+1];
for (int i = 0; i < meshFilters.Length; i++)
{
//设置合并用的网格数组
combine[i].mesh = meshFilters[i].sharedMesh;
combine[i].transform = meshFilters[i].transform.localToWorldMatrix;
}
var triangulation = NavMesh.CalculateTriangulation();
combine[^1].mesh = new Mesh()
{
vertices = triangulation.vertices,
triangles = triangulation.indices,
};
combine[^1].transform = Matrix4x4.identity;
//合并网格
mergedMesh.CombineMeshes(combine);
mergedMesh.RecalculateNormals();
mergedMesh.RecalculateBounds();
debugPathMeshs = null;
return mergedMesh;
}
public void OnDrawGizmos()
{
// if (debugMesh is not null)
// {
// Gizmos.color = new Color(0f, 1f, 1f, 0.5f);
// Gizmos.DrawMesh(debugMesh);
// Gizmos.color = new Color(0f, 0f, 0f, 0.3f);
// Gizmos.DrawWireMesh(debugMesh);
// }
//
// return;
if (debugPathMeshs is not null)
{
foreach (var mesh in debugPathMeshs)
{
Gizmos.color = new Color(0f, 1f, 1f, 0.5f);
Gizmos.DrawMesh(mesh);
}
}
}
}
}