forked from mirror/DotRecast
for unity3d
This commit is contained in:
parent
cfe8378f1d
commit
17891c2d43
|
@ -1,97 +0,0 @@
|
||||||
using DotRecast.Detour;
|
|
||||||
using DotRecast.Recast.Demo.Geom;
|
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Builder;
|
|
||||||
|
|
||||||
public abstract class AbstractNavMeshBuilder
|
|
||||||
{
|
|
||||||
protected NavMeshDataCreateParams GetNavMeshCreateParams(DemoInputGeomProvider m_geom, float m_cellSize,
|
|
||||||
float m_cellHeight, float m_agentHeight, float m_agentRadius, float m_agentMaxClimb,
|
|
||||||
RecastBuilderResult rcResult)
|
|
||||||
{
|
|
||||||
PolyMesh m_pmesh = rcResult.GetMesh();
|
|
||||||
PolyMeshDetail m_dmesh = rcResult.GetMeshDetail();
|
|
||||||
NavMeshDataCreateParams option = new NavMeshDataCreateParams();
|
|
||||||
for (int i = 0; i < m_pmesh.npolys; ++i)
|
|
||||||
{
|
|
||||||
m_pmesh.flags[i] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
option.verts = m_pmesh.verts;
|
|
||||||
option.vertCount = m_pmesh.nverts;
|
|
||||||
option.polys = m_pmesh.polys;
|
|
||||||
option.polyAreas = m_pmesh.areas;
|
|
||||||
option.polyFlags = m_pmesh.flags;
|
|
||||||
option.polyCount = m_pmesh.npolys;
|
|
||||||
option.nvp = m_pmesh.nvp;
|
|
||||||
if (m_dmesh != null)
|
|
||||||
{
|
|
||||||
option.detailMeshes = m_dmesh.meshes;
|
|
||||||
option.detailVerts = m_dmesh.verts;
|
|
||||||
option.detailVertsCount = m_dmesh.nverts;
|
|
||||||
option.detailTris = m_dmesh.tris;
|
|
||||||
option.detailTriCount = m_dmesh.ntris;
|
|
||||||
}
|
|
||||||
|
|
||||||
option.walkableHeight = m_agentHeight;
|
|
||||||
option.walkableRadius = m_agentRadius;
|
|
||||||
option.walkableClimb = m_agentMaxClimb;
|
|
||||||
option.bmin = m_pmesh.bmin;
|
|
||||||
option.bmax = m_pmesh.bmax;
|
|
||||||
option.cs = m_cellSize;
|
|
||||||
option.ch = m_cellHeight;
|
|
||||||
option.buildBvTree = true;
|
|
||||||
|
|
||||||
option.offMeshConCount = m_geom.GetOffMeshConnections().Count;
|
|
||||||
option.offMeshConVerts = new float[option.offMeshConCount * 6];
|
|
||||||
option.offMeshConRad = new float[option.offMeshConCount];
|
|
||||||
option.offMeshConDir = new int[option.offMeshConCount];
|
|
||||||
option.offMeshConAreas = new int[option.offMeshConCount];
|
|
||||||
option.offMeshConFlags = new int[option.offMeshConCount];
|
|
||||||
option.offMeshConUserID = new int[option.offMeshConCount];
|
|
||||||
for (int i = 0; i < option.offMeshConCount; i++)
|
|
||||||
{
|
|
||||||
DemoOffMeshConnection offMeshCon = m_geom.GetOffMeshConnections()[i];
|
|
||||||
for (int j = 0; j < 6; j++)
|
|
||||||
{
|
|
||||||
option.offMeshConVerts[6 * i + j] = offMeshCon.verts[j];
|
|
||||||
}
|
|
||||||
|
|
||||||
option.offMeshConRad[i] = offMeshCon.radius;
|
|
||||||
option.offMeshConDir[i] = offMeshCon.bidir ? 1 : 0;
|
|
||||||
option.offMeshConAreas[i] = offMeshCon.area;
|
|
||||||
option.offMeshConFlags[i] = offMeshCon.flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
return option;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MeshData UpdateAreaAndFlags(MeshData meshData)
|
|
||||||
{
|
|
||||||
// Update poly flags from areas.
|
|
||||||
for (int i = 0; i < meshData.polys.Length; ++i)
|
|
||||||
{
|
|
||||||
if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WALKABLE)
|
|
||||||
{
|
|
||||||
meshData.polys[i].SetArea(SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND
|
|
||||||
|| meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GRASS
|
|
||||||
|| meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD)
|
|
||||||
{
|
|
||||||
meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_WALK;
|
|
||||||
}
|
|
||||||
else if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER)
|
|
||||||
{
|
|
||||||
meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_SWIM;
|
|
||||||
}
|
|
||||||
else if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_DOOR)
|
|
||||||
{
|
|
||||||
meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_DOOR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return meshData;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any damages
|
|
||||||
arising from the use of this software.
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it
|
|
||||||
freely, subject to the following restrictions:
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
|
||||||
claim that you wrote the original software. If you use this software
|
|
||||||
in a product, an acknowledgment in the product documentation would be
|
|
||||||
appreciated but is not required.
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
misrepresented as being the original software.
|
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System.Collections.Immutable;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Builder;
|
|
||||||
|
|
||||||
public class SampleAreaModifications
|
|
||||||
{
|
|
||||||
public const int SAMPLE_POLYAREA_TYPE_GROUND = 0x0;
|
|
||||||
public const int SAMPLE_POLYAREA_TYPE_WATER = 0x1;
|
|
||||||
public const int SAMPLE_POLYAREA_TYPE_ROAD = 0x2;
|
|
||||||
public const int SAMPLE_POLYAREA_TYPE_DOOR = 0x3;
|
|
||||||
public const int SAMPLE_POLYAREA_TYPE_GRASS = 0x4;
|
|
||||||
public const int SAMPLE_POLYAREA_TYPE_JUMP = 0x5;
|
|
||||||
public const int SAMPLE_POLYAREA_TYPE_JUMP_AUTO = 0x6;
|
|
||||||
public const int SAMPLE_POLYAREA_TYPE_WALKABLE = 0x3f;
|
|
||||||
|
|
||||||
public static readonly AreaModification SAMPLE_AREAMOD_WALKABLE = new(SAMPLE_POLYAREA_TYPE_WALKABLE);
|
|
||||||
public static readonly AreaModification SAMPLE_AREAMOD_GROUND = new(SAMPLE_POLYAREA_TYPE_GROUND);
|
|
||||||
public static readonly AreaModification SAMPLE_AREAMOD_WATER = new(SAMPLE_POLYAREA_TYPE_WATER);
|
|
||||||
public static readonly AreaModification SAMPLE_AREAMOD_ROAD = new(SAMPLE_POLYAREA_TYPE_ROAD);
|
|
||||||
public static readonly AreaModification SAMPLE_AREAMOD_GRASS = new(SAMPLE_POLYAREA_TYPE_GRASS);
|
|
||||||
public static readonly AreaModification SAMPLE_AREAMOD_DOOR = new(SAMPLE_POLYAREA_TYPE_DOOR);
|
|
||||||
public static readonly AreaModification SAMPLE_AREAMOD_JUMP = new(SAMPLE_POLYAREA_TYPE_JUMP);
|
|
||||||
|
|
||||||
public static readonly ImmutableArray<AreaModification> Values = ImmutableArray.Create(
|
|
||||||
SAMPLE_AREAMOD_WALKABLE,
|
|
||||||
SAMPLE_AREAMOD_GROUND,
|
|
||||||
SAMPLE_AREAMOD_WATER,
|
|
||||||
SAMPLE_AREAMOD_ROAD,
|
|
||||||
SAMPLE_AREAMOD_GRASS,
|
|
||||||
SAMPLE_AREAMOD_DOOR,
|
|
||||||
SAMPLE_AREAMOD_JUMP
|
|
||||||
);
|
|
||||||
|
|
||||||
public static AreaModification OfValue(int value)
|
|
||||||
{
|
|
||||||
return Values.FirstOrDefault(x => x.Value == value, SAMPLE_AREAMOD_GRASS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly int SAMPLE_POLYFLAGS_WALK = 0x01; // Ability to walk (ground, grass, road)
|
|
||||||
public static readonly int SAMPLE_POLYFLAGS_SWIM = 0x02; // Ability to swim (water).
|
|
||||||
public static readonly int SAMPLE_POLYFLAGS_DOOR = 0x04; // Ability to move through doors.
|
|
||||||
public static readonly int SAMPLE_POLYFLAGS_JUMP = 0x08; // Ability to jump.
|
|
||||||
public static readonly int SAMPLE_POLYFLAGS_DISABLED = 0x10; // Disabled polygon
|
|
||||||
public static readonly int SAMPLE_POLYFLAGS_ALL = 0xffff; // All abilities.
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any damages
|
|
||||||
arising from the use of this software.
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it
|
|
||||||
freely, subject to the following restrictions:
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
|
||||||
claim that you wrote the original software. If you use this software
|
|
||||||
in a product, an acknowledgment in the product documentation would be
|
|
||||||
appreciated but is not required.
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
misrepresented as being the original software.
|
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Immutable;
|
|
||||||
using DotRecast.Detour;
|
|
||||||
using DotRecast.Recast.Demo.Geom;
|
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Builder;
|
|
||||||
|
|
||||||
public class SoloNavMeshBuilder : AbstractNavMeshBuilder
|
|
||||||
{
|
|
||||||
public Tuple<IList<RecastBuilderResult>, NavMesh> Build(DemoInputGeomProvider geom, PartitionType partitionType,
|
|
||||||
float cellSize, float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb,
|
|
||||||
float agentMaxSlope, int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError,
|
|
||||||
int vertsPerPoly, float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles,
|
|
||||||
bool filterLedgeSpans, bool filterWalkableLowHeightSpans)
|
|
||||||
{
|
|
||||||
RecastBuilderResult rcResult = BuildRecastResult(geom, partitionType, cellSize, cellHeight, agentHeight,
|
|
||||||
agentRadius, agentMaxClimb, agentMaxSlope, regionMinSize, regionMergeSize, edgeMaxLen, edgeMaxError,
|
|
||||||
vertsPerPoly, detailSampleDist, detailSampleMaxError, filterLowHangingObstacles, filterLedgeSpans,
|
|
||||||
filterWalkableLowHeightSpans);
|
|
||||||
return Tuple.Create(ImmutableArray.Create(rcResult) as IList<RecastBuilderResult>,
|
|
||||||
BuildNavMesh(
|
|
||||||
BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, rcResult),
|
|
||||||
vertsPerPoly));
|
|
||||||
}
|
|
||||||
|
|
||||||
private NavMesh BuildNavMesh(MeshData meshData, int vertsPerPoly)
|
|
||||||
{
|
|
||||||
return new NavMesh(meshData, vertsPerPoly, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RecastBuilderResult BuildRecastResult(DemoInputGeomProvider geom, PartitionType partitionType, float cellSize,
|
|
||||||
float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb, float agentMaxSlope,
|
|
||||||
int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError, int vertsPerPoly,
|
|
||||||
float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles, bool filterLedgeSpans,
|
|
||||||
bool filterWalkableLowHeightSpans)
|
|
||||||
{
|
|
||||||
RecastConfig cfg = new RecastConfig(partitionType, cellSize, cellHeight, agentMaxSlope, filterLowHangingObstacles,
|
|
||||||
filterLedgeSpans, filterWalkableLowHeightSpans, agentHeight, agentRadius, agentMaxClimb, regionMinSize,
|
|
||||||
regionMergeSize, edgeMaxLen, edgeMaxError, vertsPerPoly, detailSampleDist, detailSampleMaxError,
|
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true);
|
|
||||||
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
|
|
||||||
RecastBuilder rcBuilder = new RecastBuilder();
|
|
||||||
return rcBuilder.Build(geom, bcfg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private MeshData BuildMeshData(DemoInputGeomProvider geom, float cellSize, float cellHeight, float agentHeight,
|
|
||||||
float agentRadius, float agentMaxClimb, RecastBuilderResult result)
|
|
||||||
{
|
|
||||||
NavMeshDataCreateParams option = GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight, agentRadius,
|
|
||||||
agentMaxClimb, result);
|
|
||||||
return UpdateAreaAndFlags(NavMeshBuilder.CreateNavMeshData(option));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,137 +0,0 @@
|
||||||
/*
|
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any damages
|
|
||||||
arising from the use of this software.
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it
|
|
||||||
freely, subject to the following restrictions:
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
|
||||||
claim that you wrote the original software. If you use this software
|
|
||||||
in a product, an acknowledgment in the product documentation would be
|
|
||||||
appreciated but is not required.
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
misrepresented as being the original software.
|
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using DotRecast.Core;
|
|
||||||
using DotRecast.Detour;
|
|
||||||
using DotRecast.Recast.Demo.Geom;
|
|
||||||
using static DotRecast.Core.RcMath;
|
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Builder;
|
|
||||||
|
|
||||||
public class TileNavMeshBuilder : AbstractNavMeshBuilder
|
|
||||||
{
|
|
||||||
public TileNavMeshBuilder()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public Tuple<IList<RecastBuilderResult>, NavMesh> Build(DemoInputGeomProvider geom, PartitionType partitionType,
|
|
||||||
float cellSize, float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb,
|
|
||||||
float agentMaxSlope, int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError,
|
|
||||||
int vertsPerPoly, float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles,
|
|
||||||
bool filterLedgeSpans, bool filterWalkableLowHeightSpans, int tileSize)
|
|
||||||
{
|
|
||||||
List<RecastBuilderResult> rcResult = BuildRecastResult(geom, partitionType, cellSize, cellHeight, agentHeight,
|
|
||||||
agentRadius, agentMaxClimb, agentMaxSlope, regionMinSize, regionMergeSize, edgeMaxLen, edgeMaxError,
|
|
||||||
vertsPerPoly, detailSampleDist, detailSampleMaxError, filterLowHangingObstacles, filterLedgeSpans,
|
|
||||||
filterWalkableLowHeightSpans, tileSize);
|
|
||||||
return Tuple.Create((IList<RecastBuilderResult>)rcResult,
|
|
||||||
BuildNavMesh(geom,
|
|
||||||
BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, rcResult),
|
|
||||||
cellSize, tileSize, vertsPerPoly));
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<RecastBuilderResult> BuildRecastResult(DemoInputGeomProvider geom, PartitionType partitionType,
|
|
||||||
float cellSize, float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb,
|
|
||||||
float agentMaxSlope, int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError,
|
|
||||||
int vertsPerPoly, float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles,
|
|
||||||
bool filterLedgeSpans, bool filterWalkableLowHeightSpans, int tileSize)
|
|
||||||
{
|
|
||||||
RecastConfig cfg = new RecastConfig(true, tileSize, tileSize, RecastConfig.CalcBorder(agentRadius, cellSize),
|
|
||||||
partitionType, cellSize, cellHeight, agentMaxSlope, filterLowHangingObstacles, filterLedgeSpans,
|
|
||||||
filterWalkableLowHeightSpans, agentHeight, agentRadius, agentMaxClimb,
|
|
||||||
regionMinSize * regionMinSize * cellSize * cellSize,
|
|
||||||
regionMergeSize * regionMergeSize * cellSize * cellSize, edgeMaxLen, edgeMaxError, vertsPerPoly,
|
|
||||||
true, detailSampleDist, detailSampleMaxError, SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE);
|
|
||||||
RecastBuilder rcBuilder = new RecastBuilder();
|
|
||||||
return rcBuilder.BuildTiles(geom, cfg, Task.Factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
private NavMesh BuildNavMesh(DemoInputGeomProvider geom, List<MeshData> meshData, float cellSize, int tileSize,
|
|
||||||
int vertsPerPoly)
|
|
||||||
{
|
|
||||||
NavMeshParams navMeshParams = new NavMeshParams();
|
|
||||||
navMeshParams.orig.x = geom.GetMeshBoundsMin().x;
|
|
||||||
navMeshParams.orig.y = geom.GetMeshBoundsMin().y;
|
|
||||||
navMeshParams.orig.z = geom.GetMeshBoundsMin().z;
|
|
||||||
navMeshParams.tileWidth = tileSize * cellSize;
|
|
||||||
navMeshParams.tileHeight = tileSize * cellSize;
|
|
||||||
|
|
||||||
// Snprintf(text, 64, "Tiles %d x %d", tw, th);
|
|
||||||
|
|
||||||
navMeshParams.maxTiles = GetMaxTiles(geom, cellSize, tileSize);
|
|
||||||
navMeshParams.maxPolys = GetMaxPolysPerTile(geom, cellSize, tileSize);
|
|
||||||
NavMesh navMesh = new NavMesh(navMeshParams, vertsPerPoly);
|
|
||||||
meshData.ForEach(md => navMesh.AddTile(md, 0, 0));
|
|
||||||
return navMesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetMaxTiles(DemoInputGeomProvider geom, float cellSize, int tileSize)
|
|
||||||
{
|
|
||||||
int tileBits = GetTileBits(geom, cellSize, tileSize);
|
|
||||||
return 1 << tileBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetMaxPolysPerTile(DemoInputGeomProvider geom, float cellSize, int tileSize)
|
|
||||||
{
|
|
||||||
int polyBits = 22 - GetTileBits(geom, cellSize, tileSize);
|
|
||||||
return 1 << polyBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetTileBits(DemoInputGeomProvider geom, float cellSize, int tileSize)
|
|
||||||
{
|
|
||||||
Recast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
|
|
||||||
int tw = (gw + tileSize - 1) / tileSize;
|
|
||||||
int th = (gh + tileSize - 1) / tileSize;
|
|
||||||
int tileBits = Math.Min(DetourCommon.Ilog2(DetourCommon.NextPow2(tw * th)), 14);
|
|
||||||
return tileBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int[] GetTiles(DemoInputGeomProvider geom, float cellSize, int tileSize)
|
|
||||||
{
|
|
||||||
Recast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
|
|
||||||
int tw = (gw + tileSize - 1) / tileSize;
|
|
||||||
int th = (gh + tileSize - 1) / tileSize;
|
|
||||||
return new int[] { tw, th };
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<MeshData> BuildMeshData(DemoInputGeomProvider geom, float cellSize, float cellHeight, float agentHeight,
|
|
||||||
float agentRadius, float agentMaxClimb, List<RecastBuilderResult> results)
|
|
||||||
{
|
|
||||||
// Add tiles to nav mesh
|
|
||||||
List<MeshData> meshData = new();
|
|
||||||
foreach (RecastBuilderResult result in results)
|
|
||||||
{
|
|
||||||
int x = result.tileX;
|
|
||||||
int z = result.tileZ;
|
|
||||||
NavMeshDataCreateParams option = GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight,
|
|
||||||
agentRadius, agentMaxClimb, result);
|
|
||||||
option.tileX = x;
|
|
||||||
option.tileZ = z;
|
|
||||||
MeshData md = NavMeshBuilder.CreateNavMeshData(option);
|
|
||||||
if (md != null)
|
|
||||||
{
|
|
||||||
meshData.Add(UpdateAreaAndFlags(md));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return meshData;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,7 +20,7 @@ freely, subject to the following restrictions:
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Recast.Demo.Builder;
|
using DotRecast.Recast.DemoTool.Builder;
|
||||||
using Silk.NET.OpenGL;
|
using Silk.NET.OpenGL;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Draw;
|
namespace DotRecast.Recast.Demo.Draw;
|
||||||
|
|
|
@ -21,8 +21,8 @@ freely, subject to the following restrictions:
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Detour;
|
using DotRecast.Detour;
|
||||||
using DotRecast.Recast.Demo.Builder;
|
using DotRecast.Recast.DemoTool.Builder;
|
||||||
using DotRecast.Recast.Demo.Geom;
|
using DotRecast.Recast.DemoTool.Geom;
|
||||||
using DotRecast.Recast.Demo.UI;
|
using DotRecast.Recast.Demo.UI;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Draw;
|
namespace DotRecast.Recast.Demo.Draw;
|
||||||
|
|
|
@ -24,7 +24,7 @@ using System.Numerics;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Detour;
|
using DotRecast.Detour;
|
||||||
using DotRecast.Detour.QueryResults;
|
using DotRecast.Detour.QueryResults;
|
||||||
using DotRecast.Recast.Demo.Builder;
|
using DotRecast.Recast.DemoTool.Builder;
|
||||||
using Silk.NET.OpenGL;
|
using Silk.NET.OpenGL;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Draw;
|
namespace DotRecast.Recast.Demo.Draw;
|
||||||
|
|
|
@ -1,226 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any damages
|
|
||||||
arising from the use of this software.
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it
|
|
||||||
freely, subject to the following restrictions:
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
|
||||||
claim that you wrote the original software. If you use this software
|
|
||||||
in a product, an acknowledgment in the product documentation would be
|
|
||||||
appreciated but is not required.
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
misrepresented as being the original software.
|
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Immutable;
|
|
||||||
using System.Linq;
|
|
||||||
using DotRecast.Core;
|
|
||||||
using DotRecast.Recast.Geom;
|
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Geom;
|
|
||||||
|
|
||||||
public class DemoInputGeomProvider : IInputGeomProvider
|
|
||||||
{
|
|
||||||
public readonly float[] vertices;
|
|
||||||
public readonly int[] faces;
|
|
||||||
public readonly float[] normals;
|
|
||||||
private readonly RcVec3f bmin;
|
|
||||||
private readonly RcVec3f bmax;
|
|
||||||
private readonly List<ConvexVolume> _convexVolumes = new();
|
|
||||||
private readonly List<DemoOffMeshConnection> offMeshConnections = new();
|
|
||||||
private readonly TriMesh _mesh;
|
|
||||||
|
|
||||||
public DemoInputGeomProvider(List<float> vertexPositions, List<int> meshFaces) :
|
|
||||||
this(MapVertices(vertexPositions), MapFaces(meshFaces))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int[] MapFaces(List<int> meshFaces)
|
|
||||||
{
|
|
||||||
int[] faces = new int[meshFaces.Count];
|
|
||||||
for (int i = 0; i < faces.Length; i++)
|
|
||||||
{
|
|
||||||
faces[i] = meshFaces[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return faces;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float[] MapVertices(List<float> vertexPositions)
|
|
||||||
{
|
|
||||||
float[] vertices = new float[vertexPositions.Count];
|
|
||||||
for (int i = 0; i < vertices.Length; i++)
|
|
||||||
{
|
|
||||||
vertices[i] = vertexPositions[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return vertices;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DemoInputGeomProvider(float[] vertices, int[] faces)
|
|
||||||
{
|
|
||||||
this.vertices = vertices;
|
|
||||||
this.faces = faces;
|
|
||||||
normals = new float[faces.Length];
|
|
||||||
CalculateNormals();
|
|
||||||
bmin = RcVec3f.Zero;
|
|
||||||
bmax = RcVec3f.Zero;
|
|
||||||
RcVec3f.Copy(ref bmin, vertices, 0);
|
|
||||||
RcVec3f.Copy(ref bmax, vertices, 0);
|
|
||||||
for (int i = 1; i < vertices.Length / 3; i++)
|
|
||||||
{
|
|
||||||
bmin.Min(vertices, i * 3);
|
|
||||||
bmax.Max(vertices, i * 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
_mesh = new TriMesh(vertices, faces);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RcVec3f GetMeshBoundsMin()
|
|
||||||
{
|
|
||||||
return bmin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RcVec3f GetMeshBoundsMax()
|
|
||||||
{
|
|
||||||
return bmax;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CalculateNormals()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < faces.Length; i += 3)
|
|
||||||
{
|
|
||||||
int v0 = faces[i] * 3;
|
|
||||||
int v1 = faces[i + 1] * 3;
|
|
||||||
int v2 = faces[i + 2] * 3;
|
|
||||||
RcVec3f e0 = new RcVec3f();
|
|
||||||
RcVec3f e1 = new RcVec3f();
|
|
||||||
for (int j = 0; j < 3; ++j)
|
|
||||||
{
|
|
||||||
e0[j] = vertices[v1 + j] - vertices[v0 + j];
|
|
||||||
e1[j] = vertices[v2 + j] - vertices[v0 + j];
|
|
||||||
}
|
|
||||||
|
|
||||||
normals[i] = e0.y * e1.z - e0.z * e1.y;
|
|
||||||
normals[i + 1] = e0.z * e1.x - e0.x * e1.z;
|
|
||||||
normals[i + 2] = e0.x * e1.y - e0.y * e1.x;
|
|
||||||
float d = (float)Math.Sqrt(normals[i] * normals[i] + normals[i + 1] * normals[i + 1] + normals[i + 2] * normals[i + 2]);
|
|
||||||
if (d > 0)
|
|
||||||
{
|
|
||||||
d = 1.0f / d;
|
|
||||||
normals[i] *= d;
|
|
||||||
normals[i + 1] *= d;
|
|
||||||
normals[i + 2] *= d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IList<ConvexVolume> ConvexVolumes()
|
|
||||||
{
|
|
||||||
return _convexVolumes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<TriMesh> Meshes()
|
|
||||||
{
|
|
||||||
return ImmutableArray.Create(_mesh);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DemoOffMeshConnection> GetOffMeshConnections()
|
|
||||||
{
|
|
||||||
return offMeshConnections;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddOffMeshConnection(RcVec3f start, RcVec3f end, float radius, bool bidir, int area, int flags)
|
|
||||||
{
|
|
||||||
offMeshConnections.Add(new DemoOffMeshConnection(start, end, radius, bidir, area, flags));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveOffMeshConnections(Predicate<DemoOffMeshConnection> filter)
|
|
||||||
{
|
|
||||||
//offMeshConnections.RetainAll(offMeshConnections.Stream().Filter(c -> !filter.Test(c)).Collect(ToList()));
|
|
||||||
offMeshConnections.RemoveAll(filter); // TODO : 확인 필요
|
|
||||||
}
|
|
||||||
|
|
||||||
public float? RaycastMesh(RcVec3f src, RcVec3f dst)
|
|
||||||
{
|
|
||||||
// Prune hit ray.
|
|
||||||
if (!Intersections.IsectSegAABB(src, dst, bmin, bmax, out var btmin, out var btmax))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
float[] p = new float[2];
|
|
||||||
float[] q = new float[2];
|
|
||||||
p[0] = src.x + (dst.x - src.x) * btmin;
|
|
||||||
p[1] = src.z + (dst.z - src.z) * btmin;
|
|
||||||
q[0] = src.x + (dst.x - src.x) * btmax;
|
|
||||||
q[1] = src.z + (dst.z - src.z) * btmax;
|
|
||||||
|
|
||||||
List<ChunkyTriMeshNode> chunks = _mesh.chunkyTriMesh.GetChunksOverlappingSegment(p, q);
|
|
||||||
if (0 == chunks.Count)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
float tmin = 1.0f;
|
|
||||||
bool hit = false;
|
|
||||||
foreach (ChunkyTriMeshNode chunk in chunks)
|
|
||||||
{
|
|
||||||
int[] tris = chunk.tris;
|
|
||||||
for (int j = 0; j < chunk.tris.Length; j += 3)
|
|
||||||
{
|
|
||||||
RcVec3f v1 = RcVec3f.Of(
|
|
||||||
vertices[tris[j] * 3],
|
|
||||||
vertices[tris[j] * 3 + 1],
|
|
||||||
vertices[tris[j] * 3 + 2]
|
|
||||||
);
|
|
||||||
RcVec3f v2 = RcVec3f.Of(
|
|
||||||
vertices[tris[j + 1] * 3],
|
|
||||||
vertices[tris[j + 1] * 3 + 1],
|
|
||||||
vertices[tris[j + 1] * 3 + 2]
|
|
||||||
);
|
|
||||||
RcVec3f v3 = RcVec3f.Of(
|
|
||||||
vertices[tris[j + 2] * 3],
|
|
||||||
vertices[tris[j + 2] * 3 + 1],
|
|
||||||
vertices[tris[j + 2] * 3 + 2]
|
|
||||||
);
|
|
||||||
float? t = Intersections.IntersectSegmentTriangle(src, dst, v1, v2, v3);
|
|
||||||
if (null != t)
|
|
||||||
{
|
|
||||||
if (t.Value < tmin)
|
|
||||||
{
|
|
||||||
tmin = t.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
hit = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hit ? tmin : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void AddConvexVolume(float[] verts, float minh, float maxh, AreaModification areaMod)
|
|
||||||
{
|
|
||||||
ConvexVolume volume = new ConvexVolume();
|
|
||||||
volume.verts = verts;
|
|
||||||
volume.hmin = minh;
|
|
||||||
volume.hmax = maxh;
|
|
||||||
volume.areaMod = areaMod;
|
|
||||||
_convexVolumes.Add(volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearConvexVolumes()
|
|
||||||
{
|
|
||||||
_convexVolumes.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -35,9 +35,9 @@ using DotRecast.Core;
|
||||||
using DotRecast.Detour;
|
using DotRecast.Detour;
|
||||||
using DotRecast.Detour.Extras.Unity.Astar;
|
using DotRecast.Detour.Extras.Unity.Astar;
|
||||||
using DotRecast.Detour.Io;
|
using DotRecast.Detour.Io;
|
||||||
using DotRecast.Recast.Demo.Builder;
|
using DotRecast.Recast.DemoTool.Builder;
|
||||||
using DotRecast.Recast.Demo.Draw;
|
using DotRecast.Recast.Demo.Draw;
|
||||||
using DotRecast.Recast.Demo.Geom;
|
using DotRecast.Recast.DemoTool.Geom;
|
||||||
using DotRecast.Recast.Demo.Tools;
|
using DotRecast.Recast.Demo.Tools;
|
||||||
using DotRecast.Recast.Demo.UI;
|
using DotRecast.Recast.Demo.UI;
|
||||||
using static DotRecast.Core.RcMath;
|
using static DotRecast.Core.RcMath;
|
||||||
|
@ -385,10 +385,12 @@ public class RecastDemo
|
||||||
var renderGl = _gl.GetStringS(GLEnum.Renderer);
|
var renderGl = _gl.GetStringS(GLEnum.Renderer);
|
||||||
var glslString = _gl.GetStringS(GLEnum.ShadingLanguageVersion);
|
var glslString = _gl.GetStringS(GLEnum.ShadingLanguageVersion);
|
||||||
|
|
||||||
Logger.Debug(vendor);
|
var workingDirectory = Directory.GetCurrentDirectory();
|
||||||
Logger.Debug(version);
|
Logger.Information($"working directory - {workingDirectory}");
|
||||||
Logger.Debug(renderGl);
|
Logger.Information(vendor);
|
||||||
Logger.Debug(glslString);
|
Logger.Information(version);
|
||||||
|
Logger.Information(renderGl);
|
||||||
|
Logger.Information(glslString);
|
||||||
|
|
||||||
|
|
||||||
DemoInputGeomProvider geom = LoadInputMesh(Loader.ToBytes("nav_test.obj"));
|
DemoInputGeomProvider geom = LoadInputMesh(Loader.ToBytes("nav_test.obj"));
|
||||||
|
|
|
@ -21,7 +21,7 @@ freely, subject to the following restrictions:
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Detour;
|
using DotRecast.Detour;
|
||||||
using DotRecast.Recast.Demo.Draw;
|
using DotRecast.Recast.Demo.Draw;
|
||||||
using DotRecast.Recast.Demo.Geom;
|
using DotRecast.Recast.DemoTool.Geom;
|
||||||
|
|
||||||
using DotRecast.Recast.Demo.UI;
|
using DotRecast.Recast.Demo.UI;
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Silk.NET.Windowing;
|
using Silk.NET.Windowing;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Recast.Demo.Builder;
|
using DotRecast.Recast.DemoTool.Builder;
|
||||||
using DotRecast.Recast.Demo.Draw;
|
using DotRecast.Recast.Demo.Draw;
|
||||||
using DotRecast.Recast.Demo.Geom;
|
using DotRecast.Recast.DemoTool.Geom;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using static DotRecast.Recast.Demo.Draw.DebugDraw;
|
using static DotRecast.Recast.Demo.Draw.DebugDraw;
|
||||||
using static DotRecast.Recast.Demo.Draw.DebugDrawPrimitives;
|
using static DotRecast.Recast.Demo.Draw.DebugDrawPrimitives;
|
||||||
|
|
|
@ -24,7 +24,7 @@ using DotRecast.Core;
|
||||||
using DotRecast.Detour;
|
using DotRecast.Detour;
|
||||||
using DotRecast.Detour.Crowd;
|
using DotRecast.Detour.Crowd;
|
||||||
using DotRecast.Detour.QueryResults;
|
using DotRecast.Detour.QueryResults;
|
||||||
using DotRecast.Recast.Demo.Builder;
|
using DotRecast.Recast.DemoTool.Builder;
|
||||||
using DotRecast.Recast.Demo.Draw;
|
using DotRecast.Recast.Demo.Draw;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using Silk.NET.Windowing;
|
using Silk.NET.Windowing;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -26,9 +27,9 @@ using DotRecast.Detour;
|
||||||
using DotRecast.Detour.Crowd;
|
using DotRecast.Detour.Crowd;
|
||||||
using DotRecast.Detour.Crowd.Tracking;
|
using DotRecast.Detour.Crowd.Tracking;
|
||||||
using DotRecast.Detour.QueryResults;
|
using DotRecast.Detour.QueryResults;
|
||||||
using DotRecast.Recast.Demo.Builder;
|
using DotRecast.Recast.DemoTool.Builder;
|
||||||
using DotRecast.Recast.Demo.Draw;
|
using DotRecast.Recast.Demo.Draw;
|
||||||
using DotRecast.Recast.Demo.Geom;
|
using DotRecast.Recast.DemoTool.Geom;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using static DotRecast.Recast.Demo.Draw.DebugDraw;
|
using static DotRecast.Recast.Demo.Draw.DebugDraw;
|
||||||
using static DotRecast.Recast.Demo.Draw.DebugDrawPrimitives;
|
using static DotRecast.Recast.Demo.Draw.DebugDrawPrimitives;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using DotRecast.Recast.Demo.Geom;
|
using DotRecast.Recast.DemoTool.Geom;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Tools;
|
namespace DotRecast.Recast.Demo.Tools;
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,9 @@ using DotRecast.Core;
|
||||||
using DotRecast.Detour.Dynamic;
|
using DotRecast.Detour.Dynamic;
|
||||||
using DotRecast.Detour.Dynamic.Colliders;
|
using DotRecast.Detour.Dynamic.Colliders;
|
||||||
using DotRecast.Detour.Dynamic.Io;
|
using DotRecast.Detour.Dynamic.Io;
|
||||||
using DotRecast.Recast.Demo.Builder;
|
using DotRecast.Recast.DemoTool.Builder;
|
||||||
using DotRecast.Recast.Demo.Draw;
|
using DotRecast.Recast.Demo.Draw;
|
||||||
using DotRecast.Recast.Demo.Geom;
|
using DotRecast.Recast.DemoTool.Geom;
|
||||||
using DotRecast.Recast.Demo.Tools.Gizmos;
|
using DotRecast.Recast.Demo.Tools.Gizmos;
|
||||||
using DotRecast.Recast.Demo.UI;
|
using DotRecast.Recast.Demo.UI;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
|
|
@ -21,9 +21,9 @@ using System.Linq;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using Silk.NET.Windowing;
|
using Silk.NET.Windowing;
|
||||||
using DotRecast.Detour.Extras.Jumplink;
|
using DotRecast.Detour.Extras.Jumplink;
|
||||||
using DotRecast.Recast.Demo.Builder;
|
using DotRecast.Recast.DemoTool.Builder;
|
||||||
using DotRecast.Recast.Demo.Draw;
|
using DotRecast.Recast.Demo.Draw;
|
||||||
using DotRecast.Recast.Demo.Geom;
|
using DotRecast.Recast.DemoTool.Geom;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using static DotRecast.Core.RcMath;
|
using static DotRecast.Core.RcMath;
|
||||||
using static DotRecast.Recast.Demo.Draw.DebugDraw;
|
using static DotRecast.Recast.Demo.Draw.DebugDraw;
|
||||||
|
|
|
@ -21,9 +21,9 @@ freely, subject to the following restrictions:
|
||||||
using System;
|
using System;
|
||||||
using Silk.NET.Windowing;
|
using Silk.NET.Windowing;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Recast.Demo.Builder;
|
using DotRecast.Recast.DemoTool.Builder;
|
||||||
using DotRecast.Recast.Demo.Draw;
|
using DotRecast.Recast.Demo.Draw;
|
||||||
using DotRecast.Recast.Demo.Geom;
|
using DotRecast.Recast.DemoTool.Geom;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using static DotRecast.Recast.Demo.Draw.DebugDraw;
|
using static DotRecast.Recast.Demo.Draw.DebugDraw;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Detour;
|
using DotRecast.Detour;
|
||||||
using DotRecast.Detour.QueryResults;
|
using DotRecast.Detour.QueryResults;
|
||||||
using DotRecast.Recast.Demo.Builder;
|
using DotRecast.Recast.DemoTool.Builder;
|
||||||
using DotRecast.Recast.Demo.Draw;
|
using DotRecast.Recast.Demo.Draw;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using static DotRecast.Core.RcMath;
|
using static DotRecast.Core.RcMath;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
using DotRecast.Detour;
|
||||||
|
using DotRecast.Recast.DemoTool.Geom;
|
||||||
|
|
||||||
|
namespace DotRecast.Recast.DemoTool.Builder
|
||||||
|
{
|
||||||
|
public abstract class AbstractNavMeshBuilder
|
||||||
|
{
|
||||||
|
protected NavMeshDataCreateParams GetNavMeshCreateParams(DemoInputGeomProvider m_geom, float m_cellSize,
|
||||||
|
float m_cellHeight, float m_agentHeight, float m_agentRadius, float m_agentMaxClimb,
|
||||||
|
RecastBuilderResult rcResult)
|
||||||
|
{
|
||||||
|
PolyMesh m_pmesh = rcResult.GetMesh();
|
||||||
|
PolyMeshDetail m_dmesh = rcResult.GetMeshDetail();
|
||||||
|
NavMeshDataCreateParams option = new NavMeshDataCreateParams();
|
||||||
|
for (int i = 0; i < m_pmesh.npolys; ++i)
|
||||||
|
{
|
||||||
|
m_pmesh.flags[i] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
option.verts = m_pmesh.verts;
|
||||||
|
option.vertCount = m_pmesh.nverts;
|
||||||
|
option.polys = m_pmesh.polys;
|
||||||
|
option.polyAreas = m_pmesh.areas;
|
||||||
|
option.polyFlags = m_pmesh.flags;
|
||||||
|
option.polyCount = m_pmesh.npolys;
|
||||||
|
option.nvp = m_pmesh.nvp;
|
||||||
|
if (m_dmesh != null)
|
||||||
|
{
|
||||||
|
option.detailMeshes = m_dmesh.meshes;
|
||||||
|
option.detailVerts = m_dmesh.verts;
|
||||||
|
option.detailVertsCount = m_dmesh.nverts;
|
||||||
|
option.detailTris = m_dmesh.tris;
|
||||||
|
option.detailTriCount = m_dmesh.ntris;
|
||||||
|
}
|
||||||
|
|
||||||
|
option.walkableHeight = m_agentHeight;
|
||||||
|
option.walkableRadius = m_agentRadius;
|
||||||
|
option.walkableClimb = m_agentMaxClimb;
|
||||||
|
option.bmin = m_pmesh.bmin;
|
||||||
|
option.bmax = m_pmesh.bmax;
|
||||||
|
option.cs = m_cellSize;
|
||||||
|
option.ch = m_cellHeight;
|
||||||
|
option.buildBvTree = true;
|
||||||
|
|
||||||
|
option.offMeshConCount = m_geom.GetOffMeshConnections().Count;
|
||||||
|
option.offMeshConVerts = new float[option.offMeshConCount * 6];
|
||||||
|
option.offMeshConRad = new float[option.offMeshConCount];
|
||||||
|
option.offMeshConDir = new int[option.offMeshConCount];
|
||||||
|
option.offMeshConAreas = new int[option.offMeshConCount];
|
||||||
|
option.offMeshConFlags = new int[option.offMeshConCount];
|
||||||
|
option.offMeshConUserID = new int[option.offMeshConCount];
|
||||||
|
for (int i = 0; i < option.offMeshConCount; i++)
|
||||||
|
{
|
||||||
|
DemoOffMeshConnection offMeshCon = m_geom.GetOffMeshConnections()[i];
|
||||||
|
for (int j = 0; j < 6; j++)
|
||||||
|
{
|
||||||
|
option.offMeshConVerts[6 * i + j] = offMeshCon.verts[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
option.offMeshConRad[i] = offMeshCon.radius;
|
||||||
|
option.offMeshConDir[i] = offMeshCon.bidir ? 1 : 0;
|
||||||
|
option.offMeshConAreas[i] = offMeshCon.area;
|
||||||
|
option.offMeshConFlags[i] = offMeshCon.flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MeshData UpdateAreaAndFlags(MeshData meshData)
|
||||||
|
{
|
||||||
|
// Update poly flags from areas.
|
||||||
|
for (int i = 0; i < meshData.polys.Length; ++i)
|
||||||
|
{
|
||||||
|
if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WALKABLE)
|
||||||
|
{
|
||||||
|
meshData.polys[i].SetArea(SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND
|
||||||
|
|| meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GRASS
|
||||||
|
|| meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD)
|
||||||
|
{
|
||||||
|
meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_WALK;
|
||||||
|
}
|
||||||
|
else if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER)
|
||||||
|
{
|
||||||
|
meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_SWIM;
|
||||||
|
}
|
||||||
|
else if (meshData.polys[i].GetArea() == SampleAreaModifications.SAMPLE_POLYAREA_TYPE_DOOR)
|
||||||
|
{
|
||||||
|
meshData.polys[i].flags = SampleAreaModifications.SAMPLE_POLYFLAGS_DOOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return meshData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace DotRecast.Recast.DemoTool.Builder
|
||||||
|
{
|
||||||
|
|
||||||
|
public class SampleAreaModifications
|
||||||
|
{
|
||||||
|
public const int SAMPLE_POLYAREA_TYPE_GROUND = 0x0;
|
||||||
|
public const int SAMPLE_POLYAREA_TYPE_WATER = 0x1;
|
||||||
|
public const int SAMPLE_POLYAREA_TYPE_ROAD = 0x2;
|
||||||
|
public const int SAMPLE_POLYAREA_TYPE_DOOR = 0x3;
|
||||||
|
public const int SAMPLE_POLYAREA_TYPE_GRASS = 0x4;
|
||||||
|
public const int SAMPLE_POLYAREA_TYPE_JUMP = 0x5;
|
||||||
|
public const int SAMPLE_POLYAREA_TYPE_JUMP_AUTO = 0x6;
|
||||||
|
public const int SAMPLE_POLYAREA_TYPE_WALKABLE = 0x3f;
|
||||||
|
|
||||||
|
public static readonly AreaModification SAMPLE_AREAMOD_WALKABLE = new AreaModification(SAMPLE_POLYAREA_TYPE_WALKABLE);
|
||||||
|
public static readonly AreaModification SAMPLE_AREAMOD_GROUND = new AreaModification(SAMPLE_POLYAREA_TYPE_GROUND);
|
||||||
|
public static readonly AreaModification SAMPLE_AREAMOD_WATER = new AreaModification(SAMPLE_POLYAREA_TYPE_WATER);
|
||||||
|
public static readonly AreaModification SAMPLE_AREAMOD_ROAD = new AreaModification(SAMPLE_POLYAREA_TYPE_ROAD);
|
||||||
|
public static readonly AreaModification SAMPLE_AREAMOD_GRASS = new AreaModification(SAMPLE_POLYAREA_TYPE_GRASS);
|
||||||
|
public static readonly AreaModification SAMPLE_AREAMOD_DOOR = new AreaModification(SAMPLE_POLYAREA_TYPE_DOOR);
|
||||||
|
public static readonly AreaModification SAMPLE_AREAMOD_JUMP = new AreaModification(SAMPLE_POLYAREA_TYPE_JUMP);
|
||||||
|
|
||||||
|
public static readonly ImmutableArray<AreaModification> Values = ImmutableArray.Create(
|
||||||
|
SAMPLE_AREAMOD_WALKABLE,
|
||||||
|
SAMPLE_AREAMOD_GROUND,
|
||||||
|
SAMPLE_AREAMOD_WATER,
|
||||||
|
SAMPLE_AREAMOD_ROAD,
|
||||||
|
SAMPLE_AREAMOD_GRASS,
|
||||||
|
SAMPLE_AREAMOD_DOOR,
|
||||||
|
SAMPLE_AREAMOD_JUMP
|
||||||
|
);
|
||||||
|
|
||||||
|
public static AreaModification OfValue(int value)
|
||||||
|
{
|
||||||
|
return Values.FirstOrDefault(x => x.Value == value) ?? SAMPLE_AREAMOD_GRASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly int SAMPLE_POLYFLAGS_WALK = 0x01; // Ability to walk (ground, grass, road)
|
||||||
|
public static readonly int SAMPLE_POLYFLAGS_SWIM = 0x02; // Ability to swim (water).
|
||||||
|
public static readonly int SAMPLE_POLYFLAGS_DOOR = 0x04; // Ability to move through doors.
|
||||||
|
public static readonly int SAMPLE_POLYFLAGS_JUMP = 0x08; // Ability to jump.
|
||||||
|
public static readonly int SAMPLE_POLYFLAGS_DISABLED = 0x10; // Disabled polygon
|
||||||
|
public static readonly int SAMPLE_POLYFLAGS_ALL = 0xffff; // All abilities.
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using DotRecast.Detour;
|
||||||
|
using DotRecast.Recast.DemoTool.Geom;
|
||||||
|
|
||||||
|
namespace DotRecast.Recast.DemoTool.Builder
|
||||||
|
{
|
||||||
|
public class SoloNavMeshBuilder : AbstractNavMeshBuilder
|
||||||
|
{
|
||||||
|
public Tuple<IList<RecastBuilderResult>, NavMesh> Build(DemoInputGeomProvider geom, PartitionType partitionType,
|
||||||
|
float cellSize, float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb,
|
||||||
|
float agentMaxSlope, int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError,
|
||||||
|
int vertsPerPoly, float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles,
|
||||||
|
bool filterLedgeSpans, bool filterWalkableLowHeightSpans)
|
||||||
|
{
|
||||||
|
RecastBuilderResult rcResult = BuildRecastResult(geom, partitionType, cellSize, cellHeight, agentHeight,
|
||||||
|
agentRadius, agentMaxClimb, agentMaxSlope, regionMinSize, regionMergeSize, edgeMaxLen, edgeMaxError,
|
||||||
|
vertsPerPoly, detailSampleDist, detailSampleMaxError, filterLowHangingObstacles, filterLedgeSpans,
|
||||||
|
filterWalkableLowHeightSpans);
|
||||||
|
return Tuple.Create(ImmutableArray.Create(rcResult) as IList<RecastBuilderResult>,
|
||||||
|
BuildNavMesh(
|
||||||
|
BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, rcResult),
|
||||||
|
vertsPerPoly));
|
||||||
|
}
|
||||||
|
|
||||||
|
private NavMesh BuildNavMesh(MeshData meshData, int vertsPerPoly)
|
||||||
|
{
|
||||||
|
return new NavMesh(meshData, vertsPerPoly, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RecastBuilderResult BuildRecastResult(DemoInputGeomProvider geom, PartitionType partitionType, float cellSize,
|
||||||
|
float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb, float agentMaxSlope,
|
||||||
|
int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError, int vertsPerPoly,
|
||||||
|
float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles, bool filterLedgeSpans,
|
||||||
|
bool filterWalkableLowHeightSpans)
|
||||||
|
{
|
||||||
|
RecastConfig cfg = new RecastConfig(partitionType, cellSize, cellHeight, agentMaxSlope, filterLowHangingObstacles,
|
||||||
|
filterLedgeSpans, filterWalkableLowHeightSpans, agentHeight, agentRadius, agentMaxClimb, regionMinSize,
|
||||||
|
regionMergeSize, edgeMaxLen, edgeMaxError, vertsPerPoly, detailSampleDist, detailSampleMaxError,
|
||||||
|
SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true);
|
||||||
|
RecastBuilderConfig bcfg = new RecastBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
|
||||||
|
RecastBuilder rcBuilder = new RecastBuilder();
|
||||||
|
return rcBuilder.Build(geom, bcfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MeshData BuildMeshData(DemoInputGeomProvider geom, float cellSize, float cellHeight, float agentHeight,
|
||||||
|
float agentRadius, float agentMaxClimb, RecastBuilderResult result)
|
||||||
|
{
|
||||||
|
NavMeshDataCreateParams option = GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight, agentRadius,
|
||||||
|
agentMaxClimb, result);
|
||||||
|
return UpdateAreaAndFlags(NavMeshBuilder.CreateNavMeshData(option));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using DotRecast.Core;
|
||||||
|
using DotRecast.Detour;
|
||||||
|
using DotRecast.Recast.DemoTool.Geom;
|
||||||
|
using static DotRecast.Core.RcMath;
|
||||||
|
|
||||||
|
namespace DotRecast.Recast.DemoTool.Builder
|
||||||
|
{
|
||||||
|
public class TileNavMeshBuilder : AbstractNavMeshBuilder
|
||||||
|
{
|
||||||
|
public TileNavMeshBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tuple<IList<RecastBuilderResult>, NavMesh> Build(DemoInputGeomProvider geom, PartitionType partitionType,
|
||||||
|
float cellSize, float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb,
|
||||||
|
float agentMaxSlope, int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError,
|
||||||
|
int vertsPerPoly, float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles,
|
||||||
|
bool filterLedgeSpans, bool filterWalkableLowHeightSpans, int tileSize)
|
||||||
|
{
|
||||||
|
List<RecastBuilderResult> rcResult = BuildRecastResult(geom, partitionType, cellSize, cellHeight, agentHeight,
|
||||||
|
agentRadius, agentMaxClimb, agentMaxSlope, regionMinSize, regionMergeSize, edgeMaxLen, edgeMaxError,
|
||||||
|
vertsPerPoly, detailSampleDist, detailSampleMaxError, filterLowHangingObstacles, filterLedgeSpans,
|
||||||
|
filterWalkableLowHeightSpans, tileSize);
|
||||||
|
return Tuple.Create((IList<RecastBuilderResult>)rcResult,
|
||||||
|
BuildNavMesh(geom,
|
||||||
|
BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, rcResult),
|
||||||
|
cellSize, tileSize, vertsPerPoly));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<RecastBuilderResult> BuildRecastResult(DemoInputGeomProvider geom, PartitionType partitionType,
|
||||||
|
float cellSize, float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb,
|
||||||
|
float agentMaxSlope, int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError,
|
||||||
|
int vertsPerPoly, float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles,
|
||||||
|
bool filterLedgeSpans, bool filterWalkableLowHeightSpans, int tileSize)
|
||||||
|
{
|
||||||
|
RecastConfig cfg = new RecastConfig(true, tileSize, tileSize, RecastConfig.CalcBorder(agentRadius, cellSize),
|
||||||
|
partitionType, cellSize, cellHeight, agentMaxSlope, filterLowHangingObstacles, filterLedgeSpans,
|
||||||
|
filterWalkableLowHeightSpans, agentHeight, agentRadius, agentMaxClimb,
|
||||||
|
regionMinSize * regionMinSize * cellSize * cellSize,
|
||||||
|
regionMergeSize * regionMergeSize * cellSize * cellSize, edgeMaxLen, edgeMaxError, vertsPerPoly,
|
||||||
|
true, detailSampleDist, detailSampleMaxError, SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE);
|
||||||
|
RecastBuilder rcBuilder = new RecastBuilder();
|
||||||
|
return rcBuilder.BuildTiles(geom, cfg, Task.Factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private NavMesh BuildNavMesh(DemoInputGeomProvider geom, List<MeshData> meshData, float cellSize, int tileSize,
|
||||||
|
int vertsPerPoly)
|
||||||
|
{
|
||||||
|
NavMeshParams navMeshParams = new NavMeshParams();
|
||||||
|
navMeshParams.orig.x = geom.GetMeshBoundsMin().x;
|
||||||
|
navMeshParams.orig.y = geom.GetMeshBoundsMin().y;
|
||||||
|
navMeshParams.orig.z = geom.GetMeshBoundsMin().z;
|
||||||
|
navMeshParams.tileWidth = tileSize * cellSize;
|
||||||
|
navMeshParams.tileHeight = tileSize * cellSize;
|
||||||
|
|
||||||
|
// Snprintf(text, 64, "Tiles %d x %d", tw, th);
|
||||||
|
|
||||||
|
navMeshParams.maxTiles = GetMaxTiles(geom, cellSize, tileSize);
|
||||||
|
navMeshParams.maxPolys = GetMaxPolysPerTile(geom, cellSize, tileSize);
|
||||||
|
NavMesh navMesh = new NavMesh(navMeshParams, vertsPerPoly);
|
||||||
|
meshData.ForEach(md => navMesh.AddTile(md, 0, 0));
|
||||||
|
return navMesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetMaxTiles(DemoInputGeomProvider geom, float cellSize, int tileSize)
|
||||||
|
{
|
||||||
|
int tileBits = GetTileBits(geom, cellSize, tileSize);
|
||||||
|
return 1 << tileBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetMaxPolysPerTile(DemoInputGeomProvider geom, float cellSize, int tileSize)
|
||||||
|
{
|
||||||
|
int polyBits = 22 - GetTileBits(geom, cellSize, tileSize);
|
||||||
|
return 1 << polyBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetTileBits(DemoInputGeomProvider geom, float cellSize, int tileSize)
|
||||||
|
{
|
||||||
|
Recast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
|
||||||
|
int tw = (gw + tileSize - 1) / tileSize;
|
||||||
|
int th = (gh + tileSize - 1) / tileSize;
|
||||||
|
int tileBits = Math.Min(DetourCommon.Ilog2(DetourCommon.NextPow2(tw * th)), 14);
|
||||||
|
return tileBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] GetTiles(DemoInputGeomProvider geom, float cellSize, int tileSize)
|
||||||
|
{
|
||||||
|
Recast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
|
||||||
|
int tw = (gw + tileSize - 1) / tileSize;
|
||||||
|
int th = (gh + tileSize - 1) / tileSize;
|
||||||
|
return new int[] { tw, th };
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<MeshData> BuildMeshData(DemoInputGeomProvider geom, float cellSize, float cellHeight, float agentHeight,
|
||||||
|
float agentRadius, float agentMaxClimb, List<RecastBuilderResult> results)
|
||||||
|
{
|
||||||
|
// Add tiles to nav mesh
|
||||||
|
List<MeshData> meshData = new List<MeshData>();
|
||||||
|
foreach (RecastBuilderResult result in results)
|
||||||
|
{
|
||||||
|
int x = result.tileX;
|
||||||
|
int z = result.tileZ;
|
||||||
|
NavMeshDataCreateParams option = GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight,
|
||||||
|
agentRadius, agentMaxClimb, result);
|
||||||
|
option.tileX = x;
|
||||||
|
option.tileZ = z;
|
||||||
|
MeshData md = NavMeshBuilder.CreateNavMeshData(option);
|
||||||
|
if (md != null)
|
||||||
|
{
|
||||||
|
meshData.Add(UpdateAreaAndFlags(md));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return meshData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,228 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using DotRecast.Core;
|
||||||
|
using DotRecast.Recast.Geom;
|
||||||
|
|
||||||
|
namespace DotRecast.Recast.DemoTool.Geom
|
||||||
|
{
|
||||||
|
public class DemoInputGeomProvider : IInputGeomProvider
|
||||||
|
{
|
||||||
|
public readonly float[] vertices;
|
||||||
|
public readonly int[] faces;
|
||||||
|
public readonly float[] normals;
|
||||||
|
private readonly RcVec3f bmin;
|
||||||
|
private readonly RcVec3f bmax;
|
||||||
|
private readonly List<ConvexVolume> _convexVolumes = new List<ConvexVolume>();
|
||||||
|
private readonly List<DemoOffMeshConnection> offMeshConnections = new List<DemoOffMeshConnection>();
|
||||||
|
private readonly TriMesh _mesh;
|
||||||
|
|
||||||
|
public DemoInputGeomProvider(List<float> vertexPositions, List<int> meshFaces) :
|
||||||
|
this(MapVertices(vertexPositions), MapFaces(meshFaces))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int[] MapFaces(List<int> meshFaces)
|
||||||
|
{
|
||||||
|
int[] faces = new int[meshFaces.Count];
|
||||||
|
for (int i = 0; i < faces.Length; i++)
|
||||||
|
{
|
||||||
|
faces[i] = meshFaces[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return faces;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float[] MapVertices(List<float> vertexPositions)
|
||||||
|
{
|
||||||
|
float[] vertices = new float[vertexPositions.Count];
|
||||||
|
for (int i = 0; i < vertices.Length; i++)
|
||||||
|
{
|
||||||
|
vertices[i] = vertexPositions[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return vertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DemoInputGeomProvider(float[] vertices, int[] faces)
|
||||||
|
{
|
||||||
|
this.vertices = vertices;
|
||||||
|
this.faces = faces;
|
||||||
|
normals = new float[faces.Length];
|
||||||
|
CalculateNormals();
|
||||||
|
bmin = RcVec3f.Zero;
|
||||||
|
bmax = RcVec3f.Zero;
|
||||||
|
RcVec3f.Copy(ref bmin, vertices, 0);
|
||||||
|
RcVec3f.Copy(ref bmax, vertices, 0);
|
||||||
|
for (int i = 1; i < vertices.Length / 3; i++)
|
||||||
|
{
|
||||||
|
bmin.Min(vertices, i * 3);
|
||||||
|
bmax.Max(vertices, i * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
_mesh = new TriMesh(vertices, faces);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RcVec3f GetMeshBoundsMin()
|
||||||
|
{
|
||||||
|
return bmin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RcVec3f GetMeshBoundsMax()
|
||||||
|
{
|
||||||
|
return bmax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CalculateNormals()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < faces.Length; i += 3)
|
||||||
|
{
|
||||||
|
int v0 = faces[i] * 3;
|
||||||
|
int v1 = faces[i + 1] * 3;
|
||||||
|
int v2 = faces[i + 2] * 3;
|
||||||
|
RcVec3f e0 = new RcVec3f();
|
||||||
|
RcVec3f e1 = new RcVec3f();
|
||||||
|
for (int j = 0; j < 3; ++j)
|
||||||
|
{
|
||||||
|
e0[j] = vertices[v1 + j] - vertices[v0 + j];
|
||||||
|
e1[j] = vertices[v2 + j] - vertices[v0 + j];
|
||||||
|
}
|
||||||
|
|
||||||
|
normals[i] = e0.y * e1.z - e0.z * e1.y;
|
||||||
|
normals[i + 1] = e0.z * e1.x - e0.x * e1.z;
|
||||||
|
normals[i + 2] = e0.x * e1.y - e0.y * e1.x;
|
||||||
|
float d = (float)Math.Sqrt(normals[i] * normals[i] + normals[i + 1] * normals[i + 1] + normals[i + 2] * normals[i + 2]);
|
||||||
|
if (d > 0)
|
||||||
|
{
|
||||||
|
d = 1.0f / d;
|
||||||
|
normals[i] *= d;
|
||||||
|
normals[i + 1] *= d;
|
||||||
|
normals[i + 2] *= d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IList<ConvexVolume> ConvexVolumes()
|
||||||
|
{
|
||||||
|
return _convexVolumes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<TriMesh> Meshes()
|
||||||
|
{
|
||||||
|
return ImmutableArray.Create(_mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DemoOffMeshConnection> GetOffMeshConnections()
|
||||||
|
{
|
||||||
|
return offMeshConnections;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddOffMeshConnection(RcVec3f start, RcVec3f end, float radius, bool bidir, int area, int flags)
|
||||||
|
{
|
||||||
|
offMeshConnections.Add(new DemoOffMeshConnection(start, end, radius, bidir, area, flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveOffMeshConnections(Predicate<DemoOffMeshConnection> filter)
|
||||||
|
{
|
||||||
|
//offMeshConnections.RetainAll(offMeshConnections.Stream().Filter(c -> !filter.Test(c)).Collect(ToList()));
|
||||||
|
offMeshConnections.RemoveAll(filter); // TODO : 확인 필요
|
||||||
|
}
|
||||||
|
|
||||||
|
public float? RaycastMesh(RcVec3f src, RcVec3f dst)
|
||||||
|
{
|
||||||
|
// Prune hit ray.
|
||||||
|
if (!Intersections.IsectSegAABB(src, dst, bmin, bmax, out var btmin, out var btmax))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
float[] p = new float[2];
|
||||||
|
float[] q = new float[2];
|
||||||
|
p[0] = src.x + (dst.x - src.x) * btmin;
|
||||||
|
p[1] = src.z + (dst.z - src.z) * btmin;
|
||||||
|
q[0] = src.x + (dst.x - src.x) * btmax;
|
||||||
|
q[1] = src.z + (dst.z - src.z) * btmax;
|
||||||
|
|
||||||
|
List<ChunkyTriMeshNode> chunks = _mesh.chunkyTriMesh.GetChunksOverlappingSegment(p, q);
|
||||||
|
if (0 == chunks.Count)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
float? tmin = 1.0f;
|
||||||
|
bool hit = false;
|
||||||
|
foreach (ChunkyTriMeshNode chunk in chunks)
|
||||||
|
{
|
||||||
|
int[] tris = chunk.tris;
|
||||||
|
for (int j = 0; j < chunk.tris.Length; j += 3)
|
||||||
|
{
|
||||||
|
RcVec3f v1 = RcVec3f.Of(
|
||||||
|
vertices[tris[j] * 3],
|
||||||
|
vertices[tris[j] * 3 + 1],
|
||||||
|
vertices[tris[j] * 3 + 2]
|
||||||
|
);
|
||||||
|
RcVec3f v2 = RcVec3f.Of(
|
||||||
|
vertices[tris[j + 1] * 3],
|
||||||
|
vertices[tris[j + 1] * 3 + 1],
|
||||||
|
vertices[tris[j + 1] * 3 + 2]
|
||||||
|
);
|
||||||
|
RcVec3f v3 = RcVec3f.Of(
|
||||||
|
vertices[tris[j + 2] * 3],
|
||||||
|
vertices[tris[j + 2] * 3 + 1],
|
||||||
|
vertices[tris[j + 2] * 3 + 2]
|
||||||
|
);
|
||||||
|
float? t = Intersections.IntersectSegmentTriangle(src, dst, v1, v2, v3);
|
||||||
|
if (null != t)
|
||||||
|
{
|
||||||
|
if (t.Value < tmin)
|
||||||
|
{
|
||||||
|
tmin = t.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
hit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hit
|
||||||
|
? tmin
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void AddConvexVolume(float[] verts, float minh, float maxh, AreaModification areaMod)
|
||||||
|
{
|
||||||
|
ConvexVolume volume = new ConvexVolume();
|
||||||
|
volume.verts = verts;
|
||||||
|
volume.hmin = minh;
|
||||||
|
volume.hmax = maxh;
|
||||||
|
volume.areaMod = areaMod;
|
||||||
|
_convexVolumes.Add(volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearConvexVolumes()
|
||||||
|
{
|
||||||
|
_convexVolumes.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,10 +20,10 @@ freely, subject to the following restrictions:
|
||||||
|
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Geom;
|
namespace DotRecast.Recast.DemoTool.Geom
|
||||||
|
|
||||||
public class DemoOffMeshConnection
|
|
||||||
{
|
{
|
||||||
|
public class DemoOffMeshConnection
|
||||||
|
{
|
||||||
public readonly float[] verts;
|
public readonly float[] verts;
|
||||||
public readonly float radius;
|
public readonly float radius;
|
||||||
public readonly bool bidir;
|
public readonly bool bidir;
|
||||||
|
@ -44,4 +44,5 @@ public class DemoOffMeshConnection
|
||||||
this.area = area;
|
this.area = area;
|
||||||
this.flags = flags;
|
this.flags = flags;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
Recast4J Copyright (c) 2015 Piotr Piastucki piotr@jtilia.org
|
Recast4J Copyright (c) 2015 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
Loading…
Reference in New Issue