mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-06-26 11:24:46 +00:00
214 lines
7.1 KiB
C#
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);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
} |