提交Unity 联机Pro

This commit is contained in:
PC-20230316NUNE\Administrator
2024-08-17 14:27:18 +08:00
parent f00193b000
commit 894100ae37
7448 changed files with 854473 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 79f59c7bf226438cb591ec56fa35968f
timeCreated: 1715335340

View File

@@ -0,0 +1,98 @@
/*
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
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 DotRecast.Core;
using DotRecast.Core.Numerics;
using DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic.Colliders
{
public class DtBoxCollider : DtCollider
{
private readonly RcVec3f center;
private readonly RcVec3f[] halfEdges;
public DtBoxCollider(RcVec3f center, RcVec3f[] halfEdges, int area, LFloat flagMergeThreshold) :
base(area, flagMergeThreshold, Bounds(center, halfEdges))
{
this.center = center;
this.halfEdges = halfEdges;
}
private static LFloat[] Bounds(RcVec3f center, RcVec3f[] halfEdges)
{
LFloat[] bounds = new LFloat[]
{
LFloat.PositiveInfinity, LFloat.PositiveInfinity, LFloat.PositiveInfinity,
LFloat.NegativeInfinity, LFloat.NegativeInfinity, LFloat.NegativeInfinity
};
for (int i = 0; i < 8; ++i)
{
LFloat s0 = (i & 1) != 0 ? (LFloat)1f : -(LFloat)1f;
LFloat s1 = (i & 2) != 0 ? (LFloat)1f : -(LFloat)1f;
LFloat s2 = (i & 4) != 0 ? (LFloat)1f : -(LFloat)1f;
LFloat vx = center.X + s0 * halfEdges[0].X + s1 * halfEdges[1].X + s2 * halfEdges[2].X;
LFloat vy = center.Y + s0 * halfEdges[0].Y + s1 * halfEdges[1].Y + s2 * halfEdges[2].Y;
LFloat vz = center.Z + s0 * halfEdges[0].Z + s1 * halfEdges[1].Z + s2 * halfEdges[2].Z;
bounds[0] = LMath.Min(bounds[0], vx);
bounds[1] = LMath.Min(bounds[1], vy);
bounds[2] = LMath.Min(bounds[2], vz);
bounds[3] = LMath.Max(bounds[3], vx);
bounds[4] = LMath.Max(bounds[4], vy);
bounds[5] = LMath.Max(bounds[5], vz);
}
return bounds;
}
public override void Rasterize(RcHeightfield hf, RcContext context)
{
RcFilledVolumeRasterization.RasterizeBox(
hf, center, halfEdges, area, (int)LMath.Floor(flagMergeThreshold / hf.ch), context);
}
public static RcVec3f[] GetHalfEdges(RcVec3f up, RcVec3f forward, RcVec3f extent)
{
RcVec3f[] halfEdges =
{
RcVec3f.Zero,
new RcVec3f(up.X, up.Y, up.Z),
RcVec3f.Zero
};
halfEdges[1] = RcVec3f.Normalize(halfEdges[1]);
halfEdges[0] = RcVec3f.Cross(up, forward);
halfEdges[0] = RcVec3f.Normalize(halfEdges[0]);
halfEdges[2] = RcVec3f.Cross(halfEdges[0], up);
halfEdges[2] = RcVec3f.Normalize(halfEdges[2]);
halfEdges[0].X *= extent.X;
halfEdges[0].Y *= extent.X;
halfEdges[0].Z *= extent.X;
halfEdges[1].X *= extent.Y;
halfEdges[1].Y *= extent.Y;
halfEdges[1].Z *= extent.Y;
halfEdges[2].X *= extent.Z;
halfEdges[2].Y *= extent.Z;
halfEdges[2].Z *= extent.Z;
return halfEdges;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 343af89640044ca4b578cf236fb94cf0
timeCreated: 1715335340

View File

@@ -0,0 +1,57 @@
/*
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
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 DotRecast.Core;
using DotRecast.Core.Numerics;
using DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic.Colliders
{
public class DtCapsuleCollider : DtCollider
{
private readonly RcVec3f start;
private readonly RcVec3f end;
private readonly LFloat radius;
public DtCapsuleCollider(RcVec3f start, RcVec3f end, LFloat radius, int area, LFloat flagMergeThreshold)
: base(area, flagMergeThreshold, Bounds(start, end, radius))
{
this.start = start;
this.end = end;
this.radius = radius;
}
public override void Rasterize(RcHeightfield hf, RcContext context)
{
RcFilledVolumeRasterization.RasterizeCapsule(hf, start, end, radius, area, (int)LMath.Floor(flagMergeThreshold / hf.ch), context);
}
private static LFloat[] Bounds(RcVec3f start, RcVec3f end, LFloat radius)
{
return new LFloat[]
{
LMath.Min(start.X, end.X) - radius, LMath.Min(start.Y, end.Y) - radius,
LMath.Min(start.Z, end.Z) - radius, LMath.Max(start.X, end.X) + radius, LMath.Max(start.Y, end.Y) + radius,
LMath.Max(start.Z, end.Z) + radius
};
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 924df89ba25a438fbfbd934f761b814f
timeCreated: 1715335340

View File

@@ -0,0 +1,46 @@
/*
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
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 DotRecast.Core;
using DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic.Colliders
{
public abstract class DtCollider : IDtCollider
{
protected readonly int area;
protected readonly LFloat flagMergeThreshold;
protected readonly LFloat[] _bounds;
public DtCollider(int area, LFloat flagMergeThreshold, LFloat[] bounds)
{
this.area = area;
this.flagMergeThreshold = flagMergeThreshold;
this._bounds = bounds;
}
public LFloat[] Bounds()
{
return _bounds;
}
public abstract void Rasterize(RcHeightfield hf, RcContext context);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7c681f6cb72b4f82b609ea36106f9fa5
timeCreated: 1715335340

View File

@@ -0,0 +1,78 @@
/*
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
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.Linq;
using DotRecast.Core;
using DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic.Colliders
{
public class DtCompositeCollider : IDtCollider
{
private readonly List<IDtCollider> colliders;
private readonly LFloat[] _bounds;
public DtCompositeCollider(List<IDtCollider> colliders)
{
this.colliders = colliders;
_bounds = Bounds(colliders);
}
public DtCompositeCollider(params IDtCollider[] colliders)
{
this.colliders = colliders.ToList();
_bounds = Bounds(this.colliders);
}
public LFloat[] Bounds()
{
return _bounds;
}
private static LFloat[] Bounds(List<IDtCollider> colliders)
{
LFloat[] bounds = new LFloat[]
{
LFloat.PositiveInfinity, LFloat.PositiveInfinity, LFloat.PositiveInfinity,
LFloat.NegativeInfinity, LFloat.NegativeInfinity, LFloat.NegativeInfinity
};
foreach (IDtCollider collider in colliders)
{
LFloat[] b = collider.Bounds();
bounds[0] = LMath.Min(bounds[0], b[0]);
bounds[1] = LMath.Min(bounds[1], b[1]);
bounds[2] = LMath.Min(bounds[2], b[2]);
bounds[3] = LMath.Max(bounds[3], b[3]);
bounds[4] = LMath.Max(bounds[4], b[4]);
bounds[5] = LMath.Max(bounds[5], b[5]);
}
return bounds;
}
public void Rasterize(RcHeightfield hf, RcContext context)
{
foreach (var c in colliders)
c.Rasterize(hf, context);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 31c4e9ca0a634501bbd20a01e5ca00b6
timeCreated: 1715335340

View File

@@ -0,0 +1,52 @@
/*
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
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 DotRecast.Core;
using DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic.Colliders
{
public class DtConvexTrimeshCollider : DtCollider
{
private readonly LFloat[] vertices;
private readonly int[] triangles;
public DtConvexTrimeshCollider(LFloat[] vertices, int[] triangles, int area, LFloat flagMergeThreshold)
: base(area, flagMergeThreshold, DtTrimeshCollider.ComputeBounds(vertices))
{
this.vertices = vertices;
this.triangles = triangles;
}
public DtConvexTrimeshCollider(LFloat[] vertices, int[] triangles, LFloat[] bounds, int area, LFloat flagMergeThreshold)
: base(area, flagMergeThreshold, bounds)
{
this.vertices = vertices;
this.triangles = triangles;
}
public override void Rasterize(RcHeightfield hf, RcContext context)
{
RcFilledVolumeRasterization.RasterizeConvex(hf, vertices, triangles, area,
(int)LMath.Floor(flagMergeThreshold / hf.ch), context);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bc503c1503a240f7b8a23fc2b63eaa1d
timeCreated: 1715335340

View File

@@ -0,0 +1,58 @@
/*
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
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 DotRecast.Core;
using DotRecast.Core.Numerics;
using DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic.Colliders
{
public class DtCylinderCollider : DtCollider
{
private readonly RcVec3f start;
private readonly RcVec3f end;
private readonly LFloat radius;
public DtCylinderCollider(RcVec3f start, RcVec3f end, LFloat radius, int area, LFloat flagMergeThreshold) :
base(area, flagMergeThreshold, Bounds(start, end, radius))
{
this.start = start;
this.end = end;
this.radius = radius;
}
public override void Rasterize(RcHeightfield hf, RcContext context)
{
RcFilledVolumeRasterization.RasterizeCylinder(hf, start, end, radius, area, (int)LMath.Floor(flagMergeThreshold / hf.ch),
context);
}
private static LFloat[] Bounds(RcVec3f start, RcVec3f end, LFloat radius)
{
return new LFloat[]
{
LMath.Min(start.X, end.X) - radius, LMath.Min(start.Y, end.Y) - radius,
LMath.Min(start.Z, end.Z) - radius, LMath.Max(start.X, end.X) + radius, LMath.Max(start.Y, end.Y) + radius,
LMath.Max(start.Z, end.Z) + radius
};
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 826cab82648144898478cf98f9b1e40a
timeCreated: 1715335340

View File

@@ -0,0 +1,59 @@
/*
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
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 DotRecast.Core;
using DotRecast.Core.Numerics;
using DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic.Colliders
{
public class DtSphereCollider : DtCollider
{
private readonly RcVec3f center;
private readonly LFloat radius;
public DtSphereCollider(RcVec3f center, LFloat radius, int area, LFloat flagMergeThreshold)
: base(area, flagMergeThreshold, Bounds(center, radius))
{
this.center = center;
this.radius = radius;
}
public override void Rasterize(RcHeightfield hf, RcContext context)
{
RcFilledVolumeRasterization.RasterizeSphere(hf, center, radius, area, (int)LMath.Floor(flagMergeThreshold / hf.ch),
context);
}
private static LFloat[] Bounds(RcVec3f center, LFloat radius)
{
return new LFloat[]
{
center.X - radius,
center.Y - radius,
center.Z - radius,
center.X + radius,
center.Y + radius,
center.Z + radius
};
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e353c1f8bfff4365acf828322df2a9df
timeCreated: 1715335340

View File

@@ -0,0 +1,71 @@
/*
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
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 DotRecast.Core;
using DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic.Colliders
{
public class DtTrimeshCollider : DtCollider
{
private readonly LFloat[] vertices;
private readonly int[] triangles;
public DtTrimeshCollider(LFloat[] vertices, int[] triangles, int area, LFloat flagMergeThreshold)
: base(area, flagMergeThreshold, ComputeBounds(vertices))
{
this.vertices = vertices;
this.triangles = triangles;
}
public DtTrimeshCollider(LFloat[] vertices, int[] triangles, LFloat[] bounds, int area, LFloat flagMergeThreshold) :
base(area, flagMergeThreshold, bounds)
{
this.vertices = vertices;
this.triangles = triangles;
}
public static LFloat[] ComputeBounds(LFloat[] vertices)
{
LFloat[] bounds = new LFloat[] { vertices[0], vertices[1], vertices[2], vertices[0], vertices[1], vertices[2] };
for (int i = 3; i < vertices.Length; i += 3)
{
bounds[0] = LMath.Min(bounds[0], vertices[i]);
bounds[1] = LMath.Min(bounds[1], vertices[i + 1]);
bounds[2] = LMath.Min(bounds[2], vertices[i + 2]);
bounds[3] = LMath.Max(bounds[3], vertices[i]);
bounds[4] = LMath.Max(bounds[4], vertices[i + 1]);
bounds[5] = LMath.Max(bounds[5], vertices[i + 2]);
}
return bounds;
}
public override void Rasterize(RcHeightfield hf, RcContext context)
{
for (int i = 0; i < triangles.Length; i += 3)
{
RcRasterizations.RasterizeTriangle(context, vertices, triangles[i], triangles[i + 1], triangles[i + 2], area,
hf, (int)LMath.Floor(flagMergeThreshold / hf.ch));
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 20a4ce560af24659b04a463f259e9114
timeCreated: 1715335340

View File

@@ -0,0 +1,31 @@
/*
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
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 DotRecast.Core;
using DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic.Colliders
{
public interface IDtCollider
{
LFloat[] Bounds();
void Rasterize(RcHeightfield hf, RcContext context);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fa31a946c5ba4ef0aacaa77e218527ad
timeCreated: 1715335340

View File

@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.1;net6.0;net7.0;net8.0</TargetFrameworks>
<PackageId>DotRecast.Detour.Dynamic</PackageId>
<PackageReadmeFile>README.md</PackageReadmeFile>
<Authors>ikpil</Authors>
<Description>DotRecast - a port of Recast Detour, Industry-standard navigation mesh toolset for .NET, C#, Unity3D, games, servers</Description>
<RepositoryType>git</RepositoryType>
<PackageProjectUrl>https://github.com/ikpil/DotRecast</PackageProjectUrl>
<RepositoryUrl>https://github.com/ikpil/DotRecast</RepositoryUrl>
<PackageTags>game gamedev ai csharp server unity navigation game-development unity3d pathfinding pathfinder recast detour navmesh crowd-simulation recastnavigation</PackageTags>
<PackageReleaseNotes>https://github.com/ikpil/DotRecast/blob/main/CHANGELOG.md</PackageReleaseNotes>
</PropertyGroup>
<ItemGroup>
<None Include="../../README.md" Pack="true" PackagePath="\"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DotRecast.Detour\DotRecast.Detour.csproj"/>
<ProjectReference Include="..\DotRecast.Recast\DotRecast.Recast.csproj"/>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 86271b6d8541401b9c49be9bfb02f251
timeCreated: 1715335340

View File

@@ -0,0 +1,261 @@
/*
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
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.Concurrent;
using System.Collections.Generic;
using System.Linq;
using DotRecast.Core;
using DotRecast.Detour.Dynamic.Colliders;
using DotRecast.Detour.Dynamic.Io;
using DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic
{
public class DtDynamicNavMesh
{
public const int MAX_VERTS_PER_POLY = 6;
public readonly DtDynamicNavMeshConfig config;
private readonly RcBuilder builder;
private readonly Dictionary<long, DtDynamicTile> _tiles = new Dictionary<long, DtDynamicTile>();
private readonly RcContext _context;
private readonly DtNavMeshParams navMeshParams;
private readonly BlockingCollection<IDtDaynmicTileJob> updateQueue = new BlockingCollection<IDtDaynmicTileJob>();
private readonly RcAtomicLong currentColliderId = new RcAtomicLong(0);
private DtNavMesh _navMesh;
private bool _dirty = true;
public DtDynamicNavMesh(DtVoxelFile voxelFile)
{
config = new DtDynamicNavMeshConfig(voxelFile.useTiles, voxelFile.tileSizeX, voxelFile.tileSizeZ, voxelFile.cellSize);
config.walkableHeight = voxelFile.walkableHeight;
config.walkableRadius = voxelFile.walkableRadius;
config.walkableClimb = voxelFile.walkableClimb;
config.walkableSlopeAngle = voxelFile.walkableSlopeAngle;
config.maxSimplificationError = voxelFile.maxSimplificationError;
config.maxEdgeLen = voxelFile.maxEdgeLen;
config.minRegionArea = voxelFile.minRegionArea;
config.regionMergeArea = voxelFile.regionMergeArea;
config.vertsPerPoly = voxelFile.vertsPerPoly;
config.buildDetailMesh = voxelFile.buildMeshDetail;
config.detailSampleDistance = voxelFile.detailSampleDistance;
config.detailSampleMaxError = voxelFile.detailSampleMaxError;
builder = new RcBuilder();
navMeshParams = new DtNavMeshParams();
navMeshParams.orig.X = voxelFile.bounds[0];
navMeshParams.orig.Y = voxelFile.bounds[1];
navMeshParams.orig.Z = voxelFile.bounds[2];
navMeshParams.tileWidth = voxelFile.cellSize * voxelFile.tileSizeX;
navMeshParams.tileHeight = voxelFile.cellSize * voxelFile.tileSizeZ;
navMeshParams.maxTiles = voxelFile.tiles.Count;
navMeshParams.maxPolys = 0x8000;
foreach (var t in voxelFile.tiles)
{
_tiles.Add(LookupKey(t.tileX, t.tileZ), new DtDynamicTile(t));
}
;
_context = new RcContext();
}
public DtNavMesh NavMesh()
{
return _navMesh;
}
/**
* Voxel queries require checkpoints to be enabled in {@link DynamicNavMeshConfig}
*/
public DtVoxelQuery VoxelQuery()
{
return new DtVoxelQuery(navMeshParams.orig, navMeshParams.tileWidth, navMeshParams.tileHeight, LookupHeightfield);
}
private RcHeightfield LookupHeightfield(int x, int z)
{
return GetTileAt(x, z)?.checkpoint.heightfield;
}
public long AddCollider(IDtCollider collider)
{
long cid = currentColliderId.IncrementAndGet();
updateQueue.Add(new DtDynamicTileColliderAdditionJob(cid, collider, GetTiles(collider.Bounds())));
return cid;
}
public void RemoveCollider(long colliderId)
{
updateQueue.Add(new DtDynamicTileColliderRemovalJob(colliderId, GetTilesByCollider(colliderId)));
}
private HashSet<DtDynamicTile> ProcessQueue()
{
var items = ConsumeQueue();
foreach (var item in items)
{
Process(item);
}
return items.SelectMany(i => i.AffectedTiles()).ToHashSet();
}
private List<IDtDaynmicTileJob> ConsumeQueue()
{
List<IDtDaynmicTileJob> items = new List<IDtDaynmicTileJob>();
while (updateQueue.TryTake(out var item))
{
items.Add(item);
}
return items;
}
private void Process(IDtDaynmicTileJob item)
{
foreach (var tile in item.AffectedTiles())
{
item.Process(tile);
}
}
// Perform full build of the navmesh
public void Build()
{
ProcessQueue();
Rebuild(_tiles.Values);
}
// // Perform full build concurrently using the given {@link ExecutorService}
// public bool Build(TaskFactory executor)
// {
// ProcessQueue();
// return Rebuild(_tiles.Values, executor);
// }
// Perform incremental update of the navmesh
public bool Update()
{
return Rebuild(ProcessQueue());
}
// // Perform incremental update concurrently using the given {@link ExecutorService}
// public bool Update(TaskFactory executor)
// {
// return Rebuild(ProcessQueue(), executor);
// }
private bool Rebuild(ICollection<DtDynamicTile> tiles)
{
foreach (var tile in tiles)
Rebuild(tile);
return UpdateNavMesh();
}
// private bool Rebuild(ICollection<DtDynamicTile> tiles, TaskFactory executor)
// {
// var tasks = tiles
// .Select(tile => executor.StartNew(() => Rebuild(tile)))
// .ToArray();
//
// Task.WaitAll(tasks);
// return UpdateNavMesh();
// }
private ICollection<DtDynamicTile> GetTiles(LFloat[] bounds)
{
if (bounds == null)
{
return _tiles.Values;
}
int minx = (int)LMath.Floor((bounds[0] - navMeshParams.orig.X) / navMeshParams.tileWidth);
int minz = (int)LMath.Floor((bounds[2] - navMeshParams.orig.Z) / navMeshParams.tileHeight);
int maxx = (int)LMath.Floor((bounds[3] - navMeshParams.orig.X) / navMeshParams.tileWidth);
int maxz = (int)LMath.Floor((bounds[5] - navMeshParams.orig.Z) / navMeshParams.tileHeight);
List<DtDynamicTile> tiles = new List<DtDynamicTile>();
for (int z = minz; z <= maxz; ++z)
{
for (int x = minx; x <= maxx; ++x)
{
DtDynamicTile tile = GetTileAt(x, z);
if (tile != null)
{
tiles.Add(tile);
}
}
}
return tiles;
}
private List<DtDynamicTile> GetTilesByCollider(long cid)
{
return _tiles.Values.Where(t => t.ContainsCollider(cid)).ToList();
}
private void Rebuild(DtDynamicTile tile)
{
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
option.walkableHeight = config.walkableHeight;
_dirty = _dirty | tile.Build(builder, config, _context);
}
private bool UpdateNavMesh()
{
if (_dirty)
{
DtNavMesh navMesh = new DtNavMesh(navMeshParams, MAX_VERTS_PER_POLY);
foreach (var t in _tiles.Values)
t.AddTo(navMesh);
_navMesh = navMesh;
_dirty = false;
return true;
}
return false;
}
private DtDynamicTile GetTileAt(int x, int z)
{
return _tiles.TryGetValue(LookupKey(x, z), out var tile)
? tile
: null;
}
private long LookupKey(long x, long z)
{
return (z << 32) | x;
}
public List<DtVoxelTile> VoxelTiles()
{
return _tiles.Values.Select(t => t.voxelTile).ToList();
}
public List<RcBuilderResult> RecastResults()
{
return _tiles.Values.Select(t => t.recastResult).ToList();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 46f1520fe06a45c4a8aa3b17ff69176f
timeCreated: 1715335340

View File

@@ -0,0 +1,59 @@
/*
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
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 DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic
{
public class DtDynamicNavMeshConfig
{
public readonly bool useTiles;
public readonly int tileSizeX;
public readonly int tileSizeZ;
public readonly LFloat cellSize;
public int partition = RcPartitionType.WATERSHED.Value;
public RcAreaModification walkableAreaModification = new RcAreaModification(1);
public LFloat walkableHeight;
public LFloat walkableSlopeAngle;
public LFloat walkableRadius;
public LFloat walkableClimb;
public LFloat minRegionArea;
public LFloat regionMergeArea;
public LFloat maxEdgeLen;
public LFloat maxSimplificationError;
public int vertsPerPoly;
public bool buildDetailMesh;
public LFloat detailSampleDistance;
public LFloat detailSampleMaxError;
public bool filterLowHangingObstacles = true;
public bool filterLedgeSpans = true;
public bool filterWalkableLowHeightSpans = true;
public bool enableCheckpoints = true;
public bool keepIntermediateResults = false;
public DtDynamicNavMeshConfig(bool useTiles, int tileSizeX, int tileSizeZ, LFloat cellSize)
{
this.useTiles = useTiles;
this.tileSizeX = tileSizeX;
this.tileSizeZ = tileSizeZ;
this.cellSize = cellSize;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9477363671ce4a1a8f959c610d76f4c4
timeCreated: 1715335340

View File

@@ -0,0 +1,194 @@
/*
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
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.Concurrent;
using System.Collections.Generic;
using System.Linq;
using DotRecast.Core;
using DotRecast.Core.Collections;
using DotRecast.Detour.Dynamic.Colliders;
using DotRecast.Detour.Dynamic.Io;
using DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic
{
public class DtDynamicTile
{
public readonly DtVoxelTile voxelTile;
public DtDynamicTileCheckpoint checkpoint;
public RcBuilderResult recastResult;
private DtMeshData meshData;
private readonly ConcurrentDictionary<long, IDtCollider> colliders = new ConcurrentDictionary<long, IDtCollider>();
private bool dirty = true;
private long id;
public DtDynamicTile(DtVoxelTile voxelTile)
{
this.voxelTile = voxelTile;
}
public bool Build(RcBuilder builder, DtDynamicNavMeshConfig config, RcContext context)
{
if (dirty)
{
RcHeightfield heightfield = BuildHeightfield(config, context);
RcBuilderResult r = BuildRecast(builder, config, voxelTile, heightfield, context);
DtNavMeshCreateParams option = NavMeshCreateParams(voxelTile.tileX, voxelTile.tileZ, voxelTile.cellSize,
voxelTile.cellHeight, config, r);
meshData = DtNavMeshBuilder.CreateNavMeshData(option);
return true;
}
return false;
}
private RcHeightfield BuildHeightfield(DtDynamicNavMeshConfig config, RcContext context)
{
ICollection<long> rasterizedColliders = checkpoint != null
? checkpoint.colliders as ICollection<long>
: RcImmutableArray<long>.Empty;
RcHeightfield heightfield = checkpoint != null
? checkpoint.heightfield
: voxelTile.Heightfield();
foreach (var (cid, c) in colliders)
{
if (!rasterizedColliders.Contains(cid))
{
heightfield.bmax.Y = LMath.Max(heightfield.bmax.Y, c.Bounds()[4] + heightfield.ch * 2);
c.Rasterize(heightfield, context);
}
}
if (config.enableCheckpoints)
{
checkpoint = new DtDynamicTileCheckpoint(heightfield, colliders.Keys.ToHashSet());
}
return heightfield;
}
private RcBuilderResult BuildRecast(RcBuilder builder, DtDynamicNavMeshConfig config, DtVoxelTile vt,
RcHeightfield heightfield, RcContext context)
{
RcConfig rcConfig = new RcConfig(
config.useTiles, config.tileSizeX, config.tileSizeZ,
vt.borderSize,
RcPartitionType.OfValue(config.partition),
vt.cellSize, vt.cellHeight,
config.walkableSlopeAngle, config.walkableHeight, config.walkableRadius, config.walkableClimb,
config.minRegionArea, config.regionMergeArea,
config.maxEdgeLen, config.maxSimplificationError,
LMath.Min(DtDynamicNavMesh.MAX_VERTS_PER_POLY, config.vertsPerPoly),
config.detailSampleDistance, config.detailSampleMaxError,
true, true, true, default, true);
RcBuilderResult r = builder.Build(context, vt.tileX, vt.tileZ, null, rcConfig, heightfield, false);
if (config.keepIntermediateResults)
{
recastResult = r;
}
return r;
}
public void AddCollider(long cid, IDtCollider collider)
{
colliders[cid] = collider;
dirty = true;
}
public bool ContainsCollider(long cid)
{
return colliders.ContainsKey(cid);
}
public void RemoveCollider(long colliderId)
{
if (colliders.TryRemove(colliderId, out var collider))
{
dirty = true;
checkpoint = null;
}
}
private DtNavMeshCreateParams NavMeshCreateParams(int tilex, int tileZ, LFloat cellSize, LFloat cellHeight,
DtDynamicNavMeshConfig config, RcBuilderResult rcResult)
{
RcPolyMesh m_pmesh = rcResult.Mesh;
RcPolyMeshDetail m_dmesh = rcResult.MeshDetail;
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
for (int i = 0; i < m_pmesh.npolys; ++i)
{
m_pmesh.flags[i] = 1;
}
option.tileX = tilex;
option.tileZ = tileZ;
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 = config.walkableHeight;
option.walkableRadius = config.walkableRadius;
option.walkableClimb = config.walkableClimb;
option.bmin = m_pmesh.bmin;
option.bmax = m_pmesh.bmax;
option.cs = cellSize;
option.ch = cellHeight;
option.buildBvTree = true;
option.offMeshConCount = 0;
option.offMeshConVerts = new LFloat[0];
option.offMeshConRad = new LFloat[0];
option.offMeshConDir = new int[0];
option.offMeshConAreas = new int[0];
option.offMeshConFlags = new int[0];
option.offMeshConUserID = new int[0];
return option;
}
public void AddTo(DtNavMesh navMesh)
{
if (meshData != null)
{
id = navMesh.AddTile(meshData, 0, 0);
}
else
{
navMesh.RemoveTile(id);
id = 0;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3bd3585a21db4b3f8b529e903d4d5826
timeCreated: 1715335340

View File

@@ -0,0 +1,69 @@
/*
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
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.Generic;
using DotRecast.Recast;
namespace DotRecast.Detour.Dynamic
{
public class DtDynamicTileCheckpoint
{
public readonly RcHeightfield heightfield;
public readonly ISet<long> colliders;
public DtDynamicTileCheckpoint(RcHeightfield heightfield, ISet<long> colliders)
{
this.colliders = colliders;
this.heightfield = Clone(heightfield);
}
private RcHeightfield Clone(RcHeightfield source)
{
RcHeightfield clone = new RcHeightfield(source.width, source.height, source.bmin, source.bmax, source.cs, source.ch, source.borderSize);
for (int z = 0, pz = 0; z < source.height; z++, pz += source.width)
{
for (int x = 0; x < source.width; x++)
{
RcSpan span = source.spans[pz + x];
RcSpan prevCopy = null;
while (span != null)
{
RcSpan copy = new RcSpan();
copy.smin = span.smin;
copy.smax = span.smax;
copy.area = span.area;
if (prevCopy == null)
{
clone.spans[pz + x] = copy;
}
else
{
prevCopy.next = copy;
}
prevCopy = copy;
span = span.next;
}
}
}
return clone;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 433b050e76494e05ba4a78341d616bce
timeCreated: 1715335340

View File

@@ -0,0 +1,48 @@
/*
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
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.Generic;
using DotRecast.Detour.Dynamic.Colliders;
namespace DotRecast.Detour.Dynamic
{
public class DtDynamicTileColliderAdditionJob : IDtDaynmicTileJob
{
private readonly long _colliderId;
private readonly IDtCollider _collider;
private readonly ICollection<DtDynamicTile> _affectedTiles;
public DtDynamicTileColliderAdditionJob(long colliderId, IDtCollider collider, ICollection<DtDynamicTile> affectedTiles)
{
_colliderId = colliderId;
_collider = collider;
_affectedTiles = affectedTiles;
}
public ICollection<DtDynamicTile> AffectedTiles()
{
return _affectedTiles;
}
public void Process(DtDynamicTile tile)
{
tile.AddCollider(_colliderId, _collider);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 821ca3ee2d4f4a8da6c669890af921d1
timeCreated: 1715335340

View File

@@ -0,0 +1,45 @@
/*
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
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.Generic;
namespace DotRecast.Detour.Dynamic
{
public class DtDynamicTileColliderRemovalJob : IDtDaynmicTileJob
{
private readonly long colliderId;
private readonly ICollection<DtDynamicTile> _affectedTiles;
public DtDynamicTileColliderRemovalJob(long colliderId, ICollection<DtDynamicTile> affectedTiles)
{
this.colliderId = colliderId;
this._affectedTiles = affectedTiles;
}
public ICollection<DtDynamicTile> AffectedTiles()
{
return _affectedTiles;
}
public void Process(DtDynamicTile tile)
{
tile.RemoveCollider(colliderId);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e1142016290a4504b0591f5107f13dd5
timeCreated: 1715335340

View File

@@ -0,0 +1,188 @@
/*
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
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 DotRecast.Core.Numerics;
using DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic
{
/**
* Voxel raycast based on the algorithm described in
*
* "A Fast Voxel Traversal Algorithm for Ray Tracing" by John Amanatides and Andrew Woo
*/
public class DtVoxelQuery
{
private readonly RcVec3f origin;
private readonly LFloat tileWidth;
private readonly LFloat tileDepth;
private readonly Func<int, int, RcHeightfield> heightfieldProvider;
public DtVoxelQuery(RcVec3f origin, LFloat tileWidth, LFloat tileDepth, Func<int, int, RcHeightfield> heightfieldProvider)
{
this.origin = origin;
this.tileWidth = tileWidth;
this.tileDepth = tileDepth;
this.heightfieldProvider = heightfieldProvider;
}
/**
* Perform raycast using voxels heightfields.
*
* @return Optional with hit parameter (t) or empty if no hit found
*/
public bool Raycast(RcVec3f start, RcVec3f end, out LFloat hit)
{
return TraverseTiles(start, end, out hit);
}
private bool TraverseTiles(RcVec3f start, RcVec3f end, out LFloat hit)
{
LFloat relStartX = start.X - origin.X;
LFloat relStartZ = start.Z - origin.Z;
int sx = (int)LMath.Floor(relStartX / tileWidth);
int sz = (int)LMath.Floor(relStartZ / tileDepth);
int ex = (int)LMath.Floor((end.X - origin.X) / tileWidth);
int ez = (int)LMath.Floor((end.Z - origin.Z) / tileDepth);
int dx = ex - sx;
int dz = ez - sz;
int stepX = dx < 0 ? -1 : 1;
int stepZ = dz < 0 ? -1 : 1;
LFloat xRem = (tileWidth + (relStartX % tileWidth)) % tileWidth;
LFloat zRem = (tileDepth + (relStartZ % tileDepth)) % tileDepth;
LFloat tx = end.X - start.X;
LFloat tz = end.Z - start.Z;
LFloat xOffest = LMath.Abs(tx < 0 ? xRem : tileWidth - xRem);
LFloat zOffest = LMath.Abs(tz < 0 ? zRem : tileDepth - zRem);
tx = LMath.Abs(tx);
tz = LMath.Abs(tz);
LFloat tMaxX = xOffest / tx;
LFloat tMaxZ = zOffest / tz;
LFloat tDeltaX = tileWidth / tx;
LFloat tDeltaZ = tileDepth / tz;
LFloat t = 0;
while (true)
{
bool isHit = TraversHeightfield(sx, sz, start, end, t, LMath.Min(1, LMath.Min(tMaxX, tMaxZ)), out hit);
if (isHit)
{
return true;
}
if ((dx > 0 ? sx >= ex : sx <= ex) && (dz > 0 ? sz >= ez : sz <= ez))
{
break;
}
if (tMaxX < tMaxZ)
{
t = tMaxX;
tMaxX += tDeltaX;
sx += stepX;
}
else
{
t = tMaxZ;
tMaxZ += tDeltaZ;
sz += stepZ;
}
}
return false;
}
private bool TraversHeightfield(int x, int z, RcVec3f start, RcVec3f end, LFloat tMin, LFloat tMax, out LFloat hit)
{
RcHeightfield hf = heightfieldProvider.Invoke(x, z);
if (null != hf)
{
LFloat tx = end.X - start.X;
LFloat ty = end.Y - start.Y;
LFloat tz = end.Z - start.Z;
LFloat[] entry = { start.X + tMin * tx, start.Y + tMin * ty, start.Z + tMin * tz };
LFloat[] exit = { start.X + tMax * tx, start.Y + tMax * ty, start.Z + tMax * tz };
LFloat relStartX = entry[0] - hf.bmin.X;
LFloat relStartZ = entry[2] - hf.bmin.Z;
int sx = (int)LMath.Floor(relStartX / hf.cs);
int sz = (int)LMath.Floor(relStartZ / hf.cs);
int ex = (int)LMath.Floor((exit[0] - hf.bmin.X) / hf.cs);
int ez = (int)LMath.Floor((exit[2] - hf.bmin.Z) / hf.cs);
int dx = ex - sx;
int dz = ez - sz;
int stepX = dx < 0 ? -1 : 1;
int stepZ = dz < 0 ? -1 : 1;
LFloat xRem = (hf.cs + (relStartX % hf.cs)) % hf.cs;
LFloat zRem = (hf.cs + (relStartZ % hf.cs)) % hf.cs;
LFloat xOffest = LMath.Abs(tx < 0 ? xRem : hf.cs - xRem);
LFloat zOffest = LMath.Abs(tz < 0 ? zRem : hf.cs - zRem);
tx = LMath.Abs(tx);
tz = LMath.Abs(tz);
LFloat tMaxX = xOffest / tx;
LFloat tMaxZ = zOffest / tz;
LFloat tDeltaX = hf.cs / tx;
LFloat tDeltaZ = hf.cs / tz;
LFloat t = 0;
while (true)
{
if (sx >= 0 && sx < hf.width && sz >= 0 && sz < hf.height)
{
LFloat y1 = start.Y + ty * (tMin + t) - hf.bmin.Y;
LFloat y2 = start.Y + ty * (tMin + LMath.Min(tMaxX, tMaxZ)) - hf.bmin.Y;
LFloat ymin = LMath.Min(y1, y2) / hf.ch;
LFloat ymax = LMath.Max(y1, y2) / hf.ch;
RcSpan span = hf.spans[sx + sz * hf.width];
while (span != null)
{
if (span.smin <= ymin && span.smax >= ymax)
{
hit = LMath.Min(1, tMin + t);
return true;
}
span = span.next;
}
}
if ((dx > 0 ? sx >= ex : sx <= ex) && (dz > 0 ? sz >= ez : sz <= ez))
{
break;
}
if (tMaxX < tMaxZ)
{
t = tMaxX;
tMaxX += tDeltaX;
sx += stepX;
}
else
{
t = tMaxZ;
tMaxZ += tDeltaZ;
sz += stepZ;
}
}
}
hit = (LFloat)0.0f;
return false;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2d08389815a14755ba38b1be514d5512
timeCreated: 1715335340

View File

@@ -0,0 +1,30 @@
/*
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
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.Generic;
namespace DotRecast.Detour.Dynamic
{
public interface IDtDaynmicTileJob
{
ICollection<DtDynamicTile> AffectedTiles();
void Process(DtDynamicTile tile);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 48d1627002564821bcea618fe2973132
timeCreated: 1715335340

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0d0e9c4460604af49b11cd184bb1fdd4
timeCreated: 1715335338

View File

@@ -0,0 +1,170 @@
/*
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
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 DotRecast.Core;
using DotRecast.Core.Numerics;
using DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic.Io
{
public class DtVoxelFile
{
public static readonly RcByteOrder PREFERRED_BYTE_ORDER = RcByteOrder.BIG_ENDIAN;
public const int MAGIC = 'V' << 24 | 'O' << 16 | 'X' << 8 | 'L';
public const int VERSION_EXPORTER_MASK = 0xF000;
public const int VERSION_COMPRESSION_MASK = 0x0F00;
public const int VERSION_EXPORTER_RECAST4J = 0x1000;
public const int VERSION_COMPRESSION_LZ4 = 0x0100;
public int version;
public int partition = RcPartitionType.WATERSHED.Value;
public bool filterLowHangingObstacles = true;
public bool filterLedgeSpans = true;
public bool filterWalkableLowHeightSpans = true;
public LFloat walkableRadius;
public LFloat walkableHeight;
public LFloat walkableClimb;
public LFloat walkableSlopeAngle;
public LFloat cellSize;
public LFloat maxSimplificationError;
public LFloat maxEdgeLen;
public LFloat minRegionArea;
public LFloat regionMergeArea;
public int vertsPerPoly;
public bool buildMeshDetail;
public LFloat detailSampleDistance;
public LFloat detailSampleMaxError;
public bool useTiles;
public int tileSizeX;
public int tileSizeZ;
public RcVec3f rotation = new RcVec3f();
public LFloat[] bounds = new LFloat[6];
public readonly List<DtVoxelTile> tiles = new List<DtVoxelTile>();
public void AddTile(DtVoxelTile tile)
{
tiles.Add(tile);
}
public RcConfig GetConfig(DtVoxelTile tile, RcAreaModification walkbableAreaMod, bool buildMeshDetail)
{
return new RcConfig(useTiles, tileSizeX, tileSizeZ,
tile.borderSize,
RcPartitionType.OfValue(partition),
cellSize, tile.cellHeight,
walkableSlopeAngle, walkableHeight, walkableRadius, walkableClimb,
minRegionArea, regionMergeArea,
maxEdgeLen, maxSimplificationError,
vertsPerPoly,
detailSampleDistance, detailSampleMaxError,
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
walkbableAreaMod, buildMeshDetail);
}
public static DtVoxelFile From(RcConfig config, List<RcBuilderResult> results)
{
DtVoxelFile f = new DtVoxelFile();
f.version = 1;
f.partition = config.Partition;
f.filterLowHangingObstacles = config.FilterLowHangingObstacles;
f.filterLedgeSpans = config.FilterLedgeSpans;
f.filterWalkableLowHeightSpans = config.FilterWalkableLowHeightSpans;
f.walkableRadius = config.WalkableRadiusWorld;
f.walkableHeight = config.WalkableHeightWorld;
f.walkableClimb = config.WalkableClimbWorld;
f.walkableSlopeAngle = config.WalkableSlopeAngle;
f.cellSize = config.Cs;
f.maxSimplificationError = config.MaxSimplificationError;
f.maxEdgeLen = config.MaxEdgeLenWorld;
f.minRegionArea = config.MinRegionAreaWorld;
f.regionMergeArea = config.MergeRegionAreaWorld;
f.vertsPerPoly = config.MaxVertsPerPoly;
f.buildMeshDetail = config.BuildMeshDetail;
f.detailSampleDistance = config.DetailSampleDist;
f.detailSampleMaxError = config.DetailSampleMaxError;
f.useTiles = config.UseTiles;
f.tileSizeX = config.TileSizeX;
f.tileSizeZ = config.TileSizeZ;
f.bounds = new LFloat[]
{
LFloat.PositiveInfinity, LFloat.PositiveInfinity, LFloat.PositiveInfinity,
LFloat.NegativeInfinity, LFloat.NegativeInfinity, LFloat.NegativeInfinity
};
foreach (RcBuilderResult r in results)
{
f.tiles.Add(new DtVoxelTile(r.TileX, r.TileZ, r.SolidHeightfiled));
f.bounds[0] = LMath.Min(f.bounds[0], r.SolidHeightfiled.bmin.X);
f.bounds[1] = LMath.Min(f.bounds[1], r.SolidHeightfiled.bmin.Y);
f.bounds[2] = LMath.Min(f.bounds[2], r.SolidHeightfiled.bmin.Z);
f.bounds[3] = LMath.Max(f.bounds[3], r.SolidHeightfiled.bmax.X);
f.bounds[4] = LMath.Max(f.bounds[4], r.SolidHeightfiled.bmax.Y);
f.bounds[5] = LMath.Max(f.bounds[5], r.SolidHeightfiled.bmax.Z);
}
return f;
}
public static DtVoxelFile From(DtDynamicNavMesh mesh)
{
DtVoxelFile f = new DtVoxelFile();
f.version = 1;
DtDynamicNavMeshConfig config = mesh.config;
f.partition = config.partition;
f.filterLowHangingObstacles = config.filterLowHangingObstacles;
f.filterLedgeSpans = config.filterLedgeSpans;
f.filterWalkableLowHeightSpans = config.filterWalkableLowHeightSpans;
f.walkableRadius = config.walkableRadius;
f.walkableHeight = config.walkableHeight;
f.walkableClimb = config.walkableClimb;
f.walkableSlopeAngle = config.walkableSlopeAngle;
f.cellSize = config.cellSize;
f.maxSimplificationError = config.maxSimplificationError;
f.maxEdgeLen = config.maxEdgeLen;
f.minRegionArea = config.minRegionArea;
f.regionMergeArea = config.regionMergeArea;
f.vertsPerPoly = config.vertsPerPoly;
f.buildMeshDetail = config.buildDetailMesh;
f.detailSampleDistance = config.detailSampleDistance;
f.detailSampleMaxError = config.detailSampleMaxError;
f.useTiles = config.useTiles;
f.tileSizeX = config.tileSizeX;
f.tileSizeZ = config.tileSizeZ;
f.bounds = new LFloat[]
{
LFloat.PositiveInfinity, LFloat.PositiveInfinity, LFloat.PositiveInfinity,
LFloat.NegativeInfinity, LFloat.NegativeInfinity, LFloat.NegativeInfinity
};
foreach (DtVoxelTile vt in mesh.VoxelTiles())
{
RcHeightfield heightfield = vt.Heightfield();
f.tiles.Add(new DtVoxelTile(vt.tileX, vt.tileZ, heightfield));
f.bounds[0] = LMath.Min(f.bounds[0], vt.boundsMin.X);
f.bounds[1] = LMath.Min(f.bounds[1], vt.boundsMin.Y);
f.bounds[2] = LMath.Min(f.bounds[2], vt.boundsMin.Z);
f.bounds[3] = LMath.Max(f.bounds[3], vt.boundsMax.X);
f.bounds[4] = LMath.Max(f.bounds[4], vt.boundsMax.Y);
f.bounds[5] = LMath.Max(f.bounds[5], vt.boundsMax.Z);
}
return f;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cd9487a5961c425eb87ca603c28fec15
timeCreated: 1715335338

View File

@@ -0,0 +1,150 @@
/*
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
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.IO;
using DotRecast.Core;
using DotRecast.Core.Numerics;
using DotRecast.Detour.Io;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic.Io
{
public class DtVoxelFileReader
{
private readonly IRcCompressor _compressor;
public DtVoxelFileReader(IRcCompressor compressor)
{
_compressor = compressor;
}
public DtVoxelFile Read(BinaryReader stream)
{
RcByteBuffer buf = IOUtils.ToByteBuffer(stream);
DtVoxelFile file = new DtVoxelFile();
int magic = buf.GetInt();
if (magic != DtVoxelFile.MAGIC)
{
magic = IOUtils.SwapEndianness(magic);
if (magic != DtVoxelFile.MAGIC)
{
throw new IOException("Invalid magic");
}
buf.Order(buf.Order() == RcByteOrder.BIG_ENDIAN ? RcByteOrder.LITTLE_ENDIAN : RcByteOrder.BIG_ENDIAN);
}
file.version = buf.GetInt();
bool isExportedFromAstar = (file.version & DtVoxelFile.VERSION_EXPORTER_MASK) == 0;
bool compression = (file.version & DtVoxelFile.VERSION_COMPRESSION_MASK) == DtVoxelFile.VERSION_COMPRESSION_LZ4;
file.walkableRadius = buf.GetFloat();
file.walkableHeight = buf.GetFloat();
file.walkableClimb = buf.GetFloat();
file.walkableSlopeAngle = buf.GetFloat();
file.cellSize = buf.GetFloat();
file.maxSimplificationError = buf.GetFloat();
file.maxEdgeLen = buf.GetFloat();
file.minRegionArea = (int)buf.GetFloat();
if (!isExportedFromAstar)
{
file.regionMergeArea = buf.GetFloat();
file.vertsPerPoly = buf.GetInt();
file.buildMeshDetail = buf.Get() != 0;
file.detailSampleDistance = buf.GetFloat();
file.detailSampleMaxError = buf.GetFloat();
}
else
{
file.regionMergeArea = 6 * file.minRegionArea;
file.vertsPerPoly = 6;
file.buildMeshDetail = true;
file.detailSampleDistance = file.maxEdgeLen * (LFloat)0.5f;
file.detailSampleMaxError = file.maxSimplificationError * (LFloat)0.8f;
}
file.useTiles = buf.Get() != 0;
file.tileSizeX = buf.GetInt();
file.tileSizeZ = buf.GetInt();
file.rotation.X = buf.GetFloat();
file.rotation.Y = buf.GetFloat();
file.rotation.Z = buf.GetFloat();
file.bounds[0] = buf.GetFloat();
file.bounds[1] = buf.GetFloat();
file.bounds[2] = buf.GetFloat();
file.bounds[3] = buf.GetFloat();
file.bounds[4] = buf.GetFloat();
file.bounds[5] = buf.GetFloat();
if (isExportedFromAstar)
{
// bounds are saved as center + size
file.bounds[0] -= (LFloat)0.5f * file.bounds[3];
file.bounds[1] -= (LFloat)0.5f * file.bounds[4];
file.bounds[2] -= (LFloat)0.5f * file.bounds[5];
file.bounds[3] += file.bounds[0];
file.bounds[4] += file.bounds[1];
file.bounds[5] += file.bounds[2];
}
int tileCount = buf.GetInt();
for (int tile = 0; tile < tileCount; tile++)
{
int tileX = buf.GetInt();
int tileZ = buf.GetInt();
int width = buf.GetInt();
int depth = buf.GetInt();
int borderSize = buf.GetInt();
RcVec3f boundsMin = new RcVec3f();
boundsMin.X = buf.GetFloat();
boundsMin.Y = buf.GetFloat();
boundsMin.Z = buf.GetFloat();
RcVec3f boundsMax = new RcVec3f();
boundsMax.X = buf.GetFloat();
boundsMax.Y = buf.GetFloat();
boundsMax.Z = buf.GetFloat();
if (isExportedFromAstar)
{
// bounds are local
boundsMin.X += file.bounds[0];
boundsMin.Y += file.bounds[1];
boundsMin.Z += file.bounds[2];
boundsMax.X += file.bounds[0];
boundsMax.Y += file.bounds[1];
boundsMax.Z += file.bounds[2];
}
LFloat cellSize = buf.GetFloat();
LFloat cellHeight = buf.GetFloat();
int voxelSize = buf.GetInt();
int position = buf.Position();
byte[] bytes = buf.ReadBytes(voxelSize).ToArray();
if (compression)
{
bytes = _compressor.Decompress(bytes);
}
RcByteBuffer data = new RcByteBuffer(bytes);
data.Order(buf.Order());
file.AddTile(new DtVoxelTile(tileX, tileZ, width, depth, boundsMin, boundsMax, cellSize, cellHeight, borderSize, data));
buf.Position(position + voxelSize);
}
return file;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cd66a05921a942558006c63396be5407
timeCreated: 1715335338

View File

@@ -0,0 +1,102 @@
/*
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
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.IO;
using DotRecast.Core;
using DotRecast.Core.Numerics;
using DotRecast.Detour.Io;
namespace DotRecast.Detour.Dynamic.Io
{
public class DtVoxelFileWriter : DtWriter
{
private readonly IRcCompressor _compressor;
public DtVoxelFileWriter(IRcCompressor compressor)
{
_compressor = compressor;
}
public void Write(BinaryWriter stream, DtVoxelFile f, bool compression)
{
Write(stream, f, DtVoxelFile.PREFERRED_BYTE_ORDER, compression);
}
public void Write(BinaryWriter stream, DtVoxelFile f, RcByteOrder byteOrder, bool compression)
{
Write(stream, DtVoxelFile.MAGIC, byteOrder);
Write(stream, DtVoxelFile.VERSION_EXPORTER_RECAST4J | (compression ? DtVoxelFile.VERSION_COMPRESSION_LZ4 : 0), byteOrder);
Write(stream, f.walkableRadius, byteOrder);
Write(stream, f.walkableHeight, byteOrder);
Write(stream, f.walkableClimb, byteOrder);
Write(stream, f.walkableSlopeAngle, byteOrder);
Write(stream, f.cellSize, byteOrder);
Write(stream, f.maxSimplificationError, byteOrder);
Write(stream, f.maxEdgeLen, byteOrder);
Write(stream, f.minRegionArea, byteOrder);
Write(stream, f.regionMergeArea, byteOrder);
Write(stream, f.vertsPerPoly, byteOrder);
Write(stream, f.buildMeshDetail);
Write(stream, f.detailSampleDistance, byteOrder);
Write(stream, f.detailSampleMaxError, byteOrder);
Write(stream, f.useTiles);
Write(stream, f.tileSizeX, byteOrder);
Write(stream, f.tileSizeZ, byteOrder);
Write(stream, f.rotation.X, byteOrder);
Write(stream, f.rotation.Y, byteOrder);
Write(stream, f.rotation.Z, byteOrder);
Write(stream, f.bounds[0], byteOrder);
Write(stream, f.bounds[1], byteOrder);
Write(stream, f.bounds[2], byteOrder);
Write(stream, f.bounds[3], byteOrder);
Write(stream, f.bounds[4], byteOrder);
Write(stream, f.bounds[5], byteOrder);
Write(stream, f.tiles.Count, byteOrder);
foreach (DtVoxelTile t in f.tiles)
{
WriteTile(stream, t, byteOrder, compression);
}
}
public void WriteTile(BinaryWriter stream, DtVoxelTile tile, RcByteOrder byteOrder, bool compression)
{
Write(stream, tile.tileX, byteOrder);
Write(stream, tile.tileZ, byteOrder);
Write(stream, tile.width, byteOrder);
Write(stream, tile.depth, byteOrder);
Write(stream, tile.borderSize, byteOrder);
Write(stream, tile.boundsMin.X, byteOrder);
Write(stream, tile.boundsMin.Y, byteOrder);
Write(stream, tile.boundsMin.Z, byteOrder);
Write(stream, tile.boundsMax.X, byteOrder);
Write(stream, tile.boundsMax.Y, byteOrder);
Write(stream, tile.boundsMax.Z, byteOrder);
Write(stream, tile.cellSize, byteOrder);
Write(stream, tile.cellHeight, byteOrder);
byte[] bytes = tile.spanData;
if (compression)
{
bytes = _compressor.Compress(bytes);
}
Write(stream, bytes.Length, byteOrder);
stream.Write(bytes);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e2bbfda0005f432cb0c8d78264f6cf82
timeCreated: 1715335338

View File

@@ -0,0 +1,221 @@
/*
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
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 DotRecast.Core;
using DotRecast.Core.Numerics;
using DotRecast.Recast;
using JNGame.Math;
namespace DotRecast.Detour.Dynamic.Io
{
public class DtVoxelTile
{
private const int SERIALIZED_SPAN_COUNT_BYTES = 2;
private const int SERIALIZED_SPAN_BYTES = 12;
public readonly int tileX;
public readonly int tileZ;
public readonly int borderSize;
public int width;
public int depth;
public readonly RcVec3f boundsMin;
public RcVec3f boundsMax;
public LFloat cellSize;
public LFloat cellHeight;
public readonly byte[] spanData;
public DtVoxelTile(int tileX, int tileZ, int width, int depth, RcVec3f boundsMin, RcVec3f boundsMax, LFloat cellSize,
LFloat cellHeight, int borderSize, RcByteBuffer buffer)
{
this.tileX = tileX;
this.tileZ = tileZ;
this.width = width;
this.depth = depth;
this.boundsMin = boundsMin;
this.boundsMax = boundsMax;
this.cellSize = cellSize;
this.cellHeight = cellHeight;
this.borderSize = borderSize;
spanData = ToByteArray(buffer, width, depth, DtVoxelFile.PREFERRED_BYTE_ORDER);
}
public DtVoxelTile(int tileX, int tileZ, RcHeightfield heightfield)
{
this.tileX = tileX;
this.tileZ = tileZ;
width = heightfield.width;
depth = heightfield.height;
boundsMin = heightfield.bmin;
boundsMax = heightfield.bmax;
cellSize = heightfield.cs;
cellHeight = heightfield.ch;
borderSize = heightfield.borderSize;
spanData = SerializeSpans(heightfield, DtVoxelFile.PREFERRED_BYTE_ORDER);
}
public RcHeightfield Heightfield()
{
return DtVoxelFile.PREFERRED_BYTE_ORDER == RcByteOrder.BIG_ENDIAN ? HeightfieldBE() : HeightfieldLE();
}
private RcHeightfield HeightfieldBE()
{
RcHeightfield hf = new RcHeightfield(width, depth, boundsMin, boundsMax, cellSize, cellHeight, borderSize);
int position = 0;
for (int z = 0, pz = 0; z < depth; z++, pz += width)
{
for (int x = 0; x < width; x++)
{
RcSpan prev = null;
int spanCount = RcByteUtils.GetShortBE(spanData, position);
position += 2;
for (int s = 0; s < spanCount; s++)
{
RcSpan span = new RcSpan();
span.smin = RcByteUtils.GetIntBE(spanData, position);
position += 4;
span.smax = RcByteUtils.GetIntBE(spanData, position);
position += 4;
span.area = RcByteUtils.GetIntBE(spanData, position);
position += 4;
if (prev == null)
{
hf.spans[pz + x] = span;
}
else
{
prev.next = span;
}
prev = span;
}
}
}
return hf;
}
private RcHeightfield HeightfieldLE()
{
RcHeightfield hf = new RcHeightfield(width, depth, boundsMin, boundsMax, cellSize, cellHeight, borderSize);
int position = 0;
for (int z = 0, pz = 0; z < depth; z++, pz += width)
{
for (int x = 0; x < width; x++)
{
RcSpan prev = null;
int spanCount = RcByteUtils.GetShortLE(spanData, position);
position += 2;
for (int s = 0; s < spanCount; s++)
{
RcSpan span = new RcSpan();
span.smin = RcByteUtils.GetIntLE(spanData, position);
position += 4;
span.smax = RcByteUtils.GetIntLE(spanData, position);
position += 4;
span.area = RcByteUtils.GetIntLE(spanData, position);
position += 4;
if (prev == null)
{
hf.spans[pz + x] = span;
}
else
{
prev.next = span;
}
prev = span;
}
}
}
return hf;
}
private byte[] SerializeSpans(RcHeightfield heightfield, RcByteOrder order)
{
int[] counts = new int[heightfield.width * heightfield.height];
int totalCount = 0;
for (int z = 0, pz = 0; z < heightfield.height; z++, pz += heightfield.width)
{
for (int x = 0; x < heightfield.width; x++)
{
RcSpan span = heightfield.spans[pz + x];
while (span != null)
{
counts[pz + x]++;
totalCount++;
span = span.next;
}
}
}
byte[] data = new byte[totalCount * SERIALIZED_SPAN_BYTES + counts.Length * SERIALIZED_SPAN_COUNT_BYTES];
int position = 0;
for (int z = 0, pz = 0; z < heightfield.height; z++, pz += heightfield.width)
{
for (int x = 0; x < heightfield.width; x++)
{
position = RcByteUtils.PutShort(counts[pz + x], data, position, order);
RcSpan span = heightfield.spans[pz + x];
while (span != null)
{
position = RcByteUtils.PutInt(span.smin, data, position, order);
position = RcByteUtils.PutInt(span.smax, data, position, order);
position = RcByteUtils.PutInt(span.area, data, position, order);
span = span.next;
}
}
}
return data;
}
private byte[] ToByteArray(RcByteBuffer buf, int width, int height, RcByteOrder order)
{
byte[] data;
if (buf.Order() == order)
{
data = buf.ReadBytes(buf.Limit()).ToArray();
}
else
{
data = new byte[buf.Limit()];
int l = width * height;
int position = 0;
for (int i = 0; i < l; i++)
{
int count = buf.GetShort();
RcByteUtils.PutShort(count, data, position, order);
position += 2;
for (int j = 0; j < count; j++)
{
RcByteUtils.PutInt(buf.GetInt(), data, position, order);
position += 4;
RcByteUtils.PutInt(buf.GetInt(), data, position, order);
position += 4;
RcByteUtils.PutInt(buf.GetInt(), data, position, order);
position += 4;
}
}
}
return data;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 91a85b5d1fb946a2ba40c5fa9695644d
timeCreated: 1715335338