forked from mirror/DotRecast
Merge branch 'main'
# Conflicts: # src/DotRecast.Detour.Crowd/DtObstacleAvoidanceQuery.cs # src/DotRecast.Detour/DtBVNode.cs # src/DotRecast.Detour/DtNavMesh.cs # src/DotRecast.Detour/DtNavMeshQuery.cs # src/DotRecast.Detour/DtPoly.cs # src/DotRecast.Detour/DtPolyDetail.cs # src/DotRecast.Recast.Toolset/RcNavMeshBuildSettings.cs # test/DotRecast.Core.Test/RcRentedArrayTest.cs
This commit is contained in:
commit
0f28fa26ec
|
@ -39,7 +39,10 @@ jobs:
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v4
|
||||||
with:
|
with:
|
||||||
dotnet-version: ${{ matrix.dotnet-version }}.x
|
dotnet-version: |
|
||||||
|
6
|
||||||
|
7
|
||||||
|
8
|
||||||
|
|
||||||
- name: Restore dependencies
|
- name: Restore dependencies
|
||||||
run: dotnet restore
|
run: dotnet restore
|
||||||
|
|
110
CHANGELOG.md
110
CHANGELOG.md
|
@ -6,12 +6,122 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
## [Unreleased] - yyyy-mm-dd
|
## [Unreleased] - yyyy-mm-dd
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Added RcBinaryMinHeap ([@Sarofc](https://github.com/Sarofc))
|
||||||
|
- Added DotRecast.Benchmark ([@Sarofc](https://github.com/Sarofc))
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fix raycast shortcuts ([@Sarofc](https://github.com/Sarofc)) [#72](https://github.com/ikpil/DotRecast/issues/72)
|
||||||
|
- Fix dynamic mesh bounds calculation ([@ppiastucki](https://github.com/ppiastucki)) [#77](https://github.com/ikpil/DotRecast/issues/77)
|
||||||
|
- issuer : [@OhJeongrok](https://github.com/OhJeongrok)
|
||||||
|
- Fix Support non-tiled dynamic nav meshes ([@ppiastucki](https://github.com/ppiastucki))
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Changed data structure of 'neis' from List<byte> to byte[] for optimized memory usage and improved access speed in `DtLayerMonotoneRegion`
|
||||||
|
- Changed new RcVec3f[3] to stackalloc RcVec3f[3] in DtNavMesh.GetPolyHeight() to reduce heap allocation
|
||||||
|
- Changed memory handling to use stackalloc in DtNavMeshQuery.GetPolyWallSegments for reducing SOH
|
||||||
|
- Changed DtNavMeshQuery.GetPolyWallSegments() to use Span<T> for enhanced performance, memory efficiency.
|
||||||
|
- Changed bmin/bmax from int[] to RcVec3i for improved memory efficiency
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Nothing
|
||||||
|
|
||||||
|
### Special Thanks
|
||||||
|
- [@Doprez](https://github.com/Doprez)
|
||||||
|
|
||||||
|
|
||||||
|
## [2024.3.1] - 2024-07-09
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Nothing
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed bug where the dynamic voxel save file browser doesn't appear in `Recast.Demo`
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Changed to reuse samples and edges list in `BuildPolyDetail()`
|
||||||
|
- Changed `heights`, `areas`, `cons`, and `regs` arrays to byte arrays for uniformity and efficiency in `DtTileCacheLayer`
|
||||||
|
- Changed `reg`, `area` arrays to byte arrays for uniformity and efficiency in `DtTileCacheContour`
|
||||||
|
- Changed `RcChunkyTriMesh` to separate the function and variable.
|
||||||
|
- Changed to consolidate vector-related functions into one place.
|
||||||
|
- Changed stack handling from List to a fixed-size array with manual index management for optimization in `RcLayers.BuildHeightfieldLayers()`
|
||||||
|
- Changed to use Span<byte> and stackalloc for improved performance and memory management in `RcLayers.BuildHeightfieldLayers()`
|
||||||
|
- Changed vertCount and triCount to byte in `DtPolyDetail`
|
||||||
|
- Changed `new float[]` to `stackalloc float[]` in `DtConvexConvexIntersections.Intersect()`
|
||||||
|
- Changed agents management from list to dictionary in `DtCrowd`
|
||||||
|
- Changed to efficiently stack nearby DtCrowdAgents in `DtCrowd.GetNeighbours()`
|
||||||
|
- Changed to limit neighbor search to a maximum count and use array for memory efficiency in `DtCrowd.AddNeighbour()`
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Removed RcMeshDetails.VdistSq2(float[], float[])
|
||||||
|
- Removed RcVecUtils.Dot()
|
||||||
|
- Removed RcVecUtils.Scale()
|
||||||
|
- Removed RcVecUtils.Subtract(RcVec3f i, float[] verts, int j)
|
||||||
|
- Removed RcVecUtils.Subtract(float[] verts, int i, int j)
|
||||||
|
- Removed RcVecUtils.Min(), RcVecUtils.Max()
|
||||||
|
- Removed RcVecUtils.Create(float[] values)
|
||||||
|
- Removed RcVecUtils.Dot2D(this RcVec3f @this, Span<float> v, int vi)
|
||||||
|
|
||||||
|
### Special Thanks
|
||||||
|
- [@Doprez](https://github.com/Doprez)
|
||||||
|
|
||||||
|
## [2024.2.3] - 2024-06-03
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Added `DtCollectPolysQuery` and `FindCollectPolyTest`
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Nothing
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Changed `IDtPolyQuery` interface to make `Process()` more versatile
|
||||||
|
- Changed `PolyQueryInvoker` to `DtActionPolyQuery`
|
||||||
|
- Changed `DtTileCacheBuilder` to a static class
|
||||||
|
- Changed `DtTileCacheLayerHeaderReader` to a static class
|
||||||
|
- Changed `Dictionary<int, List<DtMeshTile>>` to `DtMeshTile[]` to optimize memory usage
|
||||||
|
- Changed `MAX_STEER_POINTS` from class constant to local.
|
||||||
|
- Changed `List<DtStraightPath>` to `Span<DtStraightPath>` for enhanced memory efficiency
|
||||||
|
- Changed `DtWriter` to a static class and renamed it to `RcIO`
|
||||||
|
- Changed class `Trajectory` to interface `ITrajectory`
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Nothing
|
||||||
|
|
||||||
|
### Special Thanks
|
||||||
|
- [@Doprez](https://github.com/Doprez)
|
||||||
|
|
||||||
|
|
||||||
|
## [2024.2.2] - 2024-05-18
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Added RcSpans UnitTest
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Nothing
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Changed class name of static functions to RcRecast and DtDetour
|
||||||
|
- Changed DtLink class member variable type from int to byte
|
||||||
|
- Changed initialization in DtNavMesh constructor to Init() function.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Nothing
|
||||||
|
|
||||||
|
### Special Thanks
|
||||||
|
- [@Doprez](https://github.com/Doprez)
|
||||||
|
|
||||||
|
|
||||||
|
## [2024.2.1] - 2024-05-04
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Added RcCircularBuffer<T> [@ikpil](https://github.com/ikpil)
|
- Added RcCircularBuffer<T> [@ikpil](https://github.com/ikpil)
|
||||||
- Added struct DtCrowdScopedTimer to avoid allocations in scoped timer calls. [@wrenge](https://github.com/wrenge)
|
- Added struct DtCrowdScopedTimer to avoid allocations in scoped timer calls. [@wrenge](https://github.com/wrenge)
|
||||||
- Added struct RcScopedTimer to avoid allocations in RcContext scoped timer [@ikpil](https://github.com/ikpil)
|
- Added struct RcScopedTimer to avoid allocations in RcContext scoped timer [@ikpil](https://github.com/ikpil)
|
||||||
|
- Added RcSpans [@ikpil](https://github.com/ikpil)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
- SOH issue [#14](https://github.com/ikpil/DotRecast/issues/41)
|
||||||
|
- Optimization: reduce number of allocations on hot path. [@awgil](https://github.com/awgil)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Changed DtPathCorridor.Init(int maxPath) function to allow setting the maximum path [@ikpil](https://github.com/ikpil)
|
- Changed DtPathCorridor.Init(int maxPath) function to allow setting the maximum path [@ikpil](https://github.com/ikpil)
|
||||||
|
|
|
@ -39,6 +39,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotRecast.Detour.Extras.Tes
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotRecast.Detour.TileCache.Test", "test\DotRecast.Detour.TileCache.Test\DotRecast.Detour.TileCache.Test.csproj", "{3CAA7306-088E-4373-A406-99755CC2B605}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotRecast.Detour.TileCache.Test", "test\DotRecast.Detour.TileCache.Test\DotRecast.Detour.TileCache.Test.csproj", "{3CAA7306-088E-4373-A406-99755CC2B605}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotRecast.Benchmark", "test\DotRecast.Benchmark\DotRecast.Benchmark.csproj", "{D1EFC625-D095-4208-98A2-112B73CB40B0}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tool", "tool", "{9C213609-BF13-4024-816E-A6ADD641DF24}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotRecast.Tool.PublishToUniRecast", "tool\DotRecast.Tool.PublishToUniRecast\DotRecast.Tool.PublishToUniRecast.csproj", "{1822BBA8-FE4E-4C5F-B9C0-3E20E6353446}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -112,23 +118,33 @@ Global
|
||||||
{10395C8F-DFBD-4263-8A20-EA3500A6E55A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{10395C8F-DFBD-4263-8A20-EA3500A6E55A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{10395C8F-DFBD-4263-8A20-EA3500A6E55A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{10395C8F-DFBD-4263-8A20-EA3500A6E55A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{10395C8F-DFBD-4263-8A20-EA3500A6E55A}.Release|Any CPU.Build.0 = Release|Any CPU
|
{10395C8F-DFBD-4263-8A20-EA3500A6E55A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D1EFC625-D095-4208-98A2-112B73CB40B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D1EFC625-D095-4208-98A2-112B73CB40B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D1EFC625-D095-4208-98A2-112B73CB40B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D1EFC625-D095-4208-98A2-112B73CB40B0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1822BBA8-FE4E-4C5F-B9C0-3E20E6353446}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1822BBA8-FE4E-4C5F-B9C0-3E20E6353446}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1822BBA8-FE4E-4C5F-B9C0-3E20E6353446}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1822BBA8-FE4E-4C5F-B9C0-3E20E6353446}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{FFE40BBF-843B-41FA-8504-F4ABD166762E} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
{FFE40BBF-843B-41FA-8504-F4ABD166762E} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
||||||
{38933A87-4568-40A5-A3DA-E2445E8C2B99} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
{38933A87-4568-40A5-A3DA-E2445E8C2B99} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
||||||
{C19E4BFA-63A0-4815-9815-869A9DC52DBC} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
{C19E4BFA-63A0-4815-9815-869A9DC52DBC} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
||||||
{88754FE2-A05A-4D4D-A81A-90418AD32362} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
|
||||||
{554CB5BD-D58A-4856-BFE1-666A62C9BEA3} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
|
||||||
{FA7EF26A-BA47-43FD-86F8-0A33CFDF643F} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
{FA7EF26A-BA47-43FD-86F8-0A33CFDF643F} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
||||||
{F9C5B52E-C01D-4514-94E9-B1A6895352E2} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
|
||||||
{53AF87DA-37F8-4504-B623-B2113F4438CA} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
{53AF87DA-37F8-4504-B623-B2113F4438CA} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
||||||
{67C68B34-118A-439C-88E1-D6D1ED78DC59} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
|
||||||
{17E4F2F0-FC27-416E-9CB6-9F2CAAC49C9D} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
{17E4F2F0-FC27-416E-9CB6-9F2CAAC49C9D} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
||||||
{7BAA69B2-EDC7-4603-B16F-BC7B24353F81} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
|
||||||
{DEB16B90-CCD4-497E-A2E9-4CC66FD7EF47} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
{DEB16B90-CCD4-497E-A2E9-4CC66FD7EF47} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
||||||
{3CAA7306-088E-4373-A406-99755CC2B605} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
|
||||||
{023E1E6A-4895-4573-89AE-3D5D8E0B39C8} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
{023E1E6A-4895-4573-89AE-3D5D8E0B39C8} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
||||||
{DF987948-8C23-4337-AF83-D87D6407518D} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
{DF987948-8C23-4337-AF83-D87D6407518D} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
||||||
|
{88754FE2-A05A-4D4D-A81A-90418AD32362} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
||||||
|
{554CB5BD-D58A-4856-BFE1-666A62C9BEA3} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
||||||
|
{F9C5B52E-C01D-4514-94E9-B1A6895352E2} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
||||||
|
{67C68B34-118A-439C-88E1-D6D1ED78DC59} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
||||||
|
{7BAA69B2-EDC7-4603-B16F-BC7B24353F81} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
||||||
|
{3CAA7306-088E-4373-A406-99755CC2B605} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
||||||
{10395C8F-DFBD-4263-8A20-EA3500A6E55A} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
{10395C8F-DFBD-4263-8A20-EA3500A6E55A} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
||||||
|
{D1EFC625-D095-4208-98A2-112B73CB40B0} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
||||||
|
{1822BBA8-FE4E-4C5F-B9C0-3E20E6353446} = {9C213609-BF13-4024-816E-A6ADD641DF24}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
38
README.md
38
README.md
|
@ -1,28 +1,22 @@
|
||||||
<h1 align="center">DotRecast</h1>
|
# DotRecast
|
||||||
<p align="center">
|
|
||||||
<i>DotRecast is C# Recast & Detour, a port of <a href="https://github.com/recastnavigation/recastnavigation">recastnavigation</a> and <a href="https://github.com/ppiastucki/recast4j">recast4j</a> to the C# language.</i>
|
*DotRecast is C# Recast & Detour, a port of [recastnavigation](https://github.com/recastnavigation/recastnavigation) and [recast4j](https://github.com/ppiastucki/recast4j) to the C# language.*
|
||||||
</p>
|
*If you'd like to support the project, we'd appreciate starring(⭐) our repos on Github for more visibility.*
|
||||||
<p align="center">
|
|
||||||
<i>If you'd like to support the project, we'd appreciate starring(⭐) our repos on Github for more visibility.</i>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<p align="center">
|
![GitHub License](https://img.shields.io/github/license/ikpil/DotRecast?style=for-the-badge)
|
||||||
<img alt="![GitHub License]" src="https://img.shields.io/github/license/ikpil/DotRecast?style=for-the-badge">
|
![Languages](https://img.shields.io/github/languages/top/ikpil/DotRecast?style=for-the-badge)
|
||||||
<img alt="Languages" src="https://img.shields.io/github/languages/top/ikpil/DotRecast?style=for-the-badge">
|
![GitHub repo size](https://img.shields.io/github/repo-size/ikpil/DotRecast?style=for-the-badge)
|
||||||
<img alt="GitHub repo size" src="https://img.shields.io/github/repo-size/ikpil/DotRecast?style=for-the-badge">
|
[![GitHub Repo stars](https://img.shields.io/github/stars/ikpil/DotRecast?style=for-the-badge&logo=github)](https://github.com/ikpil/DotRecast)
|
||||||
<a href="https://github.com/ikpil/DotRecast"><img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/ikpil/DotRecast?style=for-the-badge&logo=github"></a>
|
[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/ikpil/DotRecast/dotnet.yml?style=for-the-badge&logo=github)](https://github.com/ikpil/DotRecast/actions/workflows/dotnet.yml)
|
||||||
<a href="https://github.com/ikpil/DotRecast/actions/workflows/dotnet.yml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/ikpil/DotRecast/dotnet.yml?style=for-the-badge&logo=github"></a>
|
[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/ikpil/DotRecast/codeql.yml?style=for-the-badge&logo=github&label=CODEQL)](https://github.com/ikpil/DotRecast/actions/workflows/codeql.yml)
|
||||||
<a href="https://github.com/ikpil/DotRecast/actions/workflows/codeql.yml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/ikpil/DotRecast/codeql.yml?style=for-the-badge&logo=github&label=CODEQL"></a>
|
[![GitHub commit activity](https://img.shields.io/github/commit-activity/m/ikpil/DotRecast?style=for-the-badge&logo=github)](https://github.com/ikpil/DotRecast/commits)
|
||||||
<a href="https://github.com/ikpil/DotRecast/commits"><img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/ikpil/DotRecast?style=for-the-badge&logo=github"></a>
|
[![GitHub issues](https://img.shields.io/github/issues-raw/ikpil/DotRecast?style=for-the-badge&logo=github&color=44cc11)](https://github.com/ikpil/DotRecast/issues)
|
||||||
<a href="https://github.com/ikpil/DotRecast/issues"><img alt="GitHub issues" src="https://img.shields.io/github/issues-raw/ikpil/DotRecast?style=for-the-badge&logo=github&color=44cc11"></a>
|
[![GitHub closed issues](https://img.shields.io/github/issues-closed-raw/ikpil/DotRecast?style=for-the-badge&logo=github&color=a371f7)](https://github.com/ikpil/DotRecast/issues)
|
||||||
<a href="https://github.com/ikpil/DotRecast/issues"><img alt="GitHub closed issues" src="https://img.shields.io/github/issues-closed-raw/ikpil/DotRecast?style=for-the-badge&logo=github&color=a371f7"></a>
|
[![NuGet Version](https://img.shields.io/nuget/vpre/DotRecast.Core?style=for-the-badge&logo=nuget)](https://www.nuget.org/packages/DotRecast.Core)
|
||||||
<a href="https://www.nuget.org/packages/DotRecast.Core"><img alt="NuGet Version" src="https://img.shields.io/nuget/vpre/DotRecast.Core?style=for-the-badge&logo=nuget"></a>
|
[![NuGet Downloads](https://img.shields.io/nuget/dt/DotRecast.Core?style=for-the-badge&logo=nuget)](https://www.nuget.org/packages/DotRecast.Core)
|
||||||
<a href="https://www.nuget.org/packages/DotRecast.Core"><img alt="NuGet Downloads" src="https://img.shields.io/nuget/dt/DotRecast.Core?style=for-the-badge&logo=nuget"></a>
|
[![GitHub Sponsors](https://img.shields.io/github/sponsors/ikpil?style=for-the-badge&logo=GitHub-Sponsors&link=https%3A%2F%2Fgithub.com%2Fsponsors%2Fikpil)](https://github.com/sponsors/ikpil)
|
||||||
<a href="https://visitorbadge.io/status?path=ikpil%2FDotRecast"><img alt="Visitors" src="https://api.visitorbadge.io/api/daily?path=ikpil%2FDotRecast&countColor=%23263759"></a>
|
|
||||||
<a href="https://github.com/sponsors/ikpil"><img alt="GitHub Sponsors" src="https://img.shields.io/github/sponsors/ikpil?style=for-the-badge&logo=GitHub-Sponsors&link=https%3A%2F%2Fgithub.com%2Fsponsors%2Fikpil"></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Security;
|
using System.Net.Security;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Core.Collections
|
namespace DotRecast.Core.Collections
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace DotRecast.Core.Collections
|
||||||
|
{
|
||||||
|
public sealed class RcBinaryMinHeap<T>
|
||||||
|
{
|
||||||
|
private readonly List<T> _items;
|
||||||
|
private readonly Comparison<T> _comparision;
|
||||||
|
|
||||||
|
public int Count => _items.Count;
|
||||||
|
public int Capacity => _items.Capacity;
|
||||||
|
|
||||||
|
public RcBinaryMinHeap(Comparison<T> comparision)
|
||||||
|
{
|
||||||
|
_items = new List<T>();
|
||||||
|
_comparision = comparision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RcBinaryMinHeap(int capacity, Comparison<T> comparison) : this(comparison)
|
||||||
|
{
|
||||||
|
if (capacity <= 0)
|
||||||
|
throw new ArgumentException("capacity must greater than zero");
|
||||||
|
|
||||||
|
_items = new List<T>(capacity);
|
||||||
|
_comparision = comparison;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Push(T val)
|
||||||
|
{
|
||||||
|
_items.Add(val);
|
||||||
|
SiftUp(_items.Count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Pop()
|
||||||
|
{
|
||||||
|
var min = Peek();
|
||||||
|
RemoveMin();
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveMin()
|
||||||
|
{
|
||||||
|
if (_items.Count == 0)
|
||||||
|
{
|
||||||
|
Throw();
|
||||||
|
static void Throw() => throw new InvalidOperationException("no element to pop");
|
||||||
|
}
|
||||||
|
|
||||||
|
int last = _items.Count - 1;
|
||||||
|
Swap(0, last);
|
||||||
|
_items.RemoveAt(last);
|
||||||
|
|
||||||
|
MinHeapify(0, last - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public T Top()
|
||||||
|
{
|
||||||
|
return _items[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public T Peek()
|
||||||
|
{
|
||||||
|
if (IsEmpty())
|
||||||
|
{
|
||||||
|
throw new Exception("Heap is empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return _items[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool Modify(T node)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _items.Count; i++)
|
||||||
|
{
|
||||||
|
if (_items[i].Equals(node))
|
||||||
|
{
|
||||||
|
SiftUp(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
_items.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool IsEmpty()
|
||||||
|
{
|
||||||
|
return 0 == _items.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SiftUp(int nodeIndex)
|
||||||
|
{
|
||||||
|
int parent = (nodeIndex - 1) / 2;
|
||||||
|
while (_comparision.Invoke(_items[nodeIndex], _items[parent]) < 0)
|
||||||
|
{
|
||||||
|
Swap(parent, nodeIndex);
|
||||||
|
nodeIndex = parent;
|
||||||
|
parent = (nodeIndex - 1) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void MinHeapify(int nodeIndex, int lastIndex)
|
||||||
|
{
|
||||||
|
int left = (nodeIndex * 2) + 1;
|
||||||
|
int right = left + 1;
|
||||||
|
int smallest = nodeIndex;
|
||||||
|
|
||||||
|
if (left <= lastIndex && _comparision.Invoke(_items[left], _items[nodeIndex]) < 0)
|
||||||
|
smallest = left;
|
||||||
|
|
||||||
|
if (right <= lastIndex && _comparision.Invoke(_items[right], _items[smallest]) < 0)
|
||||||
|
smallest = right;
|
||||||
|
|
||||||
|
if (smallest == nodeIndex)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Swap(nodeIndex, smallest);
|
||||||
|
MinHeapify(smallest, lastIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private void Swap(int x, int y)
|
||||||
|
{
|
||||||
|
if (x == y)
|
||||||
|
return;
|
||||||
|
|
||||||
|
(_items[y], _items[x]) = (_items[x], _items[y]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public T[] ToArray()
|
||||||
|
{
|
||||||
|
return _items.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> ToList()
|
||||||
|
{
|
||||||
|
return new List<T>(_items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Core.Collections
|
namespace DotRecast.Core.Collections
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Core.Collections
|
namespace DotRecast.Core.Collections
|
||||||
{
|
{
|
||||||
public readonly partial struct RcImmutableArray<T>
|
public readonly partial struct RcImmutableArray<T>
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace DotRecast.Core.Collections
|
namespace DotRecast.Core.Collections
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core.Collections
|
namespace DotRecast.Core.Collections
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core.Collections
|
namespace DotRecast.Core.Collections
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core.Collections
|
namespace DotRecast.Core.Collections
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core.Collections
|
namespace DotRecast.Core.Collections
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core.Collections
|
namespace DotRecast.Core.Collections
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core.Collections
|
namespace DotRecast.Core.Collections
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core.Collections
|
namespace DotRecast.Core.Collections
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core.Collections
|
namespace DotRecast.Core.Collections
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core.Collections
|
namespace DotRecast.Core.Collections
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
public interface IRcRand
|
public interface IRcRand
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core.Numerics
|
namespace DotRecast.Core.Numerics
|
||||||
|
|
|
@ -1,20 +1,15 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core.Numerics
|
namespace DotRecast.Core.Numerics
|
||||||
{
|
{
|
||||||
public static class RcVecUtils
|
public static class RcVec
|
||||||
{
|
{
|
||||||
public const float EPSILON = 1e-6f;
|
public const float EPSILON = 1e-6f;
|
||||||
|
public static readonly float EQUAL_THRESHOLD = RcMath.Sqr(1.0f / 16384.0f);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static RcVec3f Create(float[] values)
|
public static RcVec3f Create(Span<float> values, int n)
|
||||||
{
|
|
||||||
return Create(values, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static RcVec3f Create(float[] values, int n)
|
|
||||||
{
|
{
|
||||||
return new RcVec3f(values[n + 0], values[n + 1], values[n + 2]);
|
return new RcVec3f(values[n + 0], values[n + 1], values[n + 2]);
|
||||||
}
|
}
|
||||||
|
@ -42,10 +37,73 @@ namespace DotRecast.Core.Numerics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
/// Performs a 'sloppy' colocation check of the specified points.
|
||||||
public static RcVec3f Scale(this RcVec3f v, float scale)
|
/// @param[in] p0 A point. [(x, y, z)]
|
||||||
|
/// @param[in] p1 A point. [(x, y, z)]
|
||||||
|
/// @return True if the points are considered to be at the same location.
|
||||||
|
///
|
||||||
|
/// Basically, this function will return true if the specified points are
|
||||||
|
/// close enough to eachother to be considered colocated.
|
||||||
|
public static bool Equal(RcVec3f p0, RcVec3f p1)
|
||||||
{
|
{
|
||||||
return v * scale;
|
float d = RcVec3f.DistanceSquared(p0, p1);
|
||||||
|
return d < EQUAL_THRESHOLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static float Dot2(RcVec3f a, RcVec3f b)
|
||||||
|
{
|
||||||
|
return a.X * b.X + a.Z * b.Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static float DistSq2(float[] verts, int p, int q)
|
||||||
|
{
|
||||||
|
float dx = verts[q + 0] - verts[p + 0];
|
||||||
|
float dy = verts[q + 2] - verts[p + 2];
|
||||||
|
return dx * dx + dy * dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static float Dist2(float[] verts, int p, int q)
|
||||||
|
{
|
||||||
|
return MathF.Sqrt(DistSq2(verts, p, q));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static float DistSq2(RcVec3f p, RcVec3f q)
|
||||||
|
{
|
||||||
|
float dx = q.X - p.X;
|
||||||
|
float dy = q.Z - p.Z;
|
||||||
|
return dx * dx + dy * dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static float Dist2(RcVec3f p, RcVec3f q)
|
||||||
|
{
|
||||||
|
return MathF.Sqrt(DistSq2(p, q));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static float Cross2(float[] verts, int p1, int p2, int p3)
|
||||||
|
{
|
||||||
|
float u1 = verts[p2 + 0] - verts[p1 + 0];
|
||||||
|
float v1 = verts[p2 + 2] - verts[p1 + 2];
|
||||||
|
float u2 = verts[p3 + 0] - verts[p1 + 0];
|
||||||
|
float v2 = verts[p3 + 2] - verts[p1 + 2];
|
||||||
|
return u1 * v2 - v1 * u2;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static float Cross2(RcVec3f p1, RcVec3f p2, RcVec3f p3)
|
||||||
|
{
|
||||||
|
float u1 = p2.X - p1.X;
|
||||||
|
float v1 = p2.Z - p1.Z;
|
||||||
|
float u2 = p3.X - p1.X;
|
||||||
|
float v2 = p3.Z - p1.Z;
|
||||||
|
return u1 * v2 - v1 * u2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Derives the dot product of two vectors on the xz-plane. (@p u . @p v)
|
/// Derives the dot product of two vectors on the xz-plane. (@p u . @p v)
|
||||||
|
@ -62,46 +120,6 @@ namespace DotRecast.Core.Numerics
|
||||||
@this.Z * v.Z;
|
@this.Z * v.Z;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static float Dot2D(this RcVec3f @this, float[] v, int vi)
|
|
||||||
{
|
|
||||||
return @this.X * v[vi] +
|
|
||||||
@this.Z * v[vi + 2];
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static RcVec3f Add(RcVec3f a, float[] verts, int i)
|
|
||||||
{
|
|
||||||
return new RcVec3f(
|
|
||||||
a.X + verts[i],
|
|
||||||
a.Y + verts[i + 1],
|
|
||||||
a.Z + verts[i + 2]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static RcVec3f Subtract(float[] verts, int i, int j)
|
|
||||||
{
|
|
||||||
return new RcVec3f(
|
|
||||||
verts[i] - verts[j],
|
|
||||||
verts[i + 1] - verts[j + 1],
|
|
||||||
verts[i + 2] - verts[j + 2]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static RcVec3f Subtract(RcVec3f i, float[] verts, int j)
|
|
||||||
{
|
|
||||||
return new RcVec3f(
|
|
||||||
i.X - verts[j],
|
|
||||||
i.Y - verts[j + 1],
|
|
||||||
i.Z - verts[j + 2]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Cross(float[] dest, float[] v1, float[] v2)
|
public static void Cross(float[] dest, float[] v1, float[] v2)
|
||||||
{
|
{
|
||||||
|
@ -119,19 +137,11 @@ namespace DotRecast.Core.Numerics
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static float Dot(float[] v1, float[] v2)
|
public static void Copy(Span<float> @out, int n, Span<float> @in, int m)
|
||||||
{
|
{
|
||||||
return v1[0] * v2[0] +
|
@out[n + 0] = @in[m + 0];
|
||||||
v1[1] * v2[1] +
|
@out[n + 1] = @in[m + 1];
|
||||||
v1[2] * v2[2];
|
@out[n + 2] = @in[m + 2];
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static float Dot(float[] v1, RcVec3f vector2)
|
|
||||||
{
|
|
||||||
return v1[0] * vector2.X +
|
|
||||||
v1[1] * vector2.Y +
|
|
||||||
v1[2] * vector2.Z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the distance between two points.
|
/// Returns the distance between two points.
|
||||||
|
@ -167,26 +177,6 @@ namespace DotRecast.Core.Numerics
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static RcVec3f Min(RcVec3f v, float[] @in, int i)
|
|
||||||
{
|
|
||||||
return new RcVec3f(
|
|
||||||
(v.X < @in[i + 0]) ? v.X : @in[i + 0],
|
|
||||||
(v.Y < @in[i + 1]) ? v.Y : @in[i + 1],
|
|
||||||
(v.Z < @in[i + 2]) ? v.Z : @in[i + 2]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static RcVec3f Max(RcVec3f v, float[] @in, int i)
|
|
||||||
{
|
|
||||||
return new RcVec3f(
|
|
||||||
(v.X > @in[i + 0]) ? v.X : @in[i + 0],
|
|
||||||
(v.Y > @in[i + 1]) ? v.Y : @in[i + 1],
|
|
||||||
(v.Z > @in[i + 2]) ? v.Z : @in[i + 2]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Derives the distance between the specified points on the xz-plane.
|
/// Derives the distance between the specified points on the xz-plane.
|
||||||
/// @param[in] v1 A point. [(x, y, z)]
|
/// @param[in] v1 A point. [(x, y, z)]
|
||||||
/// @param[in] v2 A point. [(x, y, z)]
|
/// @param[in] v2 A point. [(x, y, z)]
|
||||||
|
@ -202,6 +192,10 @@ namespace DotRecast.Core.Numerics
|
||||||
return (float)MathF.Sqrt(dx * dx + dz * dz);
|
return (float)MathF.Sqrt(dx * dx + dz * dz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Derives the square of the distance between the specified points on the xz-plane.
|
||||||
|
/// @param[in] v1 A point. [(x, y, z)]
|
||||||
|
/// @param[in] v2 A point. [(x, y, z)]
|
||||||
|
/// @return The square of the distance between the point on the xz-plane.
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static float Dist2DSqr(RcVec3f v1, RcVec3f v2)
|
public static float Dist2DSqr(RcVec3f v1, RcVec3f v2)
|
||||||
{
|
{
|
||||||
|
@ -262,7 +256,7 @@ namespace DotRecast.Core.Numerics
|
||||||
/// @param[in] v2 The destination vector.
|
/// @param[in] v2 The destination vector.
|
||||||
/// @param[in] t The interpolation factor. [Limits: 0 <= value <= 1.0]
|
/// @param[in] t The interpolation factor. [Limits: 0 <= value <= 1.0]
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static RcVec3f Lerp(float[] verts, int v1, int v2, float t)
|
public static RcVec3f Lerp(Span<float> verts, int v1, int v2, float t)
|
||||||
{
|
{
|
||||||
return new RcVec3f(
|
return new RcVec3f(
|
||||||
verts[v1 + 0] + (verts[v2 + 0] - verts[v1 + 0]) * t,
|
verts[v1 + 0] + (verts[v2 + 0] - verts[v1 + 0]) * t,
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -49,6 +50,19 @@ namespace DotRecast.Core.Numerics
|
||||||
Z = f;
|
Z = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public RcVec3f(ReadOnlySpan<float> values)
|
||||||
|
{
|
||||||
|
if (values.Length < 3)
|
||||||
|
{
|
||||||
|
RcThrowHelper.ThrowArgumentOutOfRangeException(nameof(values));
|
||||||
|
}
|
||||||
|
|
||||||
|
X = values[0];
|
||||||
|
Y = values[1];
|
||||||
|
Z = values[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly float Length()
|
public readonly float Length()
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace DotRecast.Core.Numerics
|
||||||
|
{
|
||||||
|
public struct RcVec3i
|
||||||
|
{
|
||||||
|
public int X;
|
||||||
|
public int Y;
|
||||||
|
public int Z;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
public enum RcByteOrder
|
public enum RcByteOrder
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
public class RcEdge
|
public class RcEdge
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
/*
|
||||||
|
Recast4J Copyright (c) 2015 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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.IO;
|
||||||
|
|
||||||
|
namespace DotRecast.Core
|
||||||
|
{
|
||||||
|
public static class RcIO
|
||||||
|
{
|
||||||
|
public static RcByteBuffer ToByteBuffer(BinaryReader br, bool direct)
|
||||||
|
{
|
||||||
|
byte[] data = ToByteArray(br);
|
||||||
|
if (direct)
|
||||||
|
{
|
||||||
|
Array.Reverse(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RcByteBuffer(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] ToByteArray(BinaryReader br)
|
||||||
|
{
|
||||||
|
using var ms = new MemoryStream();
|
||||||
|
Span<byte> buffer = stackalloc byte[4096];
|
||||||
|
int l;
|
||||||
|
while ((l = br.Read(buffer)) > 0)
|
||||||
|
{
|
||||||
|
ms.Write(buffer.Slice(0, l));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ms.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static RcByteBuffer ToByteBuffer(BinaryReader br)
|
||||||
|
{
|
||||||
|
var bytes = ToByteArray(br);
|
||||||
|
return new RcByteBuffer(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int SwapEndianness(int i)
|
||||||
|
{
|
||||||
|
var s = (((uint)i >> 24) & 0xFF) | (((uint)i >> 8) & 0xFF00) | (((uint)i << 8) & 0xFF0000) | ((i << 24) & 0xFF000000);
|
||||||
|
return (int)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] ReadFileIfFound(string filename)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(filename))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
string filePath = filename;
|
||||||
|
|
||||||
|
if (!File.Exists(filePath))
|
||||||
|
{
|
||||||
|
var searchFilePath = RcDirectory.SearchFile($"{filename}");
|
||||||
|
if (!File.Exists(searchFilePath))
|
||||||
|
{
|
||||||
|
searchFilePath = RcDirectory.SearchFile($"resources/{filename}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(searchFilePath))
|
||||||
|
{
|
||||||
|
filePath = searchFilePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
byte[] buffer = new byte[fs.Length];
|
||||||
|
var read = fs.Read(buffer, 0, buffer.Length);
|
||||||
|
if (read != buffer.Length)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(BinaryWriter ws, float value, RcByteOrder order)
|
||||||
|
{
|
||||||
|
byte[] bytes = BitConverter.GetBytes(value);
|
||||||
|
int i = BitConverter.ToInt32(bytes, 0);
|
||||||
|
Write(ws, i, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(BinaryWriter ws, short value, RcByteOrder order)
|
||||||
|
{
|
||||||
|
if (order == RcByteOrder.BIG_ENDIAN)
|
||||||
|
{
|
||||||
|
ws.Write((byte)((value >> 8) & 0xFF));
|
||||||
|
ws.Write((byte)(value & 0xFF));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ws.Write((byte)(value & 0xFF));
|
||||||
|
ws.Write((byte)((value >> 8) & 0xFF));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(BinaryWriter ws, long value, RcByteOrder order)
|
||||||
|
{
|
||||||
|
if (order == RcByteOrder.BIG_ENDIAN)
|
||||||
|
{
|
||||||
|
Write(ws, (int)((ulong)value >> 32), order);
|
||||||
|
Write(ws, (int)(value & 0xFFFFFFFF), order);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Write(ws, (int)(value & 0xFFFFFFFF), order);
|
||||||
|
Write(ws, (int)((ulong)value >> 32), order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(BinaryWriter ws, int value, RcByteOrder order)
|
||||||
|
{
|
||||||
|
if (order == RcByteOrder.BIG_ENDIAN)
|
||||||
|
{
|
||||||
|
ws.Write((byte)((value >> 24) & 0xFF));
|
||||||
|
ws.Write((byte)((value >> 16) & 0xFF));
|
||||||
|
ws.Write((byte)((value >> 8) & 0xFF));
|
||||||
|
ws.Write((byte)(value & 0xFF));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ws.Write((byte)(value & 0xFF));
|
||||||
|
ws.Write((byte)((value >> 8) & 0xFF));
|
||||||
|
ws.Write((byte)((value >> 16) & 0xFF));
|
||||||
|
ws.Write((byte)((value >> 24) & 0xFF));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(BinaryWriter ws, bool value)
|
||||||
|
{
|
||||||
|
Write(ws, (byte)(value ? 1 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(BinaryWriter ws, byte value)
|
||||||
|
{
|
||||||
|
ws.Write(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(BinaryWriter ws, MemoryStream ms)
|
||||||
|
{
|
||||||
|
ms.Position = 0;
|
||||||
|
byte[] buffer = new byte[ms.Length];
|
||||||
|
ms.Read(buffer, 0, buffer.Length);
|
||||||
|
ws.Write(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +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
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -29,5 +29,11 @@ namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
return f * f;
|
return f * f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static float Lerp(float value1, float value2, float amount)
|
||||||
|
{
|
||||||
|
return (value1 * (1.0f - amount)) + (value2 * amount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace DotRecast.Core
|
|
||||||
{
|
|
||||||
public static class RcResources
|
|
||||||
{
|
|
||||||
public static byte[] Load(string filename)
|
|
||||||
{
|
|
||||||
var filepath = filename;
|
|
||||||
if (!File.Exists(filepath))
|
|
||||||
{
|
|
||||||
filepath = RcDirectory.SearchFile($"resources/{filename}");
|
|
||||||
}
|
|
||||||
|
|
||||||
using var fs = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
|
||||||
byte[] buffer = new byte[fs.Length];
|
|
||||||
fs.Read(buffer, 0, buffer.Length);
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
|
@ -6,17 +6,31 @@ namespace DotRecast.Core
|
||||||
public static class RcSpans
|
public static class RcSpans
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Copy<T>(Span<T> source, Span<T> destination)
|
public static void Copy<T>(Span<T> src, Span<T> dst)
|
||||||
{
|
{
|
||||||
Copy(source, 0, destination, 0, source.Length);
|
src.CopyTo(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Copy<T>(Span<T> source, int sourceIdx, Span<T> destination, int destinationIdx, int length)
|
public static void Copy<T>(Span<T> src, int srcIdx, Span<T> dst, int dstIdx, int length)
|
||||||
{
|
{
|
||||||
var src = source.Slice(sourceIdx, length);
|
var slicedSrc = src.Slice(srcIdx, length);
|
||||||
var dst = destination.Slice(destinationIdx);
|
var slicedDst = dst.Slice(dstIdx);
|
||||||
src.CopyTo(dst);
|
slicedSrc.CopyTo(slicedDst);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void Move<T>(Span<T> src, int srcIdx, int dstIdx, int length)
|
||||||
|
{
|
||||||
|
var slicedSrc = src.Slice(srcIdx, length);
|
||||||
|
var slicedDst = src.Slice(dstIdx, length);
|
||||||
|
slicedSrc.CopyTo(slicedDst);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void Fill<T>(Span<T> span, T value, int start, int count)
|
||||||
|
{
|
||||||
|
span.Slice(start, count).Fill(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
|
|
||||||
|
@ -15,6 +15,12 @@ namespace DotRecast.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void ThrowArgumentOutOfRangeException(string argument)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(argument);
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void StackOverflow()
|
public static void StackOverflow()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
/// Recast performance timer categories.
|
/// Recast performance timer categories.
|
||||||
/// @see rcContext
|
/// @see rcContext
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -20,7 +20,7 @@ freely, subject to the following restrictions:
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Diagnostics;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Buffers;
|
using DotRecast.Core.Buffers;
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
|
@ -121,8 +121,9 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// @ingroup crowd
|
/// @ingroup crowd
|
||||||
public class DtCrowd
|
public class DtCrowd
|
||||||
{
|
{
|
||||||
private readonly RcAtomicInteger _agentId = new RcAtomicInteger();
|
private readonly RcAtomicInteger _agentIdx;
|
||||||
private readonly List<DtCrowdAgent> _agents;
|
private readonly Dictionary<int, DtCrowdAgent> _agents;
|
||||||
|
private readonly List<DtCrowdAgent> _activeAgents;
|
||||||
|
|
||||||
private readonly DtPathQueue _pathQ;
|
private readonly DtPathQueue _pathQ;
|
||||||
|
|
||||||
|
@ -171,7 +172,9 @@ namespace DotRecast.Detour.Crowd
|
||||||
// Allocate temp buffer for merging paths.
|
// Allocate temp buffer for merging paths.
|
||||||
_maxPathResult = DtCrowdConst.MAX_PATH_RESULT;
|
_maxPathResult = DtCrowdConst.MAX_PATH_RESULT;
|
||||||
_pathQ = new DtPathQueue(config);
|
_pathQ = new DtPathQueue(config);
|
||||||
_agents = new List<DtCrowdAgent>();
|
_agentIdx = new RcAtomicInteger(0);
|
||||||
|
_agents = new Dictionary<int, DtCrowdAgent>();
|
||||||
|
_activeAgents = new List<DtCrowdAgent>();
|
||||||
|
|
||||||
// The navQuery is mostly used for local searches, no need for large node pool.
|
// The navQuery is mostly used for local searches, no need for large node pool.
|
||||||
SetNavMesh(nav);
|
SetNavMesh(nav);
|
||||||
|
@ -236,11 +239,10 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// @return The index of the agent in the agent pool. Or -1 if the agent could not be added.
|
/// @return The index of the agent in the agent pool. Or -1 if the agent could not be added.
|
||||||
public DtCrowdAgent AddAgent(RcVec3f pos, DtCrowdAgentParams option)
|
public DtCrowdAgent AddAgent(RcVec3f pos, DtCrowdAgentParams option)
|
||||||
{
|
{
|
||||||
int idx = _agentId.GetAndIncrement();
|
int idx = _agentIdx.GetAndIncrement();
|
||||||
DtCrowdAgent ag = new DtCrowdAgent(idx);
|
DtCrowdAgent ag = new DtCrowdAgent(idx);
|
||||||
ag.corridor.Init(_maxPathResult);
|
ag.corridor.Init(_maxPathResult);
|
||||||
_agents.Add(ag);
|
AddAgent(ag);
|
||||||
|
|
||||||
UpdateAgentParameters(ag, option);
|
UpdateAgentParameters(ag, option);
|
||||||
|
|
||||||
// Find nearest position on navmesh and place the agent there.
|
// Find nearest position on navmesh and place the agent there.
|
||||||
|
@ -257,6 +259,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
|
|
||||||
ag.topologyOptTime = 0;
|
ag.topologyOptTime = 0;
|
||||||
ag.targetReplanTime = 0;
|
ag.targetReplanTime = 0;
|
||||||
|
ag.nneis = 0;
|
||||||
|
|
||||||
ag.dvel = RcVec3f.Zero;
|
ag.dvel = RcVec3f.Zero;
|
||||||
ag.nvel = RcVec3f.Zero;
|
ag.nvel = RcVec3f.Zero;
|
||||||
|
@ -279,15 +282,27 @@ namespace DotRecast.Detour.Crowd
|
||||||
return ag;
|
return ag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public DtCrowdAgent GetAgent(int idx)
|
||||||
* Removes the agent from the crowd.
|
{
|
||||||
*
|
return _agents.GetValueOrDefault(idx);
|
||||||
* @param agent
|
}
|
||||||
* Agent to be removed
|
|
||||||
*/
|
// Add the agent from the crowd.
|
||||||
|
public void AddAgent(DtCrowdAgent agent)
|
||||||
|
{
|
||||||
|
if (_agents.TryAdd(agent.idx, agent))
|
||||||
|
{
|
||||||
|
_activeAgents.Add(agent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes the agent from the crowd.
|
||||||
public void RemoveAgent(DtCrowdAgent agent)
|
public void RemoveAgent(DtCrowdAgent agent)
|
||||||
{
|
{
|
||||||
_agents.Remove(agent);
|
if (_agents.Remove(agent.idx))
|
||||||
|
{
|
||||||
|
_activeAgents.Remove(agent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool RequestMoveTargetReplan(DtCrowdAgent ag, long refs, RcVec3f pos)
|
private bool RequestMoveTargetReplan(DtCrowdAgent ag, long refs, RcVec3f pos)
|
||||||
|
@ -359,7 +374,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
*/
|
*/
|
||||||
public IList<DtCrowdAgent> GetActiveAgents()
|
public IList<DtCrowdAgent> GetActiveAgents()
|
||||||
{
|
{
|
||||||
return _agents;
|
return _activeAgents;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RcVec3f GetQueryExtents()
|
public RcVec3f GetQueryExtents()
|
||||||
|
@ -590,7 +605,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
if (ag.targetReplan) // && npath > 10)
|
if (ag.targetReplan) // && npath > 10)
|
||||||
{
|
{
|
||||||
// Try to use existing steady path during replan if possible.
|
// Try to use existing steady path during replan if possible.
|
||||||
status = _navQuery.FinalizeSlicedFindPathPartial(path, ref reqPath);
|
status = _navQuery.FinalizeSlicedFindPathPartial(path, path.Count, ref reqPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -876,7 +891,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
// Update the collision boundary after certain distance has been passed or
|
// Update the collision boundary after certain distance has been passed or
|
||||||
// if it has become invalid.
|
// if it has become invalid.
|
||||||
float updateThr = ag.option.collisionQueryRange * 0.25f;
|
float updateThr = ag.option.collisionQueryRange * 0.25f;
|
||||||
if (RcVecUtils.Dist2DSqr(ag.npos, ag.boundary.GetCenter()) > RcMath.Sqr(updateThr)
|
if (RcVec.Dist2DSqr(ag.npos, ag.boundary.GetCenter()) > RcMath.Sqr(updateThr)
|
||||||
|| !ag.boundary.IsValid(_navQuery, _filters[ag.option.queryFilterType]))
|
|| !ag.boundary.IsValid(_navQuery, _filters[ag.option.queryFilterType]))
|
||||||
{
|
{
|
||||||
ag.boundary.Update(ag.corridor.GetFirstPoly(), ag.npos, ag.option.collisionQueryRange, _navQuery,
|
ag.boundary.Update(ag.corridor.GetFirstPoly(), ag.npos, ag.option.collisionQueryRange, _navQuery,
|
||||||
|
@ -884,21 +899,66 @@ namespace DotRecast.Detour.Crowd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query neighbour agents
|
// Query neighbour agents
|
||||||
GetNeighbours(ag.npos, ag.option.height, ag.option.collisionQueryRange, ag, ref ag.neis, _grid);
|
ag.nneis = GetNeighbours(ag.npos, ag.option.height, ag.option.collisionQueryRange, ag, ag.neis, DtCrowdConst.DT_CROWDAGENT_MAX_NEIGHBOURS, _grid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int AddNeighbour(DtCrowdAgent idx, float dist, Span<DtCrowdNeighbour> neis, int nneis, int maxNeis)
|
||||||
private int GetNeighbours(RcVec3f pos, float height, float range, DtCrowdAgent skip, ref List<DtCrowdNeighbour> result, DtProximityGrid grid)
|
|
||||||
{
|
{
|
||||||
result.Clear();
|
// Insert neighbour based on the distance.
|
||||||
|
int nei = 0;
|
||||||
|
if (0 == nneis)
|
||||||
|
{
|
||||||
|
nei = nneis;
|
||||||
|
}
|
||||||
|
else if (dist >= neis[nneis - 1].dist)
|
||||||
|
{
|
||||||
|
if (nneis >= maxNeis)
|
||||||
|
return nneis;
|
||||||
|
nei = nneis;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < nneis; ++i)
|
||||||
|
{
|
||||||
|
if (dist <= neis[i].dist)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int tgt = i + 1;
|
||||||
|
int n = Math.Min(nneis - i, maxNeis - tgt);
|
||||||
|
|
||||||
|
Debug.Assert(tgt + n <= maxNeis);
|
||||||
|
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
RcSpans.Move(neis, i, tgt, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
nei = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
neis[nei] = new DtCrowdNeighbour(idx, dist);
|
||||||
|
|
||||||
|
return Math.Min(nneis + 1, maxNeis);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetNeighbours(RcVec3f pos, float height, float range, DtCrowdAgent skip, DtCrowdNeighbour[] result, int maxResult, DtProximityGrid grid)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
const int MAX_NEIS = 32;
|
||||||
|
Span<int> ids = stackalloc int[MAX_NEIS];
|
||||||
|
int nids = grid.QueryItems(pos.X - range, pos.Z - range,
|
||||||
|
pos.X + range, pos.Z + range,
|
||||||
|
ids, ids.Length);
|
||||||
|
|
||||||
int MAX_NEIS = 32;
|
|
||||||
var ids = new DtCrowdAgent[MAX_NEIS];
|
|
||||||
int nids = grid.QueryItems(pos.X - range, pos.Z - range, pos.X + range, pos.Z + range, ids, ids.Length);
|
|
||||||
for (int i = 0; i < nids; ++i)
|
for (int i = 0; i < nids; ++i)
|
||||||
{
|
{
|
||||||
var ag = ids[i];
|
var ag = GetAgent(ids[i]);
|
||||||
if (ag == skip)
|
if (ag == skip)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -918,11 +978,10 @@ namespace DotRecast.Detour.Crowd
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Add(new DtCrowdNeighbour(ag, distSqr));
|
n = AddNeighbour(ag, distSqr, result, n, maxResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Sort((o1, o2) => o1.dist.CompareTo(o2.dist));
|
return n;
|
||||||
return result.Count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FindCorners(IList<DtCrowdAgent> agents, DtCrowdAgentDebugInfo debug)
|
private void FindCorners(IList<DtCrowdAgent> agents, DtCrowdAgentDebugInfo debug)
|
||||||
|
@ -945,13 +1004,13 @@ namespace DotRecast.Detour.Crowd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find corners for steering
|
// Find corners for steering
|
||||||
ag.corridor.FindCorners(ref ag.corners, DtCrowdConst.DT_CROWDAGENT_MAX_CORNERS, _navQuery, _filters[ag.option.queryFilterType]);
|
ag.ncorners = ag.corridor.FindCorners(ag.corners, DtCrowdConst.DT_CROWDAGENT_MAX_CORNERS, _navQuery, _filters[ag.option.queryFilterType]);
|
||||||
|
|
||||||
// Check to see if the corner after the next corner is directly visible,
|
// Check to see if the corner after the next corner is directly visible,
|
||||||
// and short cut to there.
|
// and short cut to there.
|
||||||
if ((ag.option.updateFlags & DtCrowdAgentUpdateFlags.DT_CROWD_OPTIMIZE_VIS) != 0 && ag.corners.Count > 0)
|
if ((ag.option.updateFlags & DtCrowdAgentUpdateFlags.DT_CROWD_OPTIMIZE_VIS) != 0 && ag.ncorners > 0)
|
||||||
{
|
{
|
||||||
RcVec3f target = ag.corners[Math.Min(1, ag.corners.Count - 1)].pos;
|
RcVec3f target = ag.corners[Math.Min(1, ag.ncorners - 1)].pos;
|
||||||
ag.corridor.OptimizePathVisibility(target, ag.option.pathOptimizationRange, _navQuery,
|
ag.corridor.OptimizePathVisibility(target, ag.option.pathOptimizationRange, _navQuery,
|
||||||
_filters[ag.option.queryFilterType]);
|
_filters[ag.option.queryFilterType]);
|
||||||
|
|
||||||
|
@ -1001,18 +1060,18 @@ namespace DotRecast.Detour.Crowd
|
||||||
|
|
||||||
// Adjust the path over the off-mesh connection.
|
// Adjust the path over the off-mesh connection.
|
||||||
long[] refs = new long[2];
|
long[] refs = new long[2];
|
||||||
if (ag.corridor.MoveOverOffmeshConnection(ag.corners[ag.corners.Count - 1].refs, refs, ref anim.startPos,
|
if (ag.corridor.MoveOverOffmeshConnection(ag.corners[ag.ncorners - 1].refs, refs, ref anim.startPos,
|
||||||
ref anim.endPos, _navQuery))
|
ref anim.endPos, _navQuery))
|
||||||
{
|
{
|
||||||
anim.initPos = ag.npos;
|
anim.initPos = ag.npos;
|
||||||
anim.polyRef = refs[1];
|
anim.polyRef = refs[1];
|
||||||
anim.active = true;
|
anim.active = true;
|
||||||
anim.t = 0.0f;
|
anim.t = 0.0f;
|
||||||
anim.tmax = (RcVecUtils.Dist2D(anim.startPos, anim.endPos) / ag.option.maxSpeed) * 0.5f;
|
anim.tmax = (RcVec.Dist2D(anim.startPos, anim.endPos) / ag.option.maxSpeed) * 0.5f;
|
||||||
|
|
||||||
ag.state = DtCrowdAgentState.DT_CROWDAGENT_STATE_OFFMESH;
|
ag.state = DtCrowdAgentState.DT_CROWDAGENT_STATE_OFFMESH;
|
||||||
ag.corners.Clear();
|
ag.ncorners = 0;
|
||||||
ag.neis.Clear();
|
ag.nneis = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1064,7 +1123,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
float speedScale = ag.GetDistanceToGoal(slowDownRadius) / slowDownRadius;
|
float speedScale = ag.GetDistanceToGoal(slowDownRadius) / slowDownRadius;
|
||||||
|
|
||||||
ag.desiredSpeed = ag.option.maxSpeed;
|
ag.desiredSpeed = ag.option.maxSpeed;
|
||||||
dvel = dvel.Scale(ag.desiredSpeed * speedScale);
|
dvel = dvel * (ag.desiredSpeed * speedScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Separation
|
// Separation
|
||||||
|
@ -1077,7 +1136,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
float w = 0;
|
float w = 0;
|
||||||
RcVec3f disp = new RcVec3f();
|
RcVec3f disp = new RcVec3f();
|
||||||
|
|
||||||
for (int j = 0; j < ag.neis.Count; ++j)
|
for (int j = 0; j < ag.nneis; ++j)
|
||||||
{
|
{
|
||||||
DtCrowdAgent nei = ag.neis[j].agent;
|
DtCrowdAgent nei = ag.neis[j].agent;
|
||||||
|
|
||||||
|
@ -1098,20 +1157,20 @@ namespace DotRecast.Detour.Crowd
|
||||||
float dist = MathF.Sqrt(distSqr);
|
float dist = MathF.Sqrt(distSqr);
|
||||||
float weight = separationWeight * (1.0f - RcMath.Sqr(dist * invSeparationDist));
|
float weight = separationWeight * (1.0f - RcMath.Sqr(dist * invSeparationDist));
|
||||||
|
|
||||||
disp = RcVecUtils.Mad(disp, diff, weight / dist);
|
disp = RcVec.Mad(disp, diff, weight / dist);
|
||||||
w += 1.0f;
|
w += 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w > 0.0001f)
|
if (w > 0.0001f)
|
||||||
{
|
{
|
||||||
// Adjust desired velocity.
|
// Adjust desired velocity.
|
||||||
dvel = RcVecUtils.Mad(dvel, disp, 1.0f / w);
|
dvel = RcVec.Mad(dvel, disp, 1.0f / w);
|
||||||
// Clamp desired velocity to desired speed.
|
// Clamp desired velocity to desired speed.
|
||||||
float speedSqr = dvel.LengthSquared();
|
float speedSqr = dvel.LengthSquared();
|
||||||
float desiredSqr = RcMath.Sqr(ag.desiredSpeed);
|
float desiredSqr = RcMath.Sqr(ag.desiredSpeed);
|
||||||
if (speedSqr > desiredSqr)
|
if (speedSqr > desiredSqr)
|
||||||
{
|
{
|
||||||
dvel = dvel.Scale(desiredSqr / speedSqr);
|
dvel = dvel * (desiredSqr / speedSqr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1139,7 +1198,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
_obstacleQuery.Reset();
|
_obstacleQuery.Reset();
|
||||||
|
|
||||||
// Add neighbours as obstacles.
|
// Add neighbours as obstacles.
|
||||||
for (int j = 0; j < ag.neis.Count; ++j)
|
for (int j = 0; j < ag.nneis; ++j)
|
||||||
{
|
{
|
||||||
DtCrowdAgent nei = ag.neis[j].agent;
|
DtCrowdAgent nei = ag.neis[j].agent;
|
||||||
if(!nei.option.contributeObstacleAvoidance || nei.option.obstacleAvoidanceWeight < ag.option.obstacleAvoidanceWeight)
|
if(!nei.option.contributeObstacleAvoidance || nei.option.obstacleAvoidanceWeight < ag.option.obstacleAvoidanceWeight)
|
||||||
|
@ -1230,7 +1289,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
|
|
||||||
float w = 0;
|
float w = 0;
|
||||||
|
|
||||||
for (int j = 0; j < ag.neis.Count; ++j)
|
for (int j = 0; j < ag.nneis; ++j)
|
||||||
{
|
{
|
||||||
DtCrowdAgent nei = ag.neis[j].agent;
|
DtCrowdAgent nei = ag.neis[j].agent;
|
||||||
long idx1 = nei.idx;
|
long idx1 = nei.idx;
|
||||||
|
@ -1264,7 +1323,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
pen = (1.0f / dist) * (pen * 0.5f) * _config.collisionResolveFactor;
|
pen = (1.0f / dist) * (pen * 0.5f) * _config.collisionResolveFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
ag.disp = RcVecUtils.Mad(ag.disp, diff, pen);
|
ag.disp = RcVec.Mad(ag.disp, diff, pen);
|
||||||
|
|
||||||
w += 1.0f;
|
w += 1.0f;
|
||||||
}
|
}
|
||||||
|
@ -1272,7 +1331,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
if (w > 0.0001f)
|
if (w > 0.0001f)
|
||||||
{
|
{
|
||||||
float iw = 1.0f / w;
|
float iw = 1.0f / w;
|
||||||
ag.disp = ag.disp.Scale(iw);
|
ag.disp = ag.disp * iw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -28,7 +28,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// @ingroup crowd
|
/// @ingroup crowd
|
||||||
public class DtCrowdAgent
|
public class DtCrowdAgent
|
||||||
{
|
{
|
||||||
public readonly long idx;
|
public readonly int idx;
|
||||||
|
|
||||||
/// The type of mesh polygon the agent is traversing. (See: #CrowdAgentState)
|
/// The type of mesh polygon the agent is traversing. (See: #CrowdAgentState)
|
||||||
public DtCrowdAgentState state;
|
public DtCrowdAgentState state;
|
||||||
|
@ -37,16 +37,19 @@ namespace DotRecast.Detour.Crowd
|
||||||
public bool partial;
|
public bool partial;
|
||||||
|
|
||||||
/// The path corridor the agent is using.
|
/// The path corridor the agent is using.
|
||||||
public DtPathCorridor corridor;
|
public readonly DtPathCorridor corridor;
|
||||||
|
|
||||||
/// The local boundary data for the agent.
|
/// The local boundary data for the agent.
|
||||||
public DtLocalBoundary boundary;
|
public readonly DtLocalBoundary boundary;
|
||||||
|
|
||||||
/// Time since the agent's path corridor was optimized.
|
/// Time since the agent's path corridor was optimized.
|
||||||
public float topologyOptTime;
|
public float topologyOptTime;
|
||||||
|
|
||||||
/// The known neighbors of the agent.
|
/// The known neighbors of the agent.
|
||||||
public List<DtCrowdNeighbour> neis = new List<DtCrowdNeighbour>();
|
public readonly DtCrowdNeighbour[] neis = new DtCrowdNeighbour[DtCrowdConst.DT_CROWDAGENT_MAX_NEIGHBOURS];
|
||||||
|
|
||||||
|
/// The number of neighbors.
|
||||||
|
public int nneis;
|
||||||
|
|
||||||
/// The desired speed.
|
/// The desired speed.
|
||||||
public float desiredSpeed;
|
public float desiredSpeed;
|
||||||
|
@ -61,7 +64,10 @@ namespace DotRecast.Detour.Crowd
|
||||||
public DtCrowdAgentParams option;
|
public DtCrowdAgentParams option;
|
||||||
|
|
||||||
/// The local path corridor corners for the agent.
|
/// The local path corridor corners for the agent.
|
||||||
public List<DtStraightPath> corners = new List<DtStraightPath>();
|
public DtStraightPath[] corners = new DtStraightPath[DtCrowdConst.DT_CROWDAGENT_MAX_CORNERS];
|
||||||
|
|
||||||
|
/// The number of corners.
|
||||||
|
public int ncorners;
|
||||||
|
|
||||||
public DtMoveRequestState targetState; // < State of the movement request.
|
public DtMoveRequestState targetState; // < State of the movement request.
|
||||||
public long targetRef; // < Target polyref of the movement request.
|
public long targetRef; // < Target polyref of the movement request.
|
||||||
|
@ -88,28 +94,28 @@ namespace DotRecast.Detour.Crowd
|
||||||
RcVec3f dv = RcVec3f.Subtract(nvel, vel);
|
RcVec3f dv = RcVec3f.Subtract(nvel, vel);
|
||||||
float ds = dv.Length();
|
float ds = dv.Length();
|
||||||
if (ds > maxDelta)
|
if (ds > maxDelta)
|
||||||
dv = dv.Scale(maxDelta / ds);
|
dv = dv * (maxDelta / ds);
|
||||||
vel = RcVec3f.Add(vel, dv);
|
vel = RcVec3f.Add(vel, dv);
|
||||||
|
|
||||||
// Integrate
|
// Integrate
|
||||||
if (vel.Length() > 0.0001f)
|
if (vel.Length() > 0.0001f)
|
||||||
npos = RcVecUtils.Mad(npos, vel, dt);
|
npos = RcVec.Mad(npos, vel, dt);
|
||||||
else
|
else
|
||||||
vel = RcVec3f.Zero;
|
vel = RcVec3f.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool OverOffmeshConnection(float radius)
|
public bool OverOffmeshConnection(float radius)
|
||||||
{
|
{
|
||||||
if (0 == corners.Count)
|
if (0 == ncorners)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool offMeshConnection = ((corners[corners.Count - 1].flags
|
bool offMeshConnection = ((corners[ncorners - 1].flags
|
||||||
& DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
& DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
||||||
? true
|
? true
|
||||||
: false;
|
: false;
|
||||||
if (offMeshConnection)
|
if (offMeshConnection)
|
||||||
{
|
{
|
||||||
float distSq = RcVecUtils.Dist2DSqr(npos, corners[corners.Count - 1].pos);
|
float distSq = RcVec.Dist2DSqr(npos, corners[ncorners - 1].pos);
|
||||||
if (distSq < radius * radius)
|
if (distSq < radius * radius)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -119,12 +125,12 @@ namespace DotRecast.Detour.Crowd
|
||||||
|
|
||||||
public float GetDistanceToGoal(float range)
|
public float GetDistanceToGoal(float range)
|
||||||
{
|
{
|
||||||
if (0 == corners.Count)
|
if (0 == ncorners)
|
||||||
return range;
|
return range;
|
||||||
|
|
||||||
bool endOfPath = ((corners[corners.Count - 1].flags & DtStraightPathFlags.DT_STRAIGHTPATH_END) != 0) ? true : false;
|
bool endOfPath = ((corners[ncorners - 1].flags & DtStraightPathFlags.DT_STRAIGHTPATH_END) != 0) ? true : false;
|
||||||
if (endOfPath)
|
if (endOfPath)
|
||||||
return Math.Min(RcVecUtils.Dist2D(npos, corners[corners.Count - 1].pos), range);
|
return Math.Min(RcVec.Dist2D(npos, corners[ncorners - 1].pos), range);
|
||||||
|
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
@ -132,10 +138,10 @@ namespace DotRecast.Detour.Crowd
|
||||||
public RcVec3f CalcSmoothSteerDirection()
|
public RcVec3f CalcSmoothSteerDirection()
|
||||||
{
|
{
|
||||||
RcVec3f dir = new RcVec3f();
|
RcVec3f dir = new RcVec3f();
|
||||||
if (0 < corners.Count)
|
if (0 < ncorners)
|
||||||
{
|
{
|
||||||
int ip0 = 0;
|
int ip0 = 0;
|
||||||
int ip1 = Math.Min(1, corners.Count - 1);
|
int ip1 = Math.Min(1, ncorners - 1);
|
||||||
var p0 = corners[ip0].pos;
|
var p0 = corners[ip0].pos;
|
||||||
var p1 = corners[ip1].pos;
|
var p1 = corners[ip1].pos;
|
||||||
|
|
||||||
|
@ -147,7 +153,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
float len0 = dir0.Length();
|
float len0 = dir0.Length();
|
||||||
float len1 = dir1.Length();
|
float len1 = dir1.Length();
|
||||||
if (len1 > 0.001f)
|
if (len1 > 0.001f)
|
||||||
dir1 = dir1.Scale(1.0f / len1);
|
dir1 = dir1 * (1.0f / len1);
|
||||||
|
|
||||||
dir.X = dir0.X - dir1.X * len0 * 0.5f;
|
dir.X = dir0.X - dir1.X * len0 * 0.5f;
|
||||||
dir.Y = 0;
|
dir.Y = 0;
|
||||||
|
@ -161,7 +167,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
public RcVec3f CalcStraightSteerDirection()
|
public RcVec3f CalcStraightSteerDirection()
|
||||||
{
|
{
|
||||||
RcVec3f dir = new RcVec3f();
|
RcVec3f dir = new RcVec3f();
|
||||||
if (0 < corners.Count)
|
if (0 < ncorners)
|
||||||
{
|
{
|
||||||
dir = RcVec3f.Subtract(corners[0].pos, npos);
|
dir = RcVec3f.Subtract(corners[0].pos, npos);
|
||||||
dir.Y = 0;
|
dir.Y = 0;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
public class DtCrowdAgentConfig
|
public class DtCrowdAgentConfig
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -24,23 +24,15 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// @ingroup crowd
|
/// @ingroup crowd
|
||||||
public class DtCrowdAgentParams
|
public class DtCrowdAgentParams
|
||||||
{
|
{
|
||||||
/// < Agent radius. [Limit: >= 0]
|
public float radius; // < Agent radius. [Limit: >= 0]
|
||||||
public float radius;
|
public float height; // < Agent height. [Limit: > 0]
|
||||||
|
public float maxAcceleration; // < Maximum allowed acceleration. [Limit: >= 0]
|
||||||
/// < Agent height. [Limit: > 0]
|
public float maxSpeed; // < Maximum allowed speed. [Limit: >= 0]
|
||||||
public float height;
|
|
||||||
|
|
||||||
/// < Maximum allowed acceleration. [Limit: >= 0]
|
|
||||||
public float maxAcceleration;
|
|
||||||
|
|
||||||
/// < Maximum allowed speed. [Limit: >= 0]
|
|
||||||
public float maxSpeed;
|
|
||||||
|
|
||||||
/// Defines how close a collision element must be before it is considered for steering behaviors. [Limits: > 0]
|
/// Defines how close a collision element must be before it is considered for steering behaviors. [Limits: > 0]
|
||||||
public float collisionQueryRange;
|
public float collisionQueryRange;
|
||||||
|
|
||||||
/// < The path visibility optimization range. [Limit: > 0]
|
public float pathOptimizationRange; // < The path visibility optimization range. [Limit: > 0]
|
||||||
public float pathOptimizationRange;
|
|
||||||
|
|
||||||
/// How aggresive the agent manager should be at avoiding collisions with this agent. [Limit: >= 0]
|
/// How aggresive the agent manager should be at avoiding collisions with this agent. [Limit: >= 0]
|
||||||
public float separationWeight;
|
public float separationWeight;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
/// The type of navigation mesh polygon the agent is currently traversing.
|
/// The type of navigation mesh polygon the agent is currently traversing.
|
||||||
/// @ingroup crowd
|
/// @ingroup crowd
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
/// Crowd agent update flags.
|
/// Crowd agent update flags.
|
||||||
/// @ingroup crowd
|
/// @ingroup crowd
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
public static class DtCrowdConst
|
public static class DtCrowdConst
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
/// Provides neighbor data for agents managed by the crowd.
|
/// Provides neighbor data for agents managed by the crowd.
|
||||||
/// @ingroup crowd
|
/// @ingroup crowd
|
||||||
/// @see dtCrowdAgent::neis, dtCrowd
|
/// @see dtCrowdAgent::neis, dtCrowd
|
||||||
public readonly struct DtCrowdNeighbour
|
public readonly struct DtCrowdNeighbour
|
||||||
{
|
{
|
||||||
public readonly DtCrowdAgent agent;
|
public readonly DtCrowdAgent agent; // < The index of the neighbor in the crowd.
|
||||||
|
public readonly float dist; // < The distance between the current agent and the neighbor.
|
||||||
|
|
||||||
/// < The index of the neighbor in the crowd.
|
|
||||||
public readonly float dist;
|
|
||||||
|
|
||||||
/// < The distance between the current agent and the neighbor.
|
|
||||||
public DtCrowdNeighbour(DtCrowdAgent agent, float dist)
|
public DtCrowdNeighbour(DtCrowdAgent agent, float dist)
|
||||||
{
|
{
|
||||||
this.agent = agent;
|
this.agent = agent;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
public class DtCrowdTimerLabel
|
public class DtCrowdTimerLabel
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -18,6 +18,7 @@ freely, subject to the following restrictions:
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
@ -90,6 +91,8 @@ namespace DotRecast.Detour.Crowd
|
||||||
|
|
||||||
public void Update(long startRef, RcVec3f pos, float collisionQueryRange, DtNavMeshQuery navquery, IDtQueryFilter filter)
|
public void Update(long startRef, RcVec3f pos, float collisionQueryRange, DtNavMeshQuery navquery, IDtQueryFilter filter)
|
||||||
{
|
{
|
||||||
|
const int MAX_SEGS_PER_POLY = DtDetour.DT_VERTS_PER_POLYGON * 3;
|
||||||
|
|
||||||
if (startRef == 0)
|
if (startRef == 0)
|
||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
|
@ -104,18 +107,17 @@ namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
// Secondly, store all polygon edges.
|
// Secondly, store all polygon edges.
|
||||||
m_segs.Clear();
|
m_segs.Clear();
|
||||||
|
Span<RcSegmentVert> segs = stackalloc RcSegmentVert[MAX_SEGS_PER_POLY];
|
||||||
var segmentVerts = new List<RcSegmentVert>();
|
int nsegs = 0;
|
||||||
var segmentRefs = new List<long>();
|
|
||||||
|
|
||||||
for (int j = 0; j < m_polys.Count; ++j)
|
for (int j = 0; j < m_polys.Count; ++j)
|
||||||
{
|
{
|
||||||
var result = navquery.GetPolyWallSegments(m_polys[j], false, filter, ref segmentVerts, ref segmentRefs);
|
var result = navquery.GetPolyWallSegments(m_polys[j], filter, segs, null, ref nsegs, MAX_SEGS_PER_POLY);
|
||||||
if (result.Succeeded())
|
if (result.Succeeded())
|
||||||
{
|
{
|
||||||
for (int k = 0; k < segmentRefs.Count; ++k)
|
for (int k = 0; k < nsegs; ++k)
|
||||||
{
|
{
|
||||||
RcSegmentVert s = segmentVerts[k];
|
ref RcSegmentVert s = ref segs[k];
|
||||||
var s0 = s.vmin;
|
var s0 = s.vmin;
|
||||||
var s3 = s.vmax;
|
var s3 = s.vmax;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
public enum DtMoveRequestState
|
public enum DtMoveRequestState
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
public class DtObstacleAvoidanceParams
|
public class DtObstacleAvoidanceParams
|
||||||
{
|
{
|
||||||
|
@ -8,18 +8,11 @@
|
||||||
public float weightSide;
|
public float weightSide;
|
||||||
public float weightToi;
|
public float weightToi;
|
||||||
public float horizTime;
|
public float horizTime;
|
||||||
public int gridSize;
|
public int gridSize; // < grid
|
||||||
|
public int adaptiveDivs; // < adaptive
|
||||||
|
public int adaptiveRings; // < adaptive
|
||||||
|
public int adaptiveDepth; // < adaptive
|
||||||
|
|
||||||
/// < grid
|
|
||||||
public int adaptiveDivs;
|
|
||||||
|
|
||||||
/// < adaptive
|
|
||||||
public int adaptiveRings;
|
|
||||||
|
|
||||||
/// < adaptive
|
|
||||||
public int adaptiveDepth;
|
|
||||||
|
|
||||||
/// < adaptive
|
|
||||||
public DtObstacleAvoidanceParams()
|
public DtObstacleAvoidanceParams()
|
||||||
{
|
{
|
||||||
velBias = 0.4f;
|
velBias = 0.4f;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -19,8 +19,8 @@ freely, subject to the following restrictions:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Buffers;
|
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,11 +28,9 @@ namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
public class DtObstacleAvoidanceQuery
|
public class DtObstacleAvoidanceQuery
|
||||||
{
|
{
|
||||||
public const int DT_MAX_PATTERN_DIVS = 32;
|
public const int DT_MAX_PATTERN_DIVS = 32; // < Max numver of adaptive divs.
|
||||||
|
|
||||||
/// < Max numver of adaptive divs.
|
|
||||||
public const int DT_MAX_PATTERN_RINGS = 4;
|
public const int DT_MAX_PATTERN_RINGS = 4;
|
||||||
|
public const float DT_PI = 3.14159265f;
|
||||||
|
|
||||||
private DtObstacleAvoidanceParams m_params;
|
private DtObstacleAvoidanceParams m_params;
|
||||||
private float m_invHorizTime;
|
private float m_invHorizTime;
|
||||||
|
@ -188,16 +186,16 @@ namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
RcVec3f v = RcVec3f.Subtract(bq, bp);
|
RcVec3f v = RcVec3f.Subtract(bq, bp);
|
||||||
RcVec3f w = RcVec3f.Subtract(ap, bp);
|
RcVec3f w = RcVec3f.Subtract(ap, bp);
|
||||||
float d = RcVecUtils.Perp2D(u, v);
|
float d = RcVec.Perp2D(u, v);
|
||||||
if (MathF.Abs(d) < 1e-6f)
|
if (MathF.Abs(d) < 1e-6f)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
d = 1.0f / d;
|
d = 1.0f / d;
|
||||||
t = RcVecUtils.Perp2D(v, w) * d;
|
t = RcVec.Perp2D(v, w) * d;
|
||||||
if (t < 0 || t > 1)
|
if (t < 0 || t > 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
float s = RcVecUtils.Perp2D(u, w) * d;
|
float s = RcVec.Perp2D(u, w) * d;
|
||||||
if (s < 0 || s > 1)
|
if (s < 0 || s > 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -218,8 +216,8 @@ namespace DotRecast.Detour.Crowd
|
||||||
float minPenalty, DtObstacleAvoidanceDebugData debug)
|
float minPenalty, DtObstacleAvoidanceDebugData debug)
|
||||||
{
|
{
|
||||||
// penalty for straying away from the desired and current velocities
|
// penalty for straying away from the desired and current velocities
|
||||||
float vpen = m_params.weightDesVel * (RcVecUtils.Dist2D(vcand, dvel) * m_invVmax);
|
float vpen = m_params.weightDesVel * (RcVec.Dist2D(vcand, dvel) * m_invVmax);
|
||||||
float vcpen = m_params.weightCurVel * (RcVecUtils.Dist2D(vcand, vel) * m_invVmax);
|
float vcpen = m_params.weightCurVel * (RcVec.Dist2D(vcand, vel) * m_invVmax);
|
||||||
|
|
||||||
// find the threshold hit time to bail out based on the early out penalty
|
// find the threshold hit time to bail out based on the early out penalty
|
||||||
// (see how the penalty is calculated below to understand)
|
// (see how the penalty is calculated below to understand)
|
||||||
|
@ -238,7 +236,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
DtObstacleCircle cir = m_circles[i];
|
DtObstacleCircle cir = m_circles[i];
|
||||||
|
|
||||||
// RVO
|
// RVO
|
||||||
RcVec3f vab = vcand.Scale(2);
|
RcVec3f vab = vcand * 2;
|
||||||
vab = RcVec3f.Subtract(vab, vel);
|
vab = RcVec3f.Subtract(vab, vel);
|
||||||
vab = RcVec3f.Subtract(vab, cir.vel);
|
vab = RcVec3f.Subtract(vab, cir.vel);
|
||||||
|
|
||||||
|
@ -363,7 +361,8 @@ namespace DotRecast.Detour.Crowd
|
||||||
}
|
}
|
||||||
|
|
||||||
// vector normalization that ignores the y-component.
|
// vector normalization that ignores the y-component.
|
||||||
void DtNormalize2D(float[] v)
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
void DtNormalize2D(Span<float> v)
|
||||||
{
|
{
|
||||||
float d = MathF.Sqrt(v[0] * v[0] + v[2] * v[2]);
|
float d = MathF.Sqrt(v[0] * v[0] + v[2] * v[2]);
|
||||||
if (d == 0)
|
if (d == 0)
|
||||||
|
@ -374,7 +373,8 @@ namespace DotRecast.Detour.Crowd
|
||||||
}
|
}
|
||||||
|
|
||||||
// vector normalization that ignores the y-component.
|
// vector normalization that ignores the y-component.
|
||||||
RcVec3f DtRotate2D(float[] v, float ang)
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
RcVec3f DtRotate2D(Span<float> v, float ang)
|
||||||
{
|
{
|
||||||
RcVec3f dest = new RcVec3f();
|
RcVec3f dest = new RcVec3f();
|
||||||
float c = MathF.Cos(ang);
|
float c = MathF.Cos(ang);
|
||||||
|
@ -385,7 +385,6 @@ namespace DotRecast.Detour.Crowd
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
static readonly float DT_PI = 3.14159265f;
|
|
||||||
|
|
||||||
public int SampleVelocityAdaptive(RcVec3f pos, float rad, float vmax, RcVec3f vel, RcVec3f dvel, out RcVec3f nvel,
|
public int SampleVelocityAdaptive(RcVec3f pos, float rad, float vmax, RcVec3f vel, RcVec3f dvel, out RcVec3f nvel,
|
||||||
DtObstacleAvoidanceParams option,
|
DtObstacleAvoidanceParams option,
|
||||||
|
@ -403,7 +402,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
debug.Reset();
|
debug.Reset();
|
||||||
|
|
||||||
// Build sampling pattern aligned to desired velocity.
|
// Build sampling pattern aligned to desired velocity.
|
||||||
using var pat = RcRentedArray.Rent<float>((DT_MAX_PATTERN_DIVS * DT_MAX_PATTERN_RINGS + 1) * 2);
|
Span<float> pat = stackalloc float[(DT_MAX_PATTERN_DIVS * DT_MAX_PATTERN_RINGS + 1) * 2];
|
||||||
int npat = 0;
|
int npat = 0;
|
||||||
|
|
||||||
int ndivs = m_params.adaptiveDivs;
|
int ndivs = m_params.adaptiveDivs;
|
||||||
|
@ -417,7 +416,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
float sa = MathF.Sin(da);
|
float sa = MathF.Sin(da);
|
||||||
|
|
||||||
// desired direction
|
// desired direction
|
||||||
float[] ddir = new float[6];
|
Span<float> ddir = stackalloc float[6];
|
||||||
ddir[0] = dvel.X;
|
ddir[0] = dvel.X;
|
||||||
ddir[1] = dvel.Y;
|
ddir[1] = dvel.Y;
|
||||||
ddir[2] = dvel.Z;
|
ddir[2] = dvel.Z;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -34,6 +34,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
private RcVec3f m_target;
|
private RcVec3f m_target;
|
||||||
|
|
||||||
private List<long> m_path;
|
private List<long> m_path;
|
||||||
|
private int m_npath;
|
||||||
private int m_maxPath;
|
private int m_maxPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,7 +89,8 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// @return True if the initialization succeeded.
|
/// @return True if the initialization succeeded.
|
||||||
public bool Init(int maxPath)
|
public bool Init(int maxPath)
|
||||||
{
|
{
|
||||||
m_path = new List<long>();
|
m_path = new List<long>(maxPath);
|
||||||
|
m_npath = 0;
|
||||||
m_maxPath = maxPath;
|
m_maxPath = maxPath;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -107,6 +109,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
m_target = pos;
|
m_target = pos;
|
||||||
m_path.Clear();
|
m_path.Clear();
|
||||||
m_path.Add(refs);
|
m_path.Add(refs);
|
||||||
|
m_npath = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,42 +133,42 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// @param[in] navquery The query object used to build the corridor.
|
/// @param[in] navquery The query object used to build the corridor.
|
||||||
/// @param[in] filter The filter to apply to the operation.
|
/// @param[in] filter The filter to apply to the operation.
|
||||||
/// @return The number of corners returned in the corner buffers. [0 <= value <= @p maxCorners]
|
/// @return The number of corners returned in the corner buffers. [0 <= value <= @p maxCorners]
|
||||||
public int FindCorners(ref List<DtStraightPath> corners, int maxCorners, DtNavMeshQuery navquery, IDtQueryFilter filter)
|
public int FindCorners(Span<DtStraightPath> corners, int maxCorners, DtNavMeshQuery navquery, IDtQueryFilter filter)
|
||||||
{
|
{
|
||||||
const float MIN_TARGET_DIST = 0.01f;
|
const float MIN_TARGET_DIST = 0.01f;
|
||||||
|
|
||||||
var result = navquery.FindStraightPath(m_pos, m_target, m_path, ref corners, maxCorners, 0);
|
int ncorners = 0;
|
||||||
if (result.Succeeded())
|
navquery.FindStraightPath(m_pos, m_target, m_path, m_npath, corners, out ncorners, maxCorners, 0);
|
||||||
|
|
||||||
|
// Prune points in the beginning of the path which are too close.
|
||||||
|
while (0 < ncorners)
|
||||||
{
|
{
|
||||||
// Prune points in the beginning of the path which are too close.
|
if ((corners[0].flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0 ||
|
||||||
int start = 0;
|
RcVec.Dist2DSqr(corners[0].pos, m_pos) > RcMath.Sqr(MIN_TARGET_DIST))
|
||||||
foreach (DtStraightPath spi in corners)
|
|
||||||
{
|
{
|
||||||
if ((spi.flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0
|
break;
|
||||||
|| RcVecUtils.Dist2DSqr(spi.pos, m_pos) > RcMath.Sqr(MIN_TARGET_DIST))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
start++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int end = corners.Count;
|
ncorners--;
|
||||||
// Prune points after an off-mesh connection.
|
if (0 < ncorners)
|
||||||
for (int i = start; i < corners.Count; i++)
|
|
||||||
{
|
{
|
||||||
DtStraightPath spi = corners[i];
|
RcSpans.Move(corners, 1, 0, 3);
|
||||||
if ((spi.flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
|
||||||
{
|
|
||||||
end = i + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
corners = corners.GetRange(start, end - start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return corners.Count;
|
|
||||||
|
// Prune points after an off-mesh connection.
|
||||||
|
for (int i = 0; i < ncorners; ++i)
|
||||||
|
{
|
||||||
|
if ((corners[i].flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
||||||
|
{
|
||||||
|
ncorners = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return ncorners;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -194,7 +197,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
public void OptimizePathVisibility(RcVec3f next, float pathOptimizationRange, DtNavMeshQuery navquery, IDtQueryFilter filter)
|
public void OptimizePathVisibility(RcVec3f next, float pathOptimizationRange, DtNavMeshQuery navquery, IDtQueryFilter filter)
|
||||||
{
|
{
|
||||||
// Clamp the ray to max distance.
|
// Clamp the ray to max distance.
|
||||||
float dist = RcVecUtils.Dist2D(m_pos, next);
|
float dist = RcVec.Dist2D(m_pos, next);
|
||||||
|
|
||||||
// If too close to the goal, do not try to optimize.
|
// If too close to the goal, do not try to optimize.
|
||||||
if (dist < 0.01f)
|
if (dist < 0.01f)
|
||||||
|
@ -207,7 +210,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
|
|
||||||
// Adjust ray length.
|
// Adjust ray length.
|
||||||
var delta = RcVec3f.Subtract(next, m_pos);
|
var delta = RcVec3f.Subtract(next, m_pos);
|
||||||
RcVec3f goal = RcVecUtils.Mad(m_pos, delta, pathOptimizationRange / dist);
|
RcVec3f goal = RcVec.Mad(m_pos, delta, pathOptimizationRange / dist);
|
||||||
|
|
||||||
var res = new List<long>();
|
var res = new List<long>();
|
||||||
var status = navquery.Raycast(m_path[0], m_pos, goal, filter, out var t, out var norm, ref res);
|
var status = navquery.Raycast(m_path[0], m_pos, goal, filter, out var t, out var norm, ref res);
|
||||||
|
@ -215,7 +218,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
if (res.Count > 1 && t > 0.99f)
|
if (res.Count > 1 && t > 0.99f)
|
||||||
{
|
{
|
||||||
m_path = DtPathUtils.MergeCorridorStartShortcut(m_path, m_path.Count, m_maxPath, res);
|
m_npath = DtPathUtils.MergeCorridorStartShortcut(ref m_path, m_npath, m_maxPath, res, res.Count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,7 +238,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// @param[in] filter The filter to apply to the operation.
|
/// @param[in] filter The filter to apply to the operation.
|
||||||
public bool OptimizePathTopology(DtNavMeshQuery navquery, IDtQueryFilter filter, int maxIterations)
|
public bool OptimizePathTopology(DtNavMeshQuery navquery, IDtQueryFilter filter, int maxIterations)
|
||||||
{
|
{
|
||||||
if (m_path.Count < 3)
|
if (m_npath < 3)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -243,11 +246,11 @@ namespace DotRecast.Detour.Crowd
|
||||||
var res = new List<long>();
|
var res = new List<long>();
|
||||||
navquery.InitSlicedFindPath(m_path[0], m_path[^1], m_pos, m_target, filter, 0);
|
navquery.InitSlicedFindPath(m_path[0], m_path[^1], m_pos, m_target, filter, 0);
|
||||||
navquery.UpdateSlicedFindPath(maxIterations, out var _);
|
navquery.UpdateSlicedFindPath(maxIterations, out var _);
|
||||||
var status = navquery.FinalizeSlicedFindPathPartial(m_path, ref res);
|
var status = navquery.FinalizeSlicedFindPathPartial(m_path, m_npath, ref res);
|
||||||
|
|
||||||
if (status.Succeeded() && res.Count > 0)
|
if (status.Succeeded() && res.Count > 0)
|
||||||
{
|
{
|
||||||
m_path = DtPathUtils.MergeCorridorStartShortcut(m_path, m_path.Count, m_maxPath, res);
|
m_npath = DtPathUtils.MergeCorridorStartShortcut(ref m_path, m_npath, m_maxPath, res, res.Count);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,21 +262,23 @@ namespace DotRecast.Detour.Crowd
|
||||||
// Advance the path up to and over the off-mesh connection.
|
// Advance the path up to and over the off-mesh connection.
|
||||||
long prevRef = 0, polyRef = m_path[0];
|
long prevRef = 0, polyRef = m_path[0];
|
||||||
int npos = 0;
|
int npos = 0;
|
||||||
while (npos < m_path.Count && polyRef != offMeshConRef)
|
while (npos < m_npath && polyRef != offMeshConRef)
|
||||||
{
|
{
|
||||||
prevRef = polyRef;
|
prevRef = polyRef;
|
||||||
polyRef = m_path[npos];
|
polyRef = m_path[npos];
|
||||||
npos++;
|
npos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (npos == m_path.Count)
|
if (npos == m_npath)
|
||||||
{
|
{
|
||||||
// Could not find offMeshConRef
|
// Could not find offMeshConRef
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prune path
|
// Prune path
|
||||||
m_path = m_path.GetRange(npos, m_path.Count - npos);
|
m_path = m_path.GetRange(npos, m_npath - npos);
|
||||||
|
m_npath -= npos;
|
||||||
|
|
||||||
refs[0] = prevRef;
|
refs[0] = prevRef;
|
||||||
refs[1] = polyRef;
|
refs[1] = polyRef;
|
||||||
|
|
||||||
|
@ -312,11 +317,12 @@ namespace DotRecast.Detour.Crowd
|
||||||
public bool MovePosition(RcVec3f npos, DtNavMeshQuery navquery, IDtQueryFilter filter)
|
public bool MovePosition(RcVec3f npos, DtNavMeshQuery navquery, IDtQueryFilter filter)
|
||||||
{
|
{
|
||||||
// Move along navmesh and update new position.
|
// Move along navmesh and update new position.
|
||||||
var visited = new List<long>();
|
const int MAX_VISITED = 16;
|
||||||
var status = navquery.MoveAlongSurface(m_path[0], m_pos, npos, filter, out var result, ref visited);
|
Span<long> visited = stackalloc long[MAX_VISITED];
|
||||||
|
var status = navquery.MoveAlongSurface(m_path[0], m_pos, npos, filter, out var result, visited, out var nvisited, MAX_VISITED);
|
||||||
if (status.Succeeded())
|
if (status.Succeeded())
|
||||||
{
|
{
|
||||||
m_path = DtPathUtils.MergeCorridorStartMoved(m_path, m_path.Count, m_maxPath, visited);
|
m_npath = DtPathUtils.MergeCorridorStartMoved(ref m_path, m_npath, m_maxPath, visited, nvisited);
|
||||||
|
|
||||||
// Adjust the position to stay on top of the navmesh.
|
// Adjust the position to stay on top of the navmesh.
|
||||||
m_pos = result;
|
m_pos = result;
|
||||||
|
@ -354,11 +360,14 @@ namespace DotRecast.Detour.Crowd
|
||||||
public bool MoveTargetPosition(RcVec3f npos, DtNavMeshQuery navquery, IDtQueryFilter filter)
|
public bool MoveTargetPosition(RcVec3f npos, DtNavMeshQuery navquery, IDtQueryFilter filter)
|
||||||
{
|
{
|
||||||
// Move along navmesh and update new position.
|
// Move along navmesh and update new position.
|
||||||
var visited = new List<long>();
|
const int MAX_VISITED = 16;
|
||||||
var status = navquery.MoveAlongSurface(m_path[^1], m_target, npos, filter, out var result, ref visited);
|
Span<long> visited = stackalloc long[MAX_VISITED];
|
||||||
|
int nvisited = 0;
|
||||||
|
var status = navquery.MoveAlongSurface(m_path[^1], m_target, npos, filter, out var result, visited, out nvisited, MAX_VISITED);
|
||||||
if (status.Succeeded())
|
if (status.Succeeded())
|
||||||
{
|
{
|
||||||
m_path = DtPathUtils.MergeCorridorEndMoved(m_path, m_path.Count, m_maxPath, visited);
|
m_npath = DtPathUtils.MergeCorridorEndMoved(ref m_path, m_npath, m_maxPath, visited, nvisited);
|
||||||
|
|
||||||
// TODO: should we do that?
|
// TODO: should we do that?
|
||||||
// Adjust the position to stay on top of the navmesh.
|
// Adjust the position to stay on top of the navmesh.
|
||||||
/*
|
/*
|
||||||
|
@ -386,24 +395,27 @@ namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
m_target = target;
|
m_target = target;
|
||||||
m_path = new List<long>(path);
|
m_path = new List<long>(path);
|
||||||
|
m_npath = path.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FixPathStart(long safeRef, RcVec3f safePos)
|
public void FixPathStart(long safeRef, RcVec3f safePos)
|
||||||
{
|
{
|
||||||
m_pos = safePos;
|
m_pos = safePos;
|
||||||
if (m_path.Count < 3 && m_path.Count > 0)
|
if (m_npath < 3 && m_npath > 0)
|
||||||
{
|
{
|
||||||
long p = m_path[m_path.Count - 1];
|
long p = m_path[m_npath - 1];
|
||||||
m_path.Clear();
|
m_path.Clear();
|
||||||
m_path.Add(safeRef);
|
m_path.Add(safeRef);
|
||||||
m_path.Add(0L);
|
m_path.Add(0L);
|
||||||
m_path.Add(p);
|
m_path.Add(p);
|
||||||
|
m_npath = 3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_path.Clear();
|
m_path.Clear();
|
||||||
m_path.Add(safeRef);
|
m_path.Add(safeRef);
|
||||||
m_path.Add(0L);
|
m_path.Add(0L);
|
||||||
|
m_npath = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,12 +423,12 @@ namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
// Keep valid path as far as possible.
|
// Keep valid path as far as possible.
|
||||||
int n = 0;
|
int n = 0;
|
||||||
while (n < m_path.Count && navquery.IsValidPolyRef(m_path[n], filter))
|
while (n < m_npath && navquery.IsValidPolyRef(m_path[n], filter))
|
||||||
{
|
{
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_path.Count == n)
|
if (m_npath == n)
|
||||||
{
|
{
|
||||||
// All valid, no need to fix.
|
// All valid, no need to fix.
|
||||||
return true;
|
return true;
|
||||||
|
@ -424,18 +436,20 @@ namespace DotRecast.Detour.Crowd
|
||||||
else if (n == 0)
|
else if (n == 0)
|
||||||
{
|
{
|
||||||
// The first polyref is bad, use current safe values.
|
// The first polyref is bad, use current safe values.
|
||||||
m_pos = RcVecUtils.Create(safePos);
|
m_pos = new RcVec3f(safePos);
|
||||||
m_path.Clear();
|
m_path.Clear();
|
||||||
m_path.Add(safeRef);
|
m_path.Add(safeRef);
|
||||||
|
m_npath = 1;
|
||||||
}
|
}
|
||||||
else if (n < m_path.Count)
|
else if (n < m_npath)
|
||||||
{
|
{
|
||||||
// The path is partially usable.
|
// The path is partially usable.
|
||||||
m_path = m_path.GetRange(0, n);
|
m_path = m_path.GetRange(0, n);
|
||||||
|
m_npath = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clamp target pos to last poly
|
// Clamp target pos to last poly
|
||||||
navquery.ClosestPointOnPolyBoundary(m_path[m_path.Count - 1], m_target, out m_target);
|
navquery.ClosestPointOnPolyBoundary(m_path[m_npath - 1], m_target, out m_target);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,7 +465,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
public bool IsValid(int maxLookAhead, DtNavMeshQuery navquery, IDtQueryFilter filter)
|
public bool IsValid(int maxLookAhead, DtNavMeshQuery navquery, IDtQueryFilter filter)
|
||||||
{
|
{
|
||||||
// Check that all polygons still pass query filter.
|
// Check that all polygons still pass query filter.
|
||||||
int n = Math.Min(m_path.Count, maxLookAhead);
|
int n = Math.Min(m_npath, maxLookAhead);
|
||||||
for (int i = 0; i < n; ++i)
|
for (int i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
if (!navquery.IsValidPolyRef(m_path[i], filter))
|
if (!navquery.IsValidPolyRef(m_path[i], filter))
|
||||||
|
@ -481,14 +495,14 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// @return The polygon reference id of the first polygon in the corridor. (Or zero if there is no path.)
|
/// @return The polygon reference id of the first polygon in the corridor. (Or zero if there is no path.)
|
||||||
public long GetFirstPoly()
|
public long GetFirstPoly()
|
||||||
{
|
{
|
||||||
return 0 == m_path.Count ? 0 : m_path[0];
|
return 0 == m_npath ? 0 : m_path[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The polygon reference id of the last polygon in the corridor, the polygon containing the target.
|
/// The polygon reference id of the last polygon in the corridor, the polygon containing the target.
|
||||||
/// @return The polygon reference id of the last polygon in the corridor. (Or zero if there is no path.)
|
/// @return The polygon reference id of the last polygon in the corridor. (Or zero if there is no path.)
|
||||||
public long GetLastPoly()
|
public long GetLastPoly()
|
||||||
{
|
{
|
||||||
return 0 == m_path.Count ? 0 : m_path[m_path.Count - 1];
|
return 0 == m_npath ? 0 : m_path[m_npath - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The corridor's path.
|
/// The corridor's path.
|
||||||
|
@ -502,7 +516,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// @return The number of polygons in the current corridor path.
|
/// @return The number of polygons in the current corridor path.
|
||||||
public int GetPathCount()
|
public int GetPathCount()
|
||||||
{
|
{
|
||||||
return m_path.Count;
|
return m_npath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -83,7 +83,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int QueryItems(float minx, float miny, float maxx, float maxy, DtCrowdAgent[] ids, int maxIds)
|
public int QueryItems(float minx, float miny, float maxx, float maxy, Span<int> ids, int maxIds)
|
||||||
{
|
{
|
||||||
int iminx = (int)MathF.Floor(minx * _invCellSize);
|
int iminx = (int)MathF.Floor(minx * _invCellSize);
|
||||||
int iminy = (int)MathF.Floor(miny * _invCellSize);
|
int iminy = (int)MathF.Floor(miny * _invCellSize);
|
||||||
|
@ -110,7 +110,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
// Check if the id exists already.
|
// Check if the id exists already.
|
||||||
int end = n;
|
int end = n;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i != end && ids[i] != item)
|
while (i != end && ids[i] != item.idx)
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
// Item not found, add it.
|
// Item not found, add it.
|
||||||
if (i == n)
|
if (i == n)
|
||||||
{
|
{
|
||||||
ids[n++] = item;
|
ids[n++] = item.idx;
|
||||||
|
|
||||||
if (n >= maxIds)
|
if (n >= maxIds)
|
||||||
return n;
|
return n;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -23,6 +23,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
|
using DotRecast.Core.Collections;
|
||||||
using DotRecast.Detour.Dynamic.Colliders;
|
using DotRecast.Detour.Dynamic.Colliders;
|
||||||
using DotRecast.Detour.Dynamic.Io;
|
using DotRecast.Detour.Dynamic.Io;
|
||||||
using DotRecast.Recast;
|
using DotRecast.Recast;
|
||||||
|
@ -62,8 +63,8 @@ namespace DotRecast.Detour.Dynamic
|
||||||
navMeshParams.orig.X = voxelFile.bounds[0];
|
navMeshParams.orig.X = voxelFile.bounds[0];
|
||||||
navMeshParams.orig.Y = voxelFile.bounds[1];
|
navMeshParams.orig.Y = voxelFile.bounds[1];
|
||||||
navMeshParams.orig.Z = voxelFile.bounds[2];
|
navMeshParams.orig.Z = voxelFile.bounds[2];
|
||||||
navMeshParams.tileWidth = voxelFile.cellSize * voxelFile.tileSizeX;
|
navMeshParams.tileWidth = voxelFile.useTiles ? voxelFile.cellSize * voxelFile.tileSizeX : voxelFile.bounds[3] - voxelFile.bounds[0];
|
||||||
navMeshParams.tileHeight = voxelFile.cellSize * voxelFile.tileSizeZ;
|
navMeshParams.tileHeight = voxelFile.useTiles ? voxelFile.cellSize * voxelFile.tileSizeZ : voxelFile.bounds[5] - voxelFile.bounds[2];
|
||||||
navMeshParams.maxTiles = voxelFile.tiles.Count;
|
navMeshParams.maxTiles = voxelFile.tiles.Count;
|
||||||
navMeshParams.maxPolys = 0x8000;
|
navMeshParams.maxPolys = 0x8000;
|
||||||
foreach (var t in voxelFile.tiles)
|
foreach (var t in voxelFile.tiles)
|
||||||
|
@ -188,17 +189,17 @@ namespace DotRecast.Detour.Dynamic
|
||||||
return _tiles.Values;
|
return _tiles.Values;
|
||||||
}
|
}
|
||||||
|
|
||||||
int minx = (int)MathF.Floor((bounds[0] - navMeshParams.orig.X) / navMeshParams.tileWidth);
|
int minx = (int)MathF.Floor((bounds[0] - navMeshParams.orig.X) / navMeshParams.tileWidth) - 1;
|
||||||
int minz = (int)MathF.Floor((bounds[2] - navMeshParams.orig.Z) / navMeshParams.tileHeight);
|
int minz = (int)MathF.Floor((bounds[2] - navMeshParams.orig.Z) / navMeshParams.tileHeight) - 1;
|
||||||
int maxx = (int)MathF.Floor((bounds[3] - navMeshParams.orig.X) / navMeshParams.tileWidth);
|
int maxx = (int)MathF.Floor((bounds[3] - navMeshParams.orig.X) / navMeshParams.tileWidth) + 1;
|
||||||
int maxz = (int)MathF.Floor((bounds[5] - navMeshParams.orig.Z) / navMeshParams.tileHeight);
|
int maxz = (int)MathF.Floor((bounds[5] - navMeshParams.orig.Z) / navMeshParams.tileHeight) + 1;
|
||||||
List<DtDynamicTile> tiles = new List<DtDynamicTile>();
|
List<DtDynamicTile> tiles = new List<DtDynamicTile>();
|
||||||
for (int z = minz; z <= maxz; ++z)
|
for (int z = minz; z <= maxz; ++z)
|
||||||
{
|
{
|
||||||
for (int x = minx; x <= maxx; ++x)
|
for (int x = minx; x <= maxx; ++x)
|
||||||
{
|
{
|
||||||
DtDynamicTile tile = GetTileAt(x, z);
|
DtDynamicTile tile = GetTileAt(x, z);
|
||||||
if (tile != null)
|
if (tile != null && IntersectsXZ(tile, bounds))
|
||||||
{
|
{
|
||||||
tiles.Add(tile);
|
tiles.Add(tile);
|
||||||
}
|
}
|
||||||
|
@ -208,6 +209,12 @@ namespace DotRecast.Detour.Dynamic
|
||||||
return tiles;
|
return tiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IntersectsXZ(DtDynamicTile tile, float[] bounds)
|
||||||
|
{
|
||||||
|
return tile.voxelTile.boundsMin.X <= bounds[3] && tile.voxelTile.boundsMax.X >= bounds[0] &&
|
||||||
|
tile.voxelTile.boundsMin.Z <= bounds[5] && tile.voxelTile.boundsMax.Z >= bounds[2];
|
||||||
|
}
|
||||||
|
|
||||||
private List<DtDynamicTile> GetTilesByCollider(long cid)
|
private List<DtDynamicTile> GetTilesByCollider(long cid)
|
||||||
{
|
{
|
||||||
return _tiles.Values.Where(t => t.ContainsCollider(cid)).ToList();
|
return _tiles.Values.Where(t => t.ContainsCollider(cid)).ToList();
|
||||||
|
@ -224,12 +231,17 @@ namespace DotRecast.Detour.Dynamic
|
||||||
{
|
{
|
||||||
if (_dirty)
|
if (_dirty)
|
||||||
{
|
{
|
||||||
DtNavMesh navMesh = new DtNavMesh(navMeshParams, MAX_VERTS_PER_POLY);
|
_dirty = false;
|
||||||
|
|
||||||
|
DtNavMesh navMesh = new DtNavMesh();
|
||||||
|
navMesh.Init(navMeshParams, MAX_VERTS_PER_POLY);
|
||||||
|
|
||||||
foreach (var t in _tiles.Values)
|
foreach (var t in _tiles.Values)
|
||||||
|
{
|
||||||
t.AddTo(navMesh);
|
t.AddTo(navMesh);
|
||||||
|
}
|
||||||
|
|
||||||
_navMesh = navMesh;
|
_navMesh = navMesh;
|
||||||
_dirty = false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,5 +269,21 @@ namespace DotRecast.Detour.Dynamic
|
||||||
{
|
{
|
||||||
return _tiles.Values.Select(t => t.recastResult).ToList();
|
return _tiles.Values.Select(t => t.recastResult).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void NavMesh(DtNavMesh mesh)
|
||||||
|
{
|
||||||
|
_tiles.Values.ForEach(t =>
|
||||||
|
{
|
||||||
|
const int MAX_NEIS = 32;
|
||||||
|
DtMeshTile[] tiles = new DtMeshTile[MAX_NEIS];
|
||||||
|
int nneis = mesh.GetTilesAt(t.voxelTile.tileX, t.voxelTile.tileZ, tiles, MAX_NEIS);
|
||||||
|
if (0 < nneis)
|
||||||
|
{
|
||||||
|
t.SetMeshData(tiles[0].data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_navMesh = mesh;
|
||||||
|
_dirty = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -168,12 +168,12 @@ namespace DotRecast.Detour.Dynamic
|
||||||
option.buildBvTree = true;
|
option.buildBvTree = true;
|
||||||
|
|
||||||
option.offMeshConCount = 0;
|
option.offMeshConCount = 0;
|
||||||
option.offMeshConVerts = new float[0];
|
option.offMeshConVerts = Array.Empty<float>();
|
||||||
option.offMeshConRad = new float[0];
|
option.offMeshConRad = Array.Empty<float>();
|
||||||
option.offMeshConDir = new int[0];
|
option.offMeshConDir = Array.Empty<int>();
|
||||||
option.offMeshConAreas = new int[0];
|
option.offMeshConAreas = Array.Empty<int>();
|
||||||
option.offMeshConFlags = new int[0];
|
option.offMeshConFlags = Array.Empty<int>();
|
||||||
option.offMeshConUserID = new int[0];
|
option.offMeshConUserID = Array.Empty<int>();
|
||||||
return option;
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ namespace DotRecast.Detour.Dynamic
|
||||||
{
|
{
|
||||||
if (meshData != null)
|
if (meshData != null)
|
||||||
{
|
{
|
||||||
id = navMesh.AddTile(meshData, 0, 0);
|
navMesh.AddTile(meshData, 0, 0, out var id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -189,5 +189,10 @@ namespace DotRecast.Detour.Dynamic
|
||||||
id = 0;
|
id = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetMeshData(DtMeshData data)
|
||||||
|
{
|
||||||
|
this.meshData = data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -78,7 +78,7 @@ namespace DotRecast.Detour.Dynamic.Io
|
||||||
walkbableAreaMod, buildMeshDetail);
|
walkbableAreaMod, buildMeshDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DtVoxelFile From(RcConfig config, List<RcBuilderResult> results)
|
public static DtVoxelFile From(RcConfig config, IList<RcBuilderResult> results)
|
||||||
{
|
{
|
||||||
DtVoxelFile f = new DtVoxelFile();
|
DtVoxelFile f = new DtVoxelFile();
|
||||||
f.version = 1;
|
f.version = 1;
|
||||||
|
@ -109,13 +109,14 @@ namespace DotRecast.Detour.Dynamic.Io
|
||||||
};
|
};
|
||||||
foreach (RcBuilderResult r in results)
|
foreach (RcBuilderResult r in results)
|
||||||
{
|
{
|
||||||
|
float pad = r.SolidHeightfiled.borderSize * r.SolidHeightfiled.cs;
|
||||||
f.tiles.Add(new DtVoxelTile(r.TileX, r.TileZ, r.SolidHeightfiled));
|
f.tiles.Add(new DtVoxelTile(r.TileX, r.TileZ, r.SolidHeightfiled));
|
||||||
f.bounds[0] = Math.Min(f.bounds[0], r.SolidHeightfiled.bmin.X);
|
f.bounds[0] = Math.Min(f.bounds[0], r.SolidHeightfiled.bmin.X + pad);
|
||||||
f.bounds[1] = Math.Min(f.bounds[1], r.SolidHeightfiled.bmin.Y);
|
f.bounds[1] = Math.Min(f.bounds[1], r.SolidHeightfiled.bmin.Y);
|
||||||
f.bounds[2] = Math.Min(f.bounds[2], r.SolidHeightfiled.bmin.Z);
|
f.bounds[2] = Math.Min(f.bounds[2], r.SolidHeightfiled.bmin.Z + pad);
|
||||||
f.bounds[3] = Math.Max(f.bounds[3], r.SolidHeightfiled.bmax.X);
|
f.bounds[3] = Math.Max(f.bounds[3], r.SolidHeightfiled.bmax.X - pad);
|
||||||
f.bounds[4] = Math.Max(f.bounds[4], r.SolidHeightfiled.bmax.Y);
|
f.bounds[4] = Math.Max(f.bounds[4], r.SolidHeightfiled.bmax.Y);
|
||||||
f.bounds[5] = Math.Max(f.bounds[5], r.SolidHeightfiled.bmax.Z);
|
f.bounds[5] = Math.Max(f.bounds[5], r.SolidHeightfiled.bmax.Z - pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
|
@ -155,12 +156,13 @@ namespace DotRecast.Detour.Dynamic.Io
|
||||||
{
|
{
|
||||||
RcHeightfield heightfield = vt.Heightfield();
|
RcHeightfield heightfield = vt.Heightfield();
|
||||||
f.tiles.Add(new DtVoxelTile(vt.tileX, vt.tileZ, heightfield));
|
f.tiles.Add(new DtVoxelTile(vt.tileX, vt.tileZ, heightfield));
|
||||||
f.bounds[0] = Math.Min(f.bounds[0], vt.boundsMin.X);
|
float pad = vt.borderSize * vt.cellSize;
|
||||||
|
f.bounds[0] = Math.Min(f.bounds[0], vt.boundsMin.X + pad);
|
||||||
f.bounds[1] = Math.Min(f.bounds[1], vt.boundsMin.Y);
|
f.bounds[1] = Math.Min(f.bounds[1], vt.boundsMin.Y);
|
||||||
f.bounds[2] = Math.Min(f.bounds[2], vt.boundsMin.Z);
|
f.bounds[2] = Math.Min(f.bounds[2], vt.boundsMin.Z + pad);
|
||||||
f.bounds[3] = Math.Max(f.bounds[3], vt.boundsMax.X);
|
f.bounds[3] = Math.Max(f.bounds[3], vt.boundsMax.X - pad);
|
||||||
f.bounds[4] = Math.Max(f.bounds[4], vt.boundsMax.Y);
|
f.bounds[4] = Math.Max(f.bounds[4], vt.boundsMax.Y);
|
||||||
f.bounds[5] = Math.Max(f.bounds[5], vt.boundsMax.Z);
|
f.bounds[5] = Math.Max(f.bounds[5], vt.boundsMax.Z - pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -35,12 +35,12 @@ namespace DotRecast.Detour.Dynamic.Io
|
||||||
|
|
||||||
public DtVoxelFile Read(BinaryReader stream)
|
public DtVoxelFile Read(BinaryReader stream)
|
||||||
{
|
{
|
||||||
RcByteBuffer buf = IOUtils.ToByteBuffer(stream);
|
RcByteBuffer buf = RcIO.ToByteBuffer(stream);
|
||||||
DtVoxelFile file = new DtVoxelFile();
|
DtVoxelFile file = new DtVoxelFile();
|
||||||
int magic = buf.GetInt();
|
int magic = buf.GetInt();
|
||||||
if (magic != DtVoxelFile.MAGIC)
|
if (magic != DtVoxelFile.MAGIC)
|
||||||
{
|
{
|
||||||
magic = IOUtils.SwapEndianness(magic);
|
magic = RcIO.SwapEndianness(magic);
|
||||||
if (magic != DtVoxelFile.MAGIC)
|
if (magic != DtVoxelFile.MAGIC)
|
||||||
{
|
{
|
||||||
throw new IOException("Invalid magic");
|
throw new IOException("Invalid magic");
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -19,12 +19,11 @@ freely, subject to the following restrictions:
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
|
||||||
using DotRecast.Detour.Io;
|
using DotRecast.Detour.Io;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Dynamic.Io
|
namespace DotRecast.Detour.Dynamic.Io
|
||||||
{
|
{
|
||||||
public class DtVoxelFileWriter : DtWriter
|
public class DtVoxelFileWriter
|
||||||
{
|
{
|
||||||
private readonly IRcCompressor _compressor;
|
private readonly IRcCompressor _compressor;
|
||||||
|
|
||||||
|
@ -40,34 +39,34 @@ namespace DotRecast.Detour.Dynamic.Io
|
||||||
|
|
||||||
public void Write(BinaryWriter stream, DtVoxelFile f, RcByteOrder byteOrder, bool compression)
|
public void Write(BinaryWriter stream, DtVoxelFile f, RcByteOrder byteOrder, bool compression)
|
||||||
{
|
{
|
||||||
Write(stream, DtVoxelFile.MAGIC, byteOrder);
|
RcIO.Write(stream, DtVoxelFile.MAGIC, byteOrder);
|
||||||
Write(stream, DtVoxelFile.VERSION_EXPORTER_RECAST4J | (compression ? DtVoxelFile.VERSION_COMPRESSION_LZ4 : 0), byteOrder);
|
RcIO.Write(stream, DtVoxelFile.VERSION_EXPORTER_RECAST4J | (compression ? DtVoxelFile.VERSION_COMPRESSION_LZ4 : 0), byteOrder);
|
||||||
Write(stream, f.walkableRadius, byteOrder);
|
RcIO.Write(stream, f.walkableRadius, byteOrder);
|
||||||
Write(stream, f.walkableHeight, byteOrder);
|
RcIO.Write(stream, f.walkableHeight, byteOrder);
|
||||||
Write(stream, f.walkableClimb, byteOrder);
|
RcIO.Write(stream, f.walkableClimb, byteOrder);
|
||||||
Write(stream, f.walkableSlopeAngle, byteOrder);
|
RcIO.Write(stream, f.walkableSlopeAngle, byteOrder);
|
||||||
Write(stream, f.cellSize, byteOrder);
|
RcIO.Write(stream, f.cellSize, byteOrder);
|
||||||
Write(stream, f.maxSimplificationError, byteOrder);
|
RcIO.Write(stream, f.maxSimplificationError, byteOrder);
|
||||||
Write(stream, f.maxEdgeLen, byteOrder);
|
RcIO.Write(stream, f.maxEdgeLen, byteOrder);
|
||||||
Write(stream, f.minRegionArea, byteOrder);
|
RcIO.Write(stream, f.minRegionArea, byteOrder);
|
||||||
Write(stream, f.regionMergeArea, byteOrder);
|
RcIO.Write(stream, f.regionMergeArea, byteOrder);
|
||||||
Write(stream, f.vertsPerPoly, byteOrder);
|
RcIO.Write(stream, f.vertsPerPoly, byteOrder);
|
||||||
Write(stream, f.buildMeshDetail);
|
RcIO.Write(stream, f.buildMeshDetail);
|
||||||
Write(stream, f.detailSampleDistance, byteOrder);
|
RcIO.Write(stream, f.detailSampleDistance, byteOrder);
|
||||||
Write(stream, f.detailSampleMaxError, byteOrder);
|
RcIO.Write(stream, f.detailSampleMaxError, byteOrder);
|
||||||
Write(stream, f.useTiles);
|
RcIO.Write(stream, f.useTiles);
|
||||||
Write(stream, f.tileSizeX, byteOrder);
|
RcIO.Write(stream, f.tileSizeX, byteOrder);
|
||||||
Write(stream, f.tileSizeZ, byteOrder);
|
RcIO.Write(stream, f.tileSizeZ, byteOrder);
|
||||||
Write(stream, f.rotation.X, byteOrder);
|
RcIO.Write(stream, f.rotation.X, byteOrder);
|
||||||
Write(stream, f.rotation.Y, byteOrder);
|
RcIO.Write(stream, f.rotation.Y, byteOrder);
|
||||||
Write(stream, f.rotation.Z, byteOrder);
|
RcIO.Write(stream, f.rotation.Z, byteOrder);
|
||||||
Write(stream, f.bounds[0], byteOrder);
|
RcIO.Write(stream, f.bounds[0], byteOrder);
|
||||||
Write(stream, f.bounds[1], byteOrder);
|
RcIO.Write(stream, f.bounds[1], byteOrder);
|
||||||
Write(stream, f.bounds[2], byteOrder);
|
RcIO.Write(stream, f.bounds[2], byteOrder);
|
||||||
Write(stream, f.bounds[3], byteOrder);
|
RcIO.Write(stream, f.bounds[3], byteOrder);
|
||||||
Write(stream, f.bounds[4], byteOrder);
|
RcIO.Write(stream, f.bounds[4], byteOrder);
|
||||||
Write(stream, f.bounds[5], byteOrder);
|
RcIO.Write(stream, f.bounds[5], byteOrder);
|
||||||
Write(stream, f.tiles.Count, byteOrder);
|
RcIO.Write(stream, f.tiles.Count, byteOrder);
|
||||||
foreach (DtVoxelTile t in f.tiles)
|
foreach (DtVoxelTile t in f.tiles)
|
||||||
{
|
{
|
||||||
WriteTile(stream, t, byteOrder, compression);
|
WriteTile(stream, t, byteOrder, compression);
|
||||||
|
@ -76,26 +75,26 @@ namespace DotRecast.Detour.Dynamic.Io
|
||||||
|
|
||||||
public void WriteTile(BinaryWriter stream, DtVoxelTile tile, RcByteOrder byteOrder, bool compression)
|
public void WriteTile(BinaryWriter stream, DtVoxelTile tile, RcByteOrder byteOrder, bool compression)
|
||||||
{
|
{
|
||||||
Write(stream, tile.tileX, byteOrder);
|
RcIO.Write(stream, tile.tileX, byteOrder);
|
||||||
Write(stream, tile.tileZ, byteOrder);
|
RcIO.Write(stream, tile.tileZ, byteOrder);
|
||||||
Write(stream, tile.width, byteOrder);
|
RcIO.Write(stream, tile.width, byteOrder);
|
||||||
Write(stream, tile.depth, byteOrder);
|
RcIO.Write(stream, tile.depth, byteOrder);
|
||||||
Write(stream, tile.borderSize, byteOrder);
|
RcIO.Write(stream, tile.borderSize, byteOrder);
|
||||||
Write(stream, tile.boundsMin.X, byteOrder);
|
RcIO.Write(stream, tile.boundsMin.X, byteOrder);
|
||||||
Write(stream, tile.boundsMin.Y, byteOrder);
|
RcIO.Write(stream, tile.boundsMin.Y, byteOrder);
|
||||||
Write(stream, tile.boundsMin.Z, byteOrder);
|
RcIO.Write(stream, tile.boundsMin.Z, byteOrder);
|
||||||
Write(stream, tile.boundsMax.X, byteOrder);
|
RcIO.Write(stream, tile.boundsMax.X, byteOrder);
|
||||||
Write(stream, tile.boundsMax.Y, byteOrder);
|
RcIO.Write(stream, tile.boundsMax.Y, byteOrder);
|
||||||
Write(stream, tile.boundsMax.Z, byteOrder);
|
RcIO.Write(stream, tile.boundsMax.Z, byteOrder);
|
||||||
Write(stream, tile.cellSize, byteOrder);
|
RcIO.Write(stream, tile.cellSize, byteOrder);
|
||||||
Write(stream, tile.cellHeight, byteOrder);
|
RcIO.Write(stream, tile.cellHeight, byteOrder);
|
||||||
byte[] bytes = tile.spanData;
|
byte[] bytes = tile.spanData;
|
||||||
if (compression)
|
if (compression)
|
||||||
{
|
{
|
||||||
bytes = _compressor.Compress(bytes);
|
bytes = _compressor.Compress(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
Write(stream, bytes.Length, byteOrder);
|
RcIO.Write(stream, bytes.Length, byteOrder);
|
||||||
stream.Write(bytes);
|
stream.Write(bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -40,20 +40,20 @@ namespace DotRecast.Detour.Extras
|
||||||
BVItem it = new BVItem();
|
BVItem it = new BVItem();
|
||||||
items[i] = it;
|
items[i] = it;
|
||||||
it.i = i;
|
it.i = i;
|
||||||
RcVec3f bmin = RcVecUtils.Create(data.verts, data.polys[i].verts[0] * 3);
|
RcVec3f bmin = RcVec.Create(data.verts, data.polys[i].verts[0] * 3);
|
||||||
RcVec3f bmax = RcVecUtils.Create(data.verts, data.polys[i].verts[0] * 3);
|
RcVec3f bmax = RcVec.Create(data.verts, data.polys[i].verts[0] * 3);
|
||||||
for (int j = 1; j < data.polys[i].vertCount; j++)
|
for (int j = 1; j < data.polys[i].vertCount; j++)
|
||||||
{
|
{
|
||||||
bmin = RcVecUtils.Min(bmin, data.verts, data.polys[i].verts[j] * 3);
|
bmin = RcVec3f.Min(bmin, RcVec.Create(data.verts, data.polys[i].verts[j] * 3));
|
||||||
bmax = RcVecUtils.Max(bmax, data.verts, data.polys[i].verts[j] * 3);
|
bmax = RcVec3f.Max(bmax, RcVec.Create(data.verts, data.polys[i].verts[j] * 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
it.bmin[0] = Math.Clamp((int)((bmin.X - data.header.bmin.X) * quantFactor), 0, 0x7fffffff);
|
it.bmin.X = Math.Clamp((int)((bmin.X - data.header.bmin.X) * quantFactor), 0, 0x7fffffff);
|
||||||
it.bmin[1] = Math.Clamp((int)((bmin.Y - data.header.bmin.Y) * quantFactor), 0, 0x7fffffff);
|
it.bmin.Y = Math.Clamp((int)((bmin.Y - data.header.bmin.Y) * quantFactor), 0, 0x7fffffff);
|
||||||
it.bmin[2] = Math.Clamp((int)((bmin.Z - data.header.bmin.Z) * quantFactor), 0, 0x7fffffff);
|
it.bmin.Z = Math.Clamp((int)((bmin.Z - data.header.bmin.Z) * quantFactor), 0, 0x7fffffff);
|
||||||
it.bmax[0] = Math.Clamp((int)((bmax.X - data.header.bmin.X) * quantFactor), 0, 0x7fffffff);
|
it.bmax.X = Math.Clamp((int)((bmax.X - data.header.bmin.X) * quantFactor), 0, 0x7fffffff);
|
||||||
it.bmax[1] = Math.Clamp((int)((bmax.Y - data.header.bmin.Y) * quantFactor), 0, 0x7fffffff);
|
it.bmax.Y = Math.Clamp((int)((bmax.Y - data.header.bmin.Y) * quantFactor), 0, 0x7fffffff);
|
||||||
it.bmax[2] = Math.Clamp((int)((bmax.Z - data.header.bmin.Z) * quantFactor), 0, 0x7fffffff);
|
it.bmax.Z = Math.Clamp((int)((bmax.Z - data.header.bmin.Z) * quantFactor), 0, 0x7fffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
return DtNavMeshBuilder.Subdivide(items, data.header.polyCount, 0, data.header.polyCount, 0, nodes);
|
return DtNavMeshBuilder.Subdivide(items, data.header.polyCount, 0, data.header.polyCount, 0, nodes);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
protected void SampleGround(JumpLinkBuilderConfig acfg, EdgeSampler es, ComputeNavMeshHeight heightFunc)
|
protected void SampleGround(JumpLinkBuilderConfig acfg, EdgeSampler es, ComputeNavMeshHeight heightFunc)
|
||||||
{
|
{
|
||||||
float cs = acfg.cellSize;
|
float cs = acfg.cellSize;
|
||||||
float dist = MathF.Sqrt(RcVecUtils.Dist2DSqr(es.start.p, es.start.q));
|
float dist = MathF.Sqrt(RcVec.Dist2DSqr(es.start.p, es.start.q));
|
||||||
int ngsamples = Math.Max(2, (int)MathF.Ceiling(dist / cs));
|
int ngsamples = Math.Max(2, (int)MathF.Ceiling(dist / cs));
|
||||||
|
|
||||||
SampleGroundSegment(heightFunc, es.start, ngsamples);
|
SampleGroundSegment(heightFunc, es.start, ngsamples);
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
using System;
|
using System;
|
||||||
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Extras.Jumplink
|
namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
public class ClimbTrajectory : Trajectory
|
public class ClimbTrajectory : ITrajectory
|
||||||
{
|
{
|
||||||
public override RcVec3f Apply(RcVec3f start, RcVec3f end, float u)
|
public RcVec3f Apply(RcVec3f start, RcVec3f end, float u)
|
||||||
{
|
{
|
||||||
return new RcVec3f()
|
return new RcVec3f()
|
||||||
{
|
{
|
||||||
X = Lerp(start.X, end.X, Math.Min(2f * u, 1f)),
|
X = RcMath.Lerp(start.X, end.X, Math.Min(2f * u, 1f)),
|
||||||
Y = Lerp(start.Y, end.Y, Math.Max(0f, 2f * u - 1f)),
|
Y = RcMath.Lerp(start.Y, end.Y, Math.Max(0f, 2f * u - 1f)),
|
||||||
Z = Lerp(start.Z, end.Z, Math.Min(2f * u, 1f))
|
Z = RcMath.Lerp(start.Z, end.Z, Math.Min(2f * u, 1f))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Recast;
|
using DotRecast.Recast;
|
||||||
using static DotRecast.Recast.RcConstants;
|
|
||||||
|
|
||||||
|
|
||||||
namespace DotRecast.Detour.Extras.Jumplink
|
namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
|
using static RcRecast;
|
||||||
|
|
||||||
public class EdgeExtractor
|
public class EdgeExtractor
|
||||||
{
|
{
|
||||||
public JumpEdge[] ExtractEdges(RcPolyMesh mesh)
|
public JumpEdge[] ExtractEdges(RcPolyMesh mesh)
|
||||||
|
@ -20,7 +20,7 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
if (i > 41 || i < 41)
|
if (i > 41 || i < 41)
|
||||||
{
|
{
|
||||||
// continue;
|
// continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nvp = mesh.nvp;
|
int nvp = mesh.nvp;
|
||||||
|
@ -29,7 +29,7 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
if (j != 1)
|
if (j != 1)
|
||||||
{
|
{
|
||||||
// continue;
|
// continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mesh.polys[p + j] == RC_MESH_NULL_IDX)
|
if (mesh.polys[p + j] == RC_MESH_NULL_IDX)
|
||||||
|
|
|
@ -7,13 +7,13 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
public readonly GroundSegment start = new GroundSegment();
|
public readonly GroundSegment start = new GroundSegment();
|
||||||
public readonly List<GroundSegment> end = new List<GroundSegment>();
|
public readonly List<GroundSegment> end = new List<GroundSegment>();
|
||||||
public readonly Trajectory trajectory;
|
public readonly ITrajectory trajectory;
|
||||||
|
|
||||||
public readonly RcVec3f ax = new RcVec3f();
|
public readonly RcVec3f ax = new RcVec3f();
|
||||||
public readonly RcVec3f ay = new RcVec3f();
|
public readonly RcVec3f ay = new RcVec3f();
|
||||||
public readonly RcVec3f az = new RcVec3f();
|
public readonly RcVec3f az = new RcVec3f();
|
||||||
|
|
||||||
public EdgeSampler(JumpEdge edge, Trajectory trajectory)
|
public EdgeSampler(JumpEdge edge, ITrajectory trajectory)
|
||||||
{
|
{
|
||||||
this.trajectory = trajectory;
|
this.trajectory = trajectory;
|
||||||
ax = RcVec3f.Subtract(edge.sq, edge.sp);
|
ax = RcVec3f.Subtract(edge.sq, edge.sp);
|
||||||
|
|
|
@ -3,7 +3,7 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Extras.Jumplink
|
namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
class EdgeSamplerFactory
|
public class EdgeSamplerFactory
|
||||||
{
|
{
|
||||||
public EdgeSampler Get(JumpLinkBuilderConfig acfg, JumpLinkType type, JumpEdge edge)
|
public EdgeSampler Get(JumpLinkBuilderConfig acfg, JumpLinkType type, JumpEdge edge)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
public class GroundSample
|
public class GroundSample
|
||||||
{
|
{
|
||||||
public RcVec3f p = new RcVec3f();
|
public RcVec3f p;
|
||||||
public bool validTrajectory;
|
public bool validTrajectory;
|
||||||
public bool validHeight;
|
public bool validHeight;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
public class GroundSegment
|
public class GroundSegment
|
||||||
{
|
{
|
||||||
public RcVec3f p = new RcVec3f();
|
public RcVec3f p;
|
||||||
public RcVec3f q = new RcVec3f();
|
public RcVec3f q;
|
||||||
public GroundSample[] gsamples;
|
public GroundSample[] gsamples;
|
||||||
public float height;
|
public float height;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
using System;
|
||||||
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
|
namespace DotRecast.Detour.Extras.Jumplink
|
||||||
|
{
|
||||||
|
public interface ITrajectory
|
||||||
|
{
|
||||||
|
RcVec3f Apply(RcVec3f start, RcVec3f end, float u);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,6 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
public GroundSample[] endSamples;
|
public GroundSample[] endSamples;
|
||||||
public GroundSegment start;
|
public GroundSegment start;
|
||||||
public GroundSegment end;
|
public GroundSegment end;
|
||||||
public Trajectory trajectory;
|
public ITrajectory trajectory;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -59,7 +59,7 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
GroundSegment end = es.end[js.groundSegment];
|
GroundSegment end = es.end[js.groundSegment];
|
||||||
RcVec3f ep = end.gsamples[js.startSample].p;
|
RcVec3f ep = end.gsamples[js.startSample].p;
|
||||||
RcVec3f eq = end.gsamples[js.startSample + js.samples - 1].p;
|
RcVec3f eq = end.gsamples[js.startSample + js.samples - 1].p;
|
||||||
float d = Math.Min(RcVecUtils.Dist2DSqr(sp, sq), RcVecUtils.Dist2DSqr(ep, eq));
|
float d = Math.Min(RcVec.Dist2DSqr(sp, sq), RcVec.Dist2DSqr(ep, eq));
|
||||||
if (d >= 4 * acfg.agentRadius * acfg.agentRadius)
|
if (d >= 4 * acfg.agentRadius * acfg.agentRadius)
|
||||||
{
|
{
|
||||||
JumpLink link = new JumpLink();
|
JumpLink link = new JumpLink();
|
||||||
|
|
|
@ -4,7 +4,7 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Extras.Jumplink
|
namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
class JumpSegmentBuilder
|
public class JumpSegmentBuilder
|
||||||
{
|
{
|
||||||
public JumpSegment[] Build(JumpLinkBuilderConfig acfg, EdgeSampler es)
|
public JumpSegment[] Build(JumpLinkBuilderConfig acfg, EdgeSampler es)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Extras.Jumplink
|
namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
public class JumpTrajectory : Trajectory
|
public class JumpTrajectory : ITrajectory
|
||||||
{
|
{
|
||||||
private readonly float jumpHeight;
|
private readonly float jumpHeight;
|
||||||
|
|
||||||
|
@ -12,13 +13,13 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
this.jumpHeight = jumpHeight;
|
this.jumpHeight = jumpHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override RcVec3f Apply(RcVec3f start, RcVec3f end, float u)
|
public RcVec3f Apply(RcVec3f start, RcVec3f end, float u)
|
||||||
{
|
{
|
||||||
return new RcVec3f
|
return new RcVec3f
|
||||||
{
|
{
|
||||||
X = Lerp(start.X, end.X, u),
|
X = RcMath.Lerp(start.X, end.X, u),
|
||||||
Y = InterpolateHeight(start.Y, end.Y, u),
|
Y = InterpolateHeight(start.Y, end.Y, u),
|
||||||
Z = Lerp(start.Z, end.Z, u)
|
Z = RcMath.Lerp(start.Z, end.Z, u)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
using DotRecast.Recast;
|
using DotRecast.Recast;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Extras.Jumplink
|
namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
class NavMeshGroundSampler : AbstractGroundSampler
|
public class NavMeshGroundSampler : AbstractGroundSampler
|
||||||
{
|
{
|
||||||
public override void Sample(JumpLinkBuilderConfig acfg, RcBuilderResult result, EdgeSampler es)
|
public override void Sample(JumpLinkBuilderConfig acfg, RcBuilderResult result, EdgeSampler es)
|
||||||
{
|
{
|
||||||
|
@ -36,7 +35,14 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
option.cs = r.Mesh.cs;
|
option.cs = r.Mesh.cs;
|
||||||
option.ch = r.Mesh.ch;
|
option.ch = r.Mesh.ch;
|
||||||
option.buildBvTree = true;
|
option.buildBvTree = true;
|
||||||
return new DtNavMeshQuery(new DtNavMesh(DtNavMeshBuilder.CreateNavMeshData(option), option.nvp, 0));
|
var mesh = new DtNavMesh();
|
||||||
|
var status = mesh.Init(DtNavMeshBuilder.CreateNavMeshData(option), option.nvp, 0);
|
||||||
|
if (status.Failed())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DtNavMeshQuery(mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,7 +55,7 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
RcAtomicBoolean found = new RcAtomicBoolean();
|
RcAtomicBoolean found = new RcAtomicBoolean();
|
||||||
RcAtomicFloat minHeight = new RcAtomicFloat(pt.Y);
|
RcAtomicFloat minHeight = new RcAtomicFloat(pt.Y);
|
||||||
|
|
||||||
navMeshQuery.QueryPolygons(pt, halfExtents, DtQueryNoOpFilter.Shared, new PolyQueryInvoker((tile, poly, refs) =>
|
navMeshQuery.QueryPolygons(pt, halfExtents, DtQueryNoOpFilter.Shared, new DtCallbackPolyQuery((tile, poly, refs) =>
|
||||||
{
|
{
|
||||||
var status = navMeshQuery.GetPolyHeight(refs, pt, out var h);
|
var status = navMeshQuery.GetPolyHeight(refs, pt, out var h);
|
||||||
if (status.Succeeded())
|
if (status.Succeeded())
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour.Extras.Jumplink
|
|
||||||
{
|
|
||||||
public class PolyQueryInvoker : IDtPolyQuery
|
|
||||||
{
|
|
||||||
public readonly Action<DtMeshTile, DtPoly, long> _callback;
|
|
||||||
|
|
||||||
public PolyQueryInvoker(Action<DtMeshTile, DtPoly, long> callback)
|
|
||||||
{
|
|
||||||
_callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Process(DtMeshTile tile, DtPoly poly, long refs)
|
|
||||||
{
|
|
||||||
_callback?.Invoke(tile, poly, refs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
using System;
|
|
||||||
using DotRecast.Core.Numerics;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour.Extras.Jumplink
|
|
||||||
{
|
|
||||||
public class Trajectory
|
|
||||||
{
|
|
||||||
public float Lerp(float f, float g, float u)
|
|
||||||
{
|
|
||||||
return u * g + (1f - u) * f;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual RcVec3f Apply(RcVec3f start, RcVec3f end, float u)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@ using DotRecast.Recast;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Extras.Jumplink
|
namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
class TrajectorySampler
|
public class TrajectorySampler
|
||||||
{
|
{
|
||||||
public void Sample(JumpLinkBuilderConfig acfg, RcHeightfield heightfield, EdgeSampler es)
|
public void Sample(JumpLinkBuilderConfig acfg, RcHeightfield heightfield, EdgeSampler es)
|
||||||
{
|
{
|
||||||
|
@ -32,10 +32,10 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool SampleTrajectory(JumpLinkBuilderConfig acfg, RcHeightfield solid, RcVec3f pa, RcVec3f pb, Trajectory tra)
|
private bool SampleTrajectory(JumpLinkBuilderConfig acfg, RcHeightfield solid, RcVec3f pa, RcVec3f pb, ITrajectory tra)
|
||||||
{
|
{
|
||||||
float cs = Math.Min(acfg.cellSize, acfg.cellHeight);
|
float cs = Math.Min(acfg.cellSize, acfg.cellHeight);
|
||||||
float d = RcVecUtils.Dist2D(pa, pb) + MathF.Abs(pa.Y - pb.Y);
|
float d = RcVec.Dist2D(pa, pb) + MathF.Abs(pa.Y - pb.Y);
|
||||||
int nsamples = Math.Max(2, (int)MathF.Ceiling(d / cs));
|
int nsamples = Math.Max(2, (int)MathF.Ceiling(d / cs));
|
||||||
for (int i = 0; i < nsamples; ++i)
|
for (int i = 0; i < nsamples; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -22,6 +23,8 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Extras.Unity.Astar
|
namespace DotRecast.Detour.Extras.Unity.Astar
|
||||||
{
|
{
|
||||||
|
using static DtDetour;
|
||||||
|
|
||||||
public class GraphMeshDataReader : ZipBinaryReader
|
public class GraphMeshDataReader : ZipBinaryReader
|
||||||
{
|
{
|
||||||
public const float INT_PRECISION_FACTOR = 1000f;
|
public const float INT_PRECISION_FACTOR = 1000f;
|
||||||
|
@ -76,7 +79,7 @@ namespace DotRecast.Detour.Extras.Unity.Astar
|
||||||
int nodeCount = buffer.GetInt();
|
int nodeCount = buffer.GetInt();
|
||||||
DtPoly[] nodes = new DtPoly[nodeCount];
|
DtPoly[] nodes = new DtPoly[nodeCount];
|
||||||
DtPolyDetail[] detailNodes = new DtPolyDetail[nodeCount];
|
DtPolyDetail[] detailNodes = new DtPolyDetail[nodeCount];
|
||||||
float[] detailVerts = new float[0];
|
float[] detailVerts = Array.Empty<float>();
|
||||||
int[] detailTris = new int[4 * nodeCount];
|
int[] detailTris = new int[4 * nodeCount];
|
||||||
int vertMask = GetVertMask(vertsCount);
|
int vertMask = GetVertMask(vertsCount);
|
||||||
float ymin = float.PositiveInfinity;
|
float ymin = float.PositiveInfinity;
|
||||||
|
@ -98,9 +101,9 @@ namespace DotRecast.Detour.Extras.Unity.Astar
|
||||||
ymax = Math.Max(ymax, verts[nodes[i].verts[1] * 3 + 1]);
|
ymax = Math.Max(ymax, verts[nodes[i].verts[1] * 3 + 1]);
|
||||||
ymax = Math.Max(ymax, verts[nodes[i].verts[2] * 3 + 1]);
|
ymax = Math.Max(ymax, verts[nodes[i].verts[2] * 3 + 1]);
|
||||||
int vertBase = 0;
|
int vertBase = 0;
|
||||||
int vertCount = 0;
|
byte vertCount = 0;
|
||||||
int triBase = i;
|
int triBase = i;
|
||||||
int triCount = 1;
|
byte triCount = 1;
|
||||||
detailNodes[i] = new DtPolyDetail(vertBase, triBase, vertCount, triCount);
|
detailNodes[i] = new DtPolyDetail(vertBase, triBase, vertCount, triCount);
|
||||||
detailTris[4 * i] = 0;
|
detailTris[4 * i] = 0;
|
||||||
detailTris[4 * i + 1] = 1;
|
detailTris[4 * i + 1] = 1;
|
||||||
|
@ -116,15 +119,15 @@ namespace DotRecast.Detour.Extras.Unity.Astar
|
||||||
tiles[tileIndex].detailVerts = detailVerts;
|
tiles[tileIndex].detailVerts = detailVerts;
|
||||||
tiles[tileIndex].detailTris = detailTris;
|
tiles[tileIndex].detailTris = detailTris;
|
||||||
DtMeshHeader header = new DtMeshHeader();
|
DtMeshHeader header = new DtMeshHeader();
|
||||||
header.magic = DtNavMesh.DT_NAVMESH_MAGIC;
|
header.magic = DT_NAVMESH_MAGIC;
|
||||||
header.version = DtNavMesh.DT_NAVMESH_VERSION;
|
header.version = DT_NAVMESH_VERSION;
|
||||||
header.x = x;
|
header.x = x;
|
||||||
header.y = z;
|
header.y = z;
|
||||||
header.polyCount = nodeCount;
|
header.polyCount = nodeCount;
|
||||||
header.vertCount = vertsCount;
|
header.vertCount = vertsCount;
|
||||||
header.detailMeshCount = nodeCount;
|
header.detailMeshCount = nodeCount;
|
||||||
header.detailTriCount = nodeCount;
|
header.detailTriCount = nodeCount;
|
||||||
header.maxLinkCount = nodeCount * 3 * 2; // XXX: Needed by Recast, not needed by recast4j
|
header.maxLinkCount = nodeCount * 3 * 2; // needed by Recast, not needed by recast4j, needed by DotRecast
|
||||||
header.bmin.X = meta.forcedBoundsCenter.x - 0.5f * meta.forcedBoundsSize.x +
|
header.bmin.X = meta.forcedBoundsCenter.x - 0.5f * meta.forcedBoundsSize.x +
|
||||||
meta.cellSize * meta.tileSizeX * x;
|
meta.cellSize * meta.tileSizeX * x;
|
||||||
header.bmin.Y = ymin;
|
header.bmin.Y = ymin;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -21,6 +22,8 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Extras.Unity.Astar
|
namespace DotRecast.Detour.Extras.Unity.Astar
|
||||||
{
|
{
|
||||||
|
using static DtDetour;
|
||||||
|
|
||||||
public class LinkBuilder
|
public class LinkBuilder
|
||||||
{
|
{
|
||||||
// Process connections and transform them into recast neighbour flags
|
// Process connections and transform them into recast neighbour flags
|
||||||
|
@ -65,19 +68,19 @@ namespace DotRecast.Detour.Extras.Unity.Astar
|
||||||
{
|
{
|
||||||
if (neighbourTile.header.bmin.X > tile.header.bmin.X)
|
if (neighbourTile.header.bmin.X > tile.header.bmin.X)
|
||||||
{
|
{
|
||||||
node.neis[DtPolyUtils.FindEdge(node, tile, neighbourTile.header.bmin.X, 0)] = DtNavMesh.DT_EXT_LINK;
|
node.neis[DtPolyUtils.FindEdge(node, tile, neighbourTile.header.bmin.X, 0)] = DT_EXT_LINK;
|
||||||
}
|
}
|
||||||
else if (neighbourTile.header.bmin.X < tile.header.bmin.X)
|
else if (neighbourTile.header.bmin.X < tile.header.bmin.X)
|
||||||
{
|
{
|
||||||
node.neis[DtPolyUtils.FindEdge(node, tile, tile.header.bmin.X, 0)] = DtNavMesh.DT_EXT_LINK | 4;
|
node.neis[DtPolyUtils.FindEdge(node, tile, tile.header.bmin.X, 0)] = DT_EXT_LINK | 4;
|
||||||
}
|
}
|
||||||
else if (neighbourTile.header.bmin.Z > tile.header.bmin.Z)
|
else if (neighbourTile.header.bmin.Z > tile.header.bmin.Z)
|
||||||
{
|
{
|
||||||
node.neis[DtPolyUtils.FindEdge(node, tile, neighbourTile.header.bmin.Z, 2)] = DtNavMesh.DT_EXT_LINK | 2;
|
node.neis[DtPolyUtils.FindEdge(node, tile, neighbourTile.header.bmin.Z, 2)] = DT_EXT_LINK | 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node.neis[DtPolyUtils.FindEdge(node, tile, tile.header.bmin.Z, 2)] = DtNavMesh.DT_EXT_LINK | 6;
|
node.neis[DtPolyUtils.FindEdge(node, tile, tile.header.bmin.Z, 2)] = DT_EXT_LINK | 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -65,10 +66,11 @@ namespace DotRecast.Detour.Extras.Unity.Astar
|
||||||
option.orig.X = -0.5f * graphMeta.forcedBoundsSize.x + graphMeta.forcedBoundsCenter.x;
|
option.orig.X = -0.5f * graphMeta.forcedBoundsSize.x + graphMeta.forcedBoundsCenter.x;
|
||||||
option.orig.Y = -0.5f * graphMeta.forcedBoundsSize.y + graphMeta.forcedBoundsCenter.y;
|
option.orig.Y = -0.5f * graphMeta.forcedBoundsSize.y + graphMeta.forcedBoundsCenter.y;
|
||||||
option.orig.Z = -0.5f * graphMeta.forcedBoundsSize.z + graphMeta.forcedBoundsCenter.z;
|
option.orig.Z = -0.5f * graphMeta.forcedBoundsSize.z + graphMeta.forcedBoundsCenter.z;
|
||||||
DtNavMesh mesh = new DtNavMesh(option, 3);
|
DtNavMesh mesh = new DtNavMesh();
|
||||||
|
mesh.Init(option, 3);
|
||||||
foreach (DtMeshData t in graphMeshData.tiles)
|
foreach (DtMeshData t in graphMeshData.tiles)
|
||||||
{
|
{
|
||||||
mesh.AddTile(t, 0, 0);
|
mesh.AddTile(t, 0, 0, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
meshes[graphIndex] = mesh;
|
meshes[graphIndex] = mesh;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -31,7 +32,7 @@ namespace DotRecast.Detour.Extras.Unity.Astar
|
||||||
ZipArchiveEntry graphReferences = file.GetEntry(filename);
|
ZipArchiveEntry graphReferences = file.GetEntry(filename);
|
||||||
using var entryStream = graphReferences.Open();
|
using var entryStream = graphReferences.Open();
|
||||||
using var br = new BinaryReader(entryStream);
|
using var br = new BinaryReader(entryStream);
|
||||||
RcByteBuffer buffer = IOUtils.ToByteBuffer(br);
|
RcByteBuffer buffer = RcIO.ToByteBuffer(br);
|
||||||
buffer.Order(RcByteOrder.LITTLE_ENDIAN);
|
buffer.Order(RcByteOrder.LITTLE_ENDIAN);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
namespace DotRecast.Detour.TileCache
|
namespace DotRecast.Detour.TileCache
|
||||||
{
|
{
|
||||||
/// Flags for addTile
|
/// Flags for addTile
|
||||||
public class DtCompressedTileFlags
|
public class DtCompressedTileFlags
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache
|
namespace DotRecast.Detour.TileCache
|
||||||
{
|
{
|
||||||
|
@ -7,8 +7,9 @@ namespace DotRecast.Detour.TileCache
|
||||||
public const int DT_LAYER_MAX_NEIS = 16;
|
public const int DT_LAYER_MAX_NEIS = 16;
|
||||||
|
|
||||||
public int area;
|
public int area;
|
||||||
public List<int> neis = new List<int>(DT_LAYER_MAX_NEIS);
|
public byte[] neis = new byte[DT_LAYER_MAX_NEIS];
|
||||||
public int regId;
|
public byte nneis;
|
||||||
public int areaId;
|
public byte regId;
|
||||||
|
public byte areaId;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
|
namespace DotRecast.Detour.TileCache
|
||||||
|
{
|
||||||
|
public class DtObstacleBox
|
||||||
|
{
|
||||||
|
public RcVec3f bmin;
|
||||||
|
public RcVec3f bmax;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
|
namespace DotRecast.Detour.TileCache
|
||||||
|
{
|
||||||
|
public class DtObstacleCylinder
|
||||||
|
{
|
||||||
|
public RcVec3f pos;
|
||||||
|
public float radius;
|
||||||
|
public float height;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
|
namespace DotRecast.Detour.TileCache
|
||||||
|
{
|
||||||
|
public class DtObstacleOrientedBox
|
||||||
|
{
|
||||||
|
public RcVec3f center;
|
||||||
|
public RcVec3f extents;
|
||||||
|
public readonly float[] rotAux = new float[2]; // { Cos(0.5f*angle)*Sin(-0.5f*angle); Cos(0.5f*angle)*Cos(0.5f*angle) - 0.5 }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache
|
namespace DotRecast.Detour.TileCache
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,6 +26,8 @@ using DotRecast.Detour.TileCache.Io;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache
|
namespace DotRecast.Detour.TileCache
|
||||||
{
|
{
|
||||||
|
using static DtDetour;
|
||||||
|
|
||||||
public class DtTileCache
|
public class DtTileCache
|
||||||
{
|
{
|
||||||
private int m_tileLutSize; // < Tile hash lookup size (must be pot).
|
private int m_tileLutSize; // < Tile hash lookup size (must be pot).
|
||||||
|
@ -51,9 +53,6 @@ namespace DotRecast.Detour.TileCache
|
||||||
private readonly List<DtObstacleRequest> m_reqs = new List<DtObstacleRequest>();
|
private readonly List<DtObstacleRequest> m_reqs = new List<DtObstacleRequest>();
|
||||||
private readonly List<long> m_update = new List<long>();
|
private readonly List<long> m_update = new List<long>();
|
||||||
|
|
||||||
private readonly DtTileCacheBuilder builder = new DtTileCacheBuilder();
|
|
||||||
private readonly DtTileCacheLayerHeaderReader tileReader = new DtTileCacheLayerHeaderReader();
|
|
||||||
|
|
||||||
public DtTileCache(DtTileCacheParams option, DtTileCacheStorageParams storageParams, DtNavMesh navmesh, IRcCompressor tcomp, IDtTileCacheMeshProcess tmprocs)
|
public DtTileCache(DtTileCacheParams option, DtTileCacheStorageParams storageParams, DtNavMesh navmesh, IRcCompressor tcomp, IDtTileCacheMeshProcess tmprocs)
|
||||||
{
|
{
|
||||||
m_params = option;
|
m_params = option;
|
||||||
|
@ -160,7 +159,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
List<long> tiles = new List<long>();
|
List<long> tiles = new List<long>();
|
||||||
|
|
||||||
// Find tile based on hash.
|
// Find tile based on hash.
|
||||||
int h = DtNavMesh.ComputeTileHash(tx, ty, m_tileLutMask);
|
int h = ComputeTileHash(tx, ty, m_tileLutMask);
|
||||||
DtCompressedTile tile = m_posLookup[h];
|
DtCompressedTile tile = m_posLookup[h];
|
||||||
while (tile != null)
|
while (tile != null)
|
||||||
{
|
{
|
||||||
|
@ -178,7 +177,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
DtCompressedTile GetTileAt(int tx, int ty, int tlayer)
|
DtCompressedTile GetTileAt(int tx, int ty, int tlayer)
|
||||||
{
|
{
|
||||||
// Find tile based on hash.
|
// Find tile based on hash.
|
||||||
int h = DtNavMesh.ComputeTileHash(tx, ty, m_tileLutMask);
|
int h = ComputeTileHash(tx, ty, m_tileLutMask);
|
||||||
DtCompressedTile tile = m_posLookup[h];
|
DtCompressedTile tile = m_posLookup[h];
|
||||||
while (tile != null)
|
while (tile != null)
|
||||||
{
|
{
|
||||||
|
@ -243,7 +242,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
// Make sure the data is in right format.
|
// Make sure the data is in right format.
|
||||||
RcByteBuffer buf = new RcByteBuffer(data);
|
RcByteBuffer buf = new RcByteBuffer(data);
|
||||||
buf.Order(m_storageParams.Order);
|
buf.Order(m_storageParams.Order);
|
||||||
DtTileCacheLayerHeader header = tileReader.Read(buf, m_storageParams.Compatibility);
|
DtTileCacheLayerHeader header = DtTileCacheLayerHeaderReader.Read(buf, m_storageParams.Compatibility);
|
||||||
// Make sure the location is free.
|
// Make sure the location is free.
|
||||||
if (GetTileAt(header.tx, header.ty, header.tlayer) != null)
|
if (GetTileAt(header.tx, header.ty, header.tlayer) != null)
|
||||||
{
|
{
|
||||||
|
@ -266,7 +265,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert tile into the position lut.
|
// Insert tile into the position lut.
|
||||||
int h = DtNavMesh.ComputeTileHash(header.tx, header.ty, m_tileLutMask);
|
int h = ComputeTileHash(header.tx, header.ty, m_tileLutMask);
|
||||||
tile.next = m_posLookup[h];
|
tile.next = m_posLookup[h];
|
||||||
m_posLookup[h] = tile;
|
m_posLookup[h] = tile;
|
||||||
|
|
||||||
|
@ -305,7 +304,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove tile from hash lookup.
|
// Remove tile from hash lookup.
|
||||||
int h = DtNavMesh.ComputeTileHash(tile.header.tx, tile.header.ty, m_tileLutMask);
|
int h = ComputeTileHash(tile.header.tx, tile.header.ty, m_tileLutMask);
|
||||||
DtCompressedTile prev = null;
|
DtCompressedTile prev = null;
|
||||||
DtCompressedTile cur = m_posLookup[h];
|
DtCompressedTile cur = m_posLookup[h];
|
||||||
while (cur != null)
|
while (cur != null)
|
||||||
|
@ -349,11 +348,11 @@ namespace DotRecast.Detour.TileCache
|
||||||
public long AddObstacle(RcVec3f pos, float radius, float height)
|
public long AddObstacle(RcVec3f pos, float radius, float height)
|
||||||
{
|
{
|
||||||
DtTileCacheObstacle ob = AllocObstacle();
|
DtTileCacheObstacle ob = AllocObstacle();
|
||||||
ob.type = DtTileCacheObstacleType.CYLINDER;
|
ob.type = DtTileCacheObstacleType.DT_OBSTACLE_CYLINDER;
|
||||||
|
|
||||||
ob.pos = pos;
|
ob.cylinder.pos = pos;
|
||||||
ob.radius = radius;
|
ob.cylinder.radius = radius;
|
||||||
ob.height = height;
|
ob.cylinder.height = height;
|
||||||
|
|
||||||
return AddObstacleRequest(ob).refs;
|
return AddObstacleRequest(ob).refs;
|
||||||
}
|
}
|
||||||
|
@ -362,10 +361,10 @@ namespace DotRecast.Detour.TileCache
|
||||||
public long AddBoxObstacle(RcVec3f bmin, RcVec3f bmax)
|
public long AddBoxObstacle(RcVec3f bmin, RcVec3f bmax)
|
||||||
{
|
{
|
||||||
DtTileCacheObstacle ob = AllocObstacle();
|
DtTileCacheObstacle ob = AllocObstacle();
|
||||||
ob.type = DtTileCacheObstacleType.BOX;
|
ob.type = DtTileCacheObstacleType.DT_OBSTACLE_BOX;
|
||||||
|
|
||||||
ob.bmin = bmin;
|
ob.box.bmin = bmin;
|
||||||
ob.bmax = bmax;
|
ob.box.bmax = bmax;
|
||||||
|
|
||||||
return AddObstacleRequest(ob).refs;
|
return AddObstacleRequest(ob).refs;
|
||||||
}
|
}
|
||||||
|
@ -374,13 +373,13 @@ namespace DotRecast.Detour.TileCache
|
||||||
public long AddBoxObstacle(RcVec3f center, RcVec3f extents, float yRadians)
|
public long AddBoxObstacle(RcVec3f center, RcVec3f extents, float yRadians)
|
||||||
{
|
{
|
||||||
DtTileCacheObstacle ob = AllocObstacle();
|
DtTileCacheObstacle ob = AllocObstacle();
|
||||||
ob.type = DtTileCacheObstacleType.ORIENTED_BOX;
|
ob.type = DtTileCacheObstacleType.DT_OBSTACLE_ORIENTED_BOX;
|
||||||
ob.center = center;
|
ob.orientedBox.center = center;
|
||||||
ob.extents = extents;
|
ob.orientedBox.extents = extents;
|
||||||
float coshalf = MathF.Cos(0.5f * yRadians);
|
float coshalf = MathF.Cos(0.5f * yRadians);
|
||||||
float sinhalf = MathF.Sin(-0.5f * yRadians);
|
float sinhalf = MathF.Sin(-0.5f * yRadians);
|
||||||
ob.rotAux[0] = coshalf * sinhalf;
|
ob.orientedBox.rotAux[0] = coshalf * sinhalf;
|
||||||
ob.rotAux[1] = coshalf * coshalf - 0.5f;
|
ob.orientedBox.rotAux[1] = coshalf * coshalf - 0.5f;
|
||||||
return AddObstacleRequest(ob).refs;
|
return AddObstacleRequest(ob).refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,26 +612,26 @@ namespace DotRecast.Detour.TileCache
|
||||||
|
|
||||||
if (Contains(ob.touched, refs))
|
if (Contains(ob.touched, refs))
|
||||||
{
|
{
|
||||||
if (ob.type == DtTileCacheObstacleType.CYLINDER)
|
if (ob.type == DtTileCacheObstacleType.DT_OBSTACLE_CYLINDER)
|
||||||
{
|
{
|
||||||
builder.MarkCylinderArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.pos, ob.radius, ob.height, 0);
|
DtTileCacheBuilder.MarkCylinderArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.cylinder.pos, ob.cylinder.radius, ob.cylinder.height, 0);
|
||||||
}
|
}
|
||||||
else if (ob.type == DtTileCacheObstacleType.BOX)
|
else if (ob.type == DtTileCacheObstacleType.DT_OBSTACLE_BOX)
|
||||||
{
|
{
|
||||||
builder.MarkBoxArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.bmin, ob.bmax, 0);
|
DtTileCacheBuilder.MarkBoxArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.box.bmin, ob.box.bmax, 0);
|
||||||
}
|
}
|
||||||
else if (ob.type == DtTileCacheObstacleType.ORIENTED_BOX)
|
else if (ob.type == DtTileCacheObstacleType.DT_OBSTACLE_ORIENTED_BOX)
|
||||||
{
|
{
|
||||||
builder.MarkBoxArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.center, ob.extents, ob.rotAux, 0);
|
DtTileCacheBuilder.MarkBoxArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.orientedBox.center, ob.orientedBox.extents, ob.orientedBox.rotAux, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build navmesh
|
// Build navmesh
|
||||||
builder.BuildTileCacheRegions(layer, walkableClimbVx);
|
DtTileCacheBuilder.BuildTileCacheRegions(layer, walkableClimbVx);
|
||||||
DtTileCacheContourSet lcset = builder.BuildTileCacheContours(layer, walkableClimbVx,
|
DtTileCacheContourSet lcset = DtTileCacheBuilder.BuildTileCacheContours(layer, walkableClimbVx, m_params.maxSimplificationError);
|
||||||
m_params.maxSimplificationError);
|
DtTileCachePolyMesh polyMesh = DtTileCacheBuilder.BuildTileCachePolyMesh(lcset, m_navmesh.GetMaxVertsPerPoly());
|
||||||
DtTileCachePolyMesh polyMesh = builder.BuildTileCachePolyMesh(lcset, m_navmesh.GetMaxVertsPerPoly());
|
|
||||||
// Early out if the mesh tile is empty.
|
// Early out if the mesh tile is empty.
|
||||||
if (polyMesh.npolys == 0)
|
if (polyMesh.npolys == 0)
|
||||||
{
|
{
|
||||||
|
@ -670,13 +669,13 @@ namespace DotRecast.Detour.TileCache
|
||||||
// Add new tile, or leave the location empty. if (navData) { // Let the
|
// Add new tile, or leave the location empty. if (navData) { // Let the
|
||||||
if (meshData != null)
|
if (meshData != null)
|
||||||
{
|
{
|
||||||
m_navmesh.AddTile(meshData, 0, 0);
|
m_navmesh.AddTile(meshData, 0, 0, out var result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtTileCacheLayer DecompressTile(DtCompressedTile tile)
|
public DtTileCacheLayer DecompressTile(DtCompressedTile tile)
|
||||||
{
|
{
|
||||||
DtTileCacheLayer layer = builder.DecompressTileCacheLayer(m_tcomp, tile.data, m_storageParams.Order, m_storageParams.Compatibility);
|
DtTileCacheLayer layer = DtTileCacheBuilder.DecompressTileCacheLayer(m_tcomp, tile.data, m_storageParams.Order, m_storageParams.Compatibility);
|
||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,29 +692,29 @@ namespace DotRecast.Detour.TileCache
|
||||||
|
|
||||||
public void GetObstacleBounds(DtTileCacheObstacle ob, ref RcVec3f bmin, ref RcVec3f bmax)
|
public void GetObstacleBounds(DtTileCacheObstacle ob, ref RcVec3f bmin, ref RcVec3f bmax)
|
||||||
{
|
{
|
||||||
if (ob.type == DtTileCacheObstacleType.CYLINDER)
|
if (ob.type == DtTileCacheObstacleType.DT_OBSTACLE_CYLINDER)
|
||||||
{
|
{
|
||||||
bmin.X = ob.pos.X - ob.radius;
|
bmin.X = ob.cylinder.pos.X - ob.cylinder.radius;
|
||||||
bmin.Y = ob.pos.Y;
|
bmin.Y = ob.cylinder.pos.Y;
|
||||||
bmin.Z = ob.pos.Z - ob.radius;
|
bmin.Z = ob.cylinder.pos.Z - ob.cylinder.radius;
|
||||||
bmax.X = ob.pos.X + ob.radius;
|
bmax.X = ob.cylinder.pos.X + ob.cylinder.radius;
|
||||||
bmax.Y = ob.pos.Y + ob.height;
|
bmax.Y = ob.cylinder.pos.Y + ob.cylinder.height;
|
||||||
bmax.Z = ob.pos.Z + ob.radius;
|
bmax.Z = ob.cylinder.pos.Z + ob.cylinder.radius;
|
||||||
}
|
}
|
||||||
else if (ob.type == DtTileCacheObstacleType.BOX)
|
else if (ob.type == DtTileCacheObstacleType.DT_OBSTACLE_BOX)
|
||||||
{
|
{
|
||||||
bmin = ob.bmin;
|
bmin = ob.box.bmin;
|
||||||
bmax = ob.bmax;
|
bmax = ob.box.bmax;
|
||||||
}
|
}
|
||||||
else if (ob.type == DtTileCacheObstacleType.ORIENTED_BOX)
|
else if (ob.type == DtTileCacheObstacleType.DT_OBSTACLE_ORIENTED_BOX)
|
||||||
{
|
{
|
||||||
float maxr = 1.41f * Math.Max(ob.extents.X, ob.extents.Z);
|
float maxr = 1.41f * Math.Max(ob.orientedBox.extents.X, ob.orientedBox.extents.Z);
|
||||||
bmin.X = ob.center.X - maxr;
|
bmin.X = ob.orientedBox.center.X - maxr;
|
||||||
bmax.X = ob.center.X + maxr;
|
bmax.X = ob.orientedBox.center.X + maxr;
|
||||||
bmin.Y = ob.center.Y - ob.extents.Y;
|
bmin.Y = ob.orientedBox.center.Y - ob.orientedBox.extents.Y;
|
||||||
bmax.Y = ob.center.Y + ob.extents.Y;
|
bmax.Y = ob.orientedBox.center.Y + ob.orientedBox.extents.Y;
|
||||||
bmin.Z = ob.center.Z - maxr;
|
bmin.Z = ob.orientedBox.center.Z - maxr;
|
||||||
bmax.Z = ob.center.Z + maxr;
|
bmax.Z = ob.orientedBox.center.Z + maxr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -29,22 +29,21 @@ using DotRecast.Recast;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache
|
namespace DotRecast.Detour.TileCache
|
||||||
{
|
{
|
||||||
public class DtTileCacheBuilder
|
public static class DtTileCacheBuilder
|
||||||
{
|
{
|
||||||
public const int DT_TILECACHE_NULL_AREA = 0;
|
public const byte DT_TILECACHE_NULL_AREA = 0;
|
||||||
public const int DT_TILECACHE_WALKABLE_AREA = 63;
|
public const byte DT_TILECACHE_WALKABLE_AREA = 63;
|
||||||
public const int DT_TILECACHE_NULL_IDX = 0xffff;
|
public const int DT_TILECACHE_NULL_IDX = 0xffff;
|
||||||
|
|
||||||
private static readonly int[] DirOffsetX = { -1, 0, 1, 0, };
|
private static readonly int[] DirOffsetX = { -1, 0, 1, 0, };
|
||||||
private static readonly int[] DirOffsetY = { 0, 1, 0, -1 };
|
private static readonly int[] DirOffsetY = { 0, 1, 0, -1 };
|
||||||
|
|
||||||
private readonly DtTileCacheLayerHeaderReader reader = new DtTileCacheLayerHeaderReader();
|
public static void BuildTileCacheRegions(DtTileCacheLayer layer, int walkableClimb)
|
||||||
|
|
||||||
public void BuildTileCacheRegions(DtTileCacheLayer layer, int walkableClimb)
|
|
||||||
{
|
{
|
||||||
int w = layer.header.width;
|
int w = layer.header.width;
|
||||||
int h = layer.header.height;
|
int h = layer.header.height;
|
||||||
|
|
||||||
Array.Fill(layer.regs, (short)0x00FF);
|
Array.Fill(layer.regs, (byte)0xFF);
|
||||||
int nsweeps = w;
|
int nsweeps = w;
|
||||||
RcLayerSweepSpan[] sweeps = new RcLayerSweepSpan[nsweeps];
|
RcLayerSweepSpan[] sweeps = new RcLayerSweepSpan[nsweeps];
|
||||||
for (int i = 0; i < sweeps.Length; i++)
|
for (int i = 0; i < sweeps.Length; i++)
|
||||||
|
@ -53,14 +52,14 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
|
|
||||||
// Partition walkable area into monotone regions.
|
// Partition walkable area into monotone regions.
|
||||||
int[] prevCount = new int[256];
|
Span<byte> prevCount = stackalloc byte[256];
|
||||||
int regId = 0;
|
byte regId = 0;
|
||||||
|
|
||||||
for (int y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
if (regId > 0)
|
if (regId > 0)
|
||||||
{
|
{
|
||||||
Array.Fill(prevCount, 0, 0, regId);
|
RcSpans.Fill<byte>(prevCount, 0, 0, regId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Memset(prevCount,0,Sizeof(char)*regId);
|
// Memset(prevCount,0,Sizeof(char)*regId);
|
||||||
|
@ -93,7 +92,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
int yidx = x + (y - 1) * w;
|
int yidx = x + (y - 1) * w;
|
||||||
if (y > 0 && IsConnected(layer, idx, yidx, walkableClimb))
|
if (y > 0 && IsConnected(layer, idx, yidx, walkableClimb))
|
||||||
{
|
{
|
||||||
int nr = layer.regs[yidx];
|
byte nr = layer.regs[yidx];
|
||||||
if (nr != 0xff)
|
if (nr != 0xff)
|
||||||
{
|
{
|
||||||
// Set neighbour when first valid neighbour is
|
// Set neighbour when first valid neighbour is
|
||||||
|
@ -147,12 +146,12 @@ namespace DotRecast.Detour.TileCache
|
||||||
{
|
{
|
||||||
int idx = x + y * w;
|
int idx = x + y * w;
|
||||||
if (layer.regs[idx] != 0xff)
|
if (layer.regs[idx] != 0xff)
|
||||||
layer.regs[idx] = (short)sweeps[layer.regs[idx]].id;
|
layer.regs[idx] = sweeps[layer.regs[idx]].id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate and init layer regions.
|
// Allocate and init layer regions.
|
||||||
int nregs = regId;
|
byte nregs = regId;
|
||||||
DtLayerMonotoneRegion[] regs = new DtLayerMonotoneRegion[nregs];
|
DtLayerMonotoneRegion[] regs = new DtLayerMonotoneRegion[nregs];
|
||||||
|
|
||||||
for (int i = 0; i < nregs; ++i)
|
for (int i = 0; i < nregs; ++i)
|
||||||
|
@ -167,7 +166,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
for (int x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
int idx = x + y * w;
|
int idx = x + y * w;
|
||||||
int ri = layer.regs[idx];
|
byte ri = layer.regs[idx];
|
||||||
if (ri == 0xff)
|
if (ri == 0xff)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -179,17 +178,17 @@ namespace DotRecast.Detour.TileCache
|
||||||
int ymi = x + (y - 1) * w;
|
int ymi = x + (y - 1) * w;
|
||||||
if (y > 0 && IsConnected(layer, idx, ymi, walkableClimb))
|
if (y > 0 && IsConnected(layer, idx, ymi, walkableClimb))
|
||||||
{
|
{
|
||||||
int rai = layer.regs[ymi];
|
byte rai = layer.regs[ymi];
|
||||||
if (rai != 0xff && rai != ri)
|
if (rai != 0xff && rai != ri)
|
||||||
{
|
{
|
||||||
AddUniqueLast(regs[ri].neis, rai);
|
AddUniqueLast(regs[ri].neis, ref regs[ri].nneis, rai);
|
||||||
AddUniqueLast(regs[rai].neis, ri);
|
AddUniqueLast(regs[rai].neis, ref regs[rai].nneis, ri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < nregs; ++i)
|
for (byte i = 0; i < nregs; ++i)
|
||||||
regs[i].regId = i;
|
regs[i].regId = i;
|
||||||
|
|
||||||
for (int i = 0; i < nregs; ++i)
|
for (int i = 0; i < nregs; ++i)
|
||||||
|
@ -198,8 +197,9 @@ namespace DotRecast.Detour.TileCache
|
||||||
|
|
||||||
int merge = -1;
|
int merge = -1;
|
||||||
int mergea = 0;
|
int mergea = 0;
|
||||||
foreach (int nei in reg.neis)
|
for (int j = 0; j < reg.nneis; ++j)
|
||||||
{
|
{
|
||||||
|
byte nei = reg.neis[j];
|
||||||
DtLayerMonotoneRegion regn = regs[nei];
|
DtLayerMonotoneRegion regn = regs[nei];
|
||||||
if (reg.regId == regn.regId)
|
if (reg.regId == regn.regId)
|
||||||
continue;
|
continue;
|
||||||
|
@ -218,7 +218,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
if (merge != -1)
|
if (merge != -1)
|
||||||
{
|
{
|
||||||
int oldId = reg.regId;
|
int oldId = reg.regId;
|
||||||
int newId = regs[merge].regId;
|
byte newId = regs[merge].regId;
|
||||||
for (int j = 0; j < nregs; ++j)
|
for (int j = 0; j < nregs; ++j)
|
||||||
if (regs[j].regId == oldId)
|
if (regs[j].regId == oldId)
|
||||||
regs[j].regId = newId;
|
regs[j].regId = newId;
|
||||||
|
@ -226,7 +226,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compact ids.
|
// Compact ids.
|
||||||
int[] remap = new int[256];
|
Span<byte> remap = stackalloc byte[256];
|
||||||
// Find number of unique regions.
|
// Find number of unique regions.
|
||||||
regId = 0;
|
regId = 0;
|
||||||
for (int i = 0; i < nregs; ++i)
|
for (int i = 0; i < nregs; ++i)
|
||||||
|
@ -243,19 +243,20 @@ namespace DotRecast.Detour.TileCache
|
||||||
for (int i = 0; i < w * h; ++i)
|
for (int i = 0; i < w * h; ++i)
|
||||||
{
|
{
|
||||||
if (layer.regs[i] != 0xff)
|
if (layer.regs[i] != 0xff)
|
||||||
layer.regs[i] = (short)regs[layer.regs[i]].regId;
|
layer.regs[i] = regs[layer.regs[i]].regId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddUniqueLast(List<int> a, int v)
|
public static void AddUniqueLast(byte[] a, ref byte an, byte v)
|
||||||
{
|
{
|
||||||
int n = a.Count;
|
int n = an;
|
||||||
if (n > 0 && a[n - 1] == v)
|
if (n > 0 && a[n - 1] == v)
|
||||||
return;
|
return;
|
||||||
a.Add(v);
|
a[an] = v;
|
||||||
|
an++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsConnected(DtTileCacheLayer layer, int ia, int ib, int walkableClimb)
|
public static bool IsConnected(DtTileCacheLayer layer, int ia, int ib, int walkableClimb)
|
||||||
{
|
{
|
||||||
if (layer.areas[ia] != layer.areas[ib])
|
if (layer.areas[ia] != layer.areas[ib])
|
||||||
return false;
|
return false;
|
||||||
|
@ -264,7 +265,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanMerge(int oldRegId, int newRegId, DtLayerMonotoneRegion[] regs, int nregs)
|
public static bool CanMerge(int oldRegId, int newRegId, DtLayerMonotoneRegion[] regs, int nregs)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int i = 0; i < nregs; ++i)
|
for (int i = 0; i < nregs; ++i)
|
||||||
|
@ -272,9 +273,11 @@ namespace DotRecast.Detour.TileCache
|
||||||
DtLayerMonotoneRegion reg = regs[i];
|
DtLayerMonotoneRegion reg = regs[i];
|
||||||
if (reg.regId != oldRegId)
|
if (reg.regId != oldRegId)
|
||||||
continue;
|
continue;
|
||||||
foreach (int nei in reg.neis)
|
|
||||||
|
int nnei = reg.nneis;
|
||||||
|
for (int j = 0; j < nnei ; ++j)
|
||||||
{
|
{
|
||||||
if (regs[nei].regId == newRegId)
|
if (regs[reg.neis[j]].regId == newRegId)
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,7 +285,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return count == 1;
|
return count == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AppendVertex(DtTempContour cont, int x, int y, int z, int r)
|
public static void AppendVertex(DtTempContour cont, int x, int y, int z, int r)
|
||||||
{
|
{
|
||||||
// Try to merge with existing segments.
|
// Try to merge with existing segments.
|
||||||
if (cont.nverts > 1)
|
if (cont.nverts > 1)
|
||||||
|
@ -316,7 +319,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
cont.nverts++;
|
cont.nverts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetNeighbourReg(DtTileCacheLayer layer, int ax, int ay, int dir)
|
public static int GetNeighbourReg(DtTileCacheLayer layer, int ax, int ay, int dir)
|
||||||
{
|
{
|
||||||
int w = layer.header.width;
|
int w = layer.header.width;
|
||||||
int ia = ax + ay * w;
|
int ia = ax + ay * w;
|
||||||
|
@ -339,17 +342,17 @@ namespace DotRecast.Detour.TileCache
|
||||||
return layer.regs[ib];
|
return layer.regs[ib];
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetDirOffsetX(int dir)
|
public static int GetDirOffsetX(int dir)
|
||||||
{
|
{
|
||||||
return DirOffsetX[dir & 0x03];
|
return DirOffsetX[dir & 0x03];
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetDirOffsetY(int dir)
|
public static int GetDirOffsetY(int dir)
|
||||||
{
|
{
|
||||||
return DirOffsetY[dir & 0x03];
|
return DirOffsetY[dir & 0x03];
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WalkContour(DtTileCacheLayer layer, int x, int y, DtTempContour cont)
|
public static void WalkContour(DtTileCacheLayer layer, int x, int y, DtTempContour cont)
|
||||||
{
|
{
|
||||||
int w = layer.header.width;
|
int w = layer.header.width;
|
||||||
int h = layer.header.height;
|
int h = layer.header.height;
|
||||||
|
@ -434,7 +437,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
cont.nverts--;
|
cont.nverts--;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float DistancePtSeg(int x, int z, int px, int pz, int qx, int qz)
|
public static float DistancePtSeg(int x, int z, int px, int pz, int qx, int qz)
|
||||||
{
|
{
|
||||||
float pqx = qx - px;
|
float pqx = qx - px;
|
||||||
float pqz = qz - pz;
|
float pqz = qz - pz;
|
||||||
|
@ -455,7 +458,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return dx * dx + dz * dz;
|
return dx * dx + dz * dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SimplifyContour(DtTempContour cont, float maxError)
|
public static void SimplifyContour(DtTempContour cont, float maxError)
|
||||||
{
|
{
|
||||||
cont.poly.Clear();
|
cont.poly.Clear();
|
||||||
|
|
||||||
|
@ -584,7 +587,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GetCornerHeight(DtTileCacheLayer layer, int x, int y, int z, int walkableClimb, out bool shouldRemove)
|
public static int GetCornerHeight(DtTileCacheLayer layer, int x, int y, int z, int walkableClimb, out bool shouldRemove)
|
||||||
{
|
{
|
||||||
int w = layer.header.width;
|
int w = layer.header.width;
|
||||||
int h = layer.header.height;
|
int h = layer.header.height;
|
||||||
|
@ -634,7 +637,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move this somewhere else, once the layer meshing is done.
|
// TODO: move this somewhere else, once the layer meshing is done.
|
||||||
public DtTileCacheContourSet BuildTileCacheContours(DtTileCacheLayer layer, int walkableClimb, float maxError)
|
public static DtTileCacheContourSet BuildTileCacheContours(DtTileCacheLayer layer, int walkableClimb, float maxError)
|
||||||
{
|
{
|
||||||
int w = layer.header.width;
|
int w = layer.header.width;
|
||||||
int h = layer.header.height;
|
int h = layer.header.height;
|
||||||
|
@ -656,7 +659,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
for (int x = 0; x < w; ++x)
|
for (int x = 0; x < w; ++x)
|
||||||
{
|
{
|
||||||
int idx = x + y * w;
|
int idx = x + y * w;
|
||||||
int ri = layer.regs[idx];
|
byte ri = layer.regs[idx];
|
||||||
if (ri == 0xff)
|
if (ri == 0xff)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -711,7 +714,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
|
|
||||||
const uint VERTEX_BUCKET_COUNT2 = (1 << 8);
|
const uint VERTEX_BUCKET_COUNT2 = (1 << 8);
|
||||||
|
|
||||||
private int ComputeVertexHash2(int x, int y, int z)
|
public static int ComputeVertexHash2(int x, int y, int z)
|
||||||
{
|
{
|
||||||
uint h1 = 0x8da6b343; // Large multiplicative constants;
|
uint h1 = 0x8da6b343; // Large multiplicative constants;
|
||||||
uint h2 = 0xd8163841; // here arbitrarily chosen primes
|
uint h2 = 0xd8163841; // here arbitrarily chosen primes
|
||||||
|
@ -720,7 +723,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return (int)(n & (VERTEX_BUCKET_COUNT2 - 1));
|
return (int)(n & (VERTEX_BUCKET_COUNT2 - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
private int AddVertex(int x, int y, int z, int[] verts, int[] firstVert, int[] nextVert, int nv)
|
public static int AddVertex(int x, int y, int z, int[] verts, int[] firstVert, int[] nextVert, int nv)
|
||||||
{
|
{
|
||||||
int bucket = ComputeVertexHash2(x, 0, z);
|
int bucket = ComputeVertexHash2(x, 0, z);
|
||||||
int i = firstVert[bucket];
|
int i = firstVert[bucket];
|
||||||
|
@ -743,7 +746,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildMeshAdjacency(int[] polys, int npolys, int[] verts, int nverts, DtTileCacheContourSet lcset,
|
public static void BuildMeshAdjacency(int[] polys, int npolys, int[] verts, int nverts, DtTileCacheContourSet lcset,
|
||||||
int maxVertsPerPoly)
|
int maxVertsPerPoly)
|
||||||
{
|
{
|
||||||
// Based on code by Eric Lengyel from:
|
// Based on code by Eric Lengyel from:
|
||||||
|
@ -954,22 +957,22 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool OverlapRangeExl(int amin, int amax, int bmin, int bmax)
|
public static bool OverlapRangeExl(int amin, int amax, int bmin, int bmax)
|
||||||
{
|
{
|
||||||
return (amin >= bmax || amax <= bmin) ? false : true;
|
return (amin >= bmax || amax <= bmin) ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int Prev(int i, int n)
|
public static int Prev(int i, int n)
|
||||||
{
|
{
|
||||||
return i - 1 >= 0 ? i - 1 : n - 1;
|
return i - 1 >= 0 ? i - 1 : n - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int Next(int i, int n)
|
public static int Next(int i, int n)
|
||||||
{
|
{
|
||||||
return i + 1 < n ? i + 1 : 0;
|
return i + 1 < n ? i + 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int Area2(int[] verts, int a, int b, int c)
|
public static int Area2(int[] verts, int a, int b, int c)
|
||||||
{
|
{
|
||||||
return (verts[b] - verts[a]) * (verts[c + 2] - verts[a + 2])
|
return (verts[b] - verts[a]) * (verts[c + 2] - verts[a + 2])
|
||||||
- (verts[c] - verts[a]) * (verts[b + 2] - verts[a + 2]);
|
- (verts[c] - verts[a]) * (verts[b + 2] - verts[a + 2]);
|
||||||
|
@ -977,17 +980,17 @@ namespace DotRecast.Detour.TileCache
|
||||||
|
|
||||||
// Returns true iff c is strictly to the left of the directed
|
// Returns true iff c is strictly to the left of the directed
|
||||||
// line through a to b.
|
// line through a to b.
|
||||||
private bool Left(int[] verts, int a, int b, int c)
|
public static bool Left(int[] verts, int a, int b, int c)
|
||||||
{
|
{
|
||||||
return Area2(verts, a, b, c) < 0;
|
return Area2(verts, a, b, c) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool LeftOn(int[] verts, int a, int b, int c)
|
public static bool LeftOn(int[] verts, int a, int b, int c)
|
||||||
{
|
{
|
||||||
return Area2(verts, a, b, c) <= 0;
|
return Area2(verts, a, b, c) <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Collinear(int[] verts, int a, int b, int c)
|
public static bool Collinear(int[] verts, int a, int b, int c)
|
||||||
{
|
{
|
||||||
return Area2(verts, a, b, c) == 0;
|
return Area2(verts, a, b, c) == 0;
|
||||||
}
|
}
|
||||||
|
@ -995,7 +998,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
// Returns true iff ab properly intersects cd: they share
|
// Returns true iff ab properly intersects cd: they share
|
||||||
// a point interior to both segments. The properness of the
|
// a point interior to both segments. The properness of the
|
||||||
// intersection is ensured by using strict leftness.
|
// intersection is ensured by using strict leftness.
|
||||||
private bool IntersectProp(int[] verts, int a, int b, int c, int d)
|
public static bool IntersectProp(int[] verts, int a, int b, int c, int d)
|
||||||
{
|
{
|
||||||
// Eliminate improper cases.
|
// Eliminate improper cases.
|
||||||
if (Collinear(verts, a, b, c) || Collinear(verts, a, b, d) || Collinear(verts, c, d, a)
|
if (Collinear(verts, a, b, c) || Collinear(verts, a, b, d) || Collinear(verts, c, d, a)
|
||||||
|
@ -1007,7 +1010,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
|
|
||||||
// Returns T iff (a,b,c) are collinear and point c lies
|
// Returns T iff (a,b,c) are collinear and point c lies
|
||||||
// on the closed segment ab.
|
// on the closed segment ab.
|
||||||
private bool Between(int[] verts, int a, int b, int c)
|
public static bool Between(int[] verts, int a, int b, int c)
|
||||||
{
|
{
|
||||||
if (!Collinear(verts, a, b, c))
|
if (!Collinear(verts, a, b, c))
|
||||||
return false;
|
return false;
|
||||||
|
@ -1021,7 +1024,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff segments ab and cd intersect, properly or improperly.
|
// Returns true iff segments ab and cd intersect, properly or improperly.
|
||||||
private bool Intersect(int[] verts, int a, int b, int c, int d)
|
public static bool Intersect(int[] verts, int a, int b, int c, int d)
|
||||||
{
|
{
|
||||||
if (IntersectProp(verts, a, b, c, d))
|
if (IntersectProp(verts, a, b, c, d))
|
||||||
return true;
|
return true;
|
||||||
|
@ -1032,14 +1035,14 @@ namespace DotRecast.Detour.TileCache
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Vequal(int[] verts, int a, int b)
|
public static bool Vequal(int[] verts, int a, int b)
|
||||||
{
|
{
|
||||||
return verts[a] == verts[b] && verts[a + 2] == verts[b + 2];
|
return verts[a] == verts[b] && verts[a + 2] == verts[b + 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns T iff (v_i, v_j) is a proper internal *or* external
|
// Returns T iff (v_i, v_j) is a proper internal *or* external
|
||||||
// diagonal of P, *ignoring edges incident to v_i and v_j*.
|
// diagonal of P, *ignoring edges incident to v_i and v_j*.
|
||||||
private bool Diagonalie(int i, int j, int n, int[] verts, int[] indices)
|
public static bool Diagonalie(int i, int j, int n, int[] verts, int[] indices)
|
||||||
{
|
{
|
||||||
int d0 = (indices[i] & 0x7fff) * 4;
|
int d0 = (indices[i] & 0x7fff) * 4;
|
||||||
int d1 = (indices[j] & 0x7fff) * 4;
|
int d1 = (indices[j] & 0x7fff) * 4;
|
||||||
|
@ -1067,7 +1070,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
|
|
||||||
// Returns true iff the diagonal (i,j) is strictly internal to the
|
// Returns true iff the diagonal (i,j) is strictly internal to the
|
||||||
// polygon P in the neighborhood of the i endpoint.
|
// polygon P in the neighborhood of the i endpoint.
|
||||||
private bool InCone(int i, int j, int n, int[] verts, int[] indices)
|
public static bool InCone(int i, int j, int n, int[] verts, int[] indices)
|
||||||
{
|
{
|
||||||
int pi = (indices[i] & 0x7fff) * 4;
|
int pi = (indices[i] & 0x7fff) * 4;
|
||||||
int pj = (indices[j] & 0x7fff) * 4;
|
int pj = (indices[j] & 0x7fff) * 4;
|
||||||
|
@ -1084,12 +1087,12 @@ namespace DotRecast.Detour.TileCache
|
||||||
|
|
||||||
// Returns T iff (v_i, v_j) is a proper internal
|
// Returns T iff (v_i, v_j) is a proper internal
|
||||||
// diagonal of P.
|
// diagonal of P.
|
||||||
private bool Diagonal(int i, int j, int n, int[] verts, int[] indices)
|
public static bool Diagonal(int i, int j, int n, int[] verts, int[] indices)
|
||||||
{
|
{
|
||||||
return InCone(i, j, n, verts, indices) && Diagonalie(i, j, n, verts, indices);
|
return InCone(i, j, n, verts, indices) && Diagonalie(i, j, n, verts, indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int Triangulate(int n, int[] verts, int[] indices, int[] tris)
|
public static int Triangulate(int n, int[] verts, int[] indices, int[] tris)
|
||||||
{
|
{
|
||||||
int ntris = 0;
|
int ntris = 0;
|
||||||
int dst = 0; // tris;
|
int dst = 0; // tris;
|
||||||
|
@ -1174,7 +1177,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return ntris;
|
return ntris;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int CountPolyVerts(int[] polys, int p, int maxVertsPerPoly)
|
public static int CountPolyVerts(int[] polys, int p, int maxVertsPerPoly)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < maxVertsPerPoly; ++i)
|
for (int i = 0; i < maxVertsPerPoly; ++i)
|
||||||
if (polys[p + i] == DT_TILECACHE_NULL_IDX)
|
if (polys[p + i] == DT_TILECACHE_NULL_IDX)
|
||||||
|
@ -1182,13 +1185,13 @@ namespace DotRecast.Detour.TileCache
|
||||||
return maxVertsPerPoly;
|
return maxVertsPerPoly;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Uleft(int[] verts, int a, int b, int c)
|
public static bool Uleft(int[] verts, int a, int b, int c)
|
||||||
{
|
{
|
||||||
return (verts[b] - verts[a]) * (verts[c + 2] - verts[a + 2])
|
return (verts[b] - verts[a]) * (verts[c + 2] - verts[a + 2])
|
||||||
- (verts[c] - verts[a]) * (verts[b + 2] - verts[a + 2]) < 0;
|
- (verts[c] - verts[a]) * (verts[b + 2] - verts[a + 2]) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetPolyMergeValue(int[] polys, int pa, int pb, int[] verts, out int ea, out int eb, int maxVertsPerPoly)
|
public static int GetPolyMergeValue(int[] polys, int pa, int pb, int[] verts, out int ea, out int eb, int maxVertsPerPoly)
|
||||||
{
|
{
|
||||||
ea = 0;
|
ea = 0;
|
||||||
eb = 0;
|
eb = 0;
|
||||||
|
@ -1259,7 +1262,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return (dx * dx) + (dy * dy);
|
return (dx * dx) + (dy * dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MergePolys(int[] polys, int pa, int pb, int ea, int eb, int maxVertsPerPoly)
|
public static void MergePolys(int[] polys, int pa, int pb, int ea, int eb, int maxVertsPerPoly)
|
||||||
{
|
{
|
||||||
int[] tmp = new int[maxVertsPerPoly * 2];
|
int[] tmp = new int[maxVertsPerPoly * 2];
|
||||||
|
|
||||||
|
@ -1278,19 +1281,19 @@ namespace DotRecast.Detour.TileCache
|
||||||
RcArrays.Copy(tmp, 0, polys, pa, maxVertsPerPoly);
|
RcArrays.Copy(tmp, 0, polys, pa, maxVertsPerPoly);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int PushFront(int v, List<int> arr)
|
public static int PushFront(int v, List<int> arr)
|
||||||
{
|
{
|
||||||
arr.Insert(0, v);
|
arr.Insert(0, v);
|
||||||
return arr.Count;
|
return arr.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int PushBack(int v, List<int> arr)
|
public static int PushBack(int v, List<int> arr)
|
||||||
{
|
{
|
||||||
arr.Add(v);
|
arr.Add(v);
|
||||||
return arr.Count;
|
return arr.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanRemoveVertex(DtTileCachePolyMesh mesh, int rem)
|
public static bool CanRemoveVertex(DtTileCachePolyMesh mesh, int rem)
|
||||||
{
|
{
|
||||||
// Count number of polygons to remove.
|
// Count number of polygons to remove.
|
||||||
int maxVertsPerPoly = mesh.nvp;
|
int maxVertsPerPoly = mesh.nvp;
|
||||||
|
@ -1388,7 +1391,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveVertex(DtTileCachePolyMesh mesh, int rem, int maxTris)
|
public static void RemoveVertex(DtTileCachePolyMesh mesh, int rem, int maxTris)
|
||||||
{
|
{
|
||||||
// Count number of polygons to remove.
|
// Count number of polygons to remove.
|
||||||
int maxVertsPerPoly = mesh.nvp;
|
int maxVertsPerPoly = mesh.nvp;
|
||||||
|
@ -1627,7 +1630,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtTileCachePolyMesh BuildTileCachePolyMesh(DtTileCacheContourSet lcset, int maxVertsPerPoly)
|
public static DtTileCachePolyMesh BuildTileCachePolyMesh(DtTileCacheContourSet lcset, int maxVertsPerPoly)
|
||||||
{
|
{
|
||||||
int maxVertices = 0;
|
int maxVertices = 0;
|
||||||
int maxTris = 0;
|
int maxTris = 0;
|
||||||
|
@ -1801,7 +1804,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MarkCylinderArea(DtTileCacheLayer layer, RcVec3f orig, float cs, float ch, RcVec3f pos, float radius, float height, int areaId)
|
public static void MarkCylinderArea(DtTileCacheLayer layer, RcVec3f orig, float cs, float ch, RcVec3f pos, float radius, float height, byte areaId)
|
||||||
{
|
{
|
||||||
RcVec3f bmin = new RcVec3f();
|
RcVec3f bmin = new RcVec3f();
|
||||||
RcVec3f bmax = new RcVec3f();
|
RcVec3f bmax = new RcVec3f();
|
||||||
|
@ -1857,12 +1860,12 @@ namespace DotRecast.Detour.TileCache
|
||||||
int y = layer.heights[x + z * w];
|
int y = layer.heights[x + z * w];
|
||||||
if (y < miny || y > maxy)
|
if (y < miny || y > maxy)
|
||||||
continue;
|
continue;
|
||||||
layer.areas[x + z * w] = (short)areaId;
|
layer.areas[x + z * w] = areaId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MarkBoxArea(DtTileCacheLayer layer, RcVec3f orig, float cs, float ch, RcVec3f bmin, RcVec3f bmax, int areaId)
|
public static void MarkBoxArea(DtTileCacheLayer layer, RcVec3f orig, float cs, float ch, RcVec3f bmin, RcVec3f bmax, byte areaId)
|
||||||
{
|
{
|
||||||
int w = layer.header.width;
|
int w = layer.header.width;
|
||||||
int h = layer.header.height;
|
int h = layer.header.height;
|
||||||
|
@ -1901,12 +1904,12 @@ namespace DotRecast.Detour.TileCache
|
||||||
int y = layer.heights[x + z * w];
|
int y = layer.heights[x + z * w];
|
||||||
if (y < miny || y > maxy)
|
if (y < miny || y > maxy)
|
||||||
continue;
|
continue;
|
||||||
layer.areas[x + z * w] = (short)areaId;
|
layer.areas[x + z * w] = areaId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] CompressTileCacheLayer(IRcCompressor comp, DtTileCacheLayer layer, RcByteOrder order, bool cCompatibility)
|
public static byte[] CompressTileCacheLayer(IRcCompressor comp, DtTileCacheLayer layer, RcByteOrder order, bool cCompatibility)
|
||||||
{
|
{
|
||||||
using var ms = new MemoryStream();
|
using var ms = new MemoryStream();
|
||||||
using var bw = new BinaryWriter(ms);
|
using var bw = new BinaryWriter(ms);
|
||||||
|
@ -1933,7 +1936,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] CompressTileCacheLayer(DtTileCacheLayerHeader header, int[] heights, int[] areas, int[] cons, RcByteOrder order, bool cCompatibility, IRcCompressor comp)
|
public static byte[] CompressTileCacheLayer(DtTileCacheLayerHeader header, int[] heights, int[] areas, int[] cons, RcByteOrder order, bool cCompatibility, IRcCompressor comp)
|
||||||
{
|
{
|
||||||
using var ms = new MemoryStream();
|
using var ms = new MemoryStream();
|
||||||
using var bw = new BinaryWriter(ms);
|
using var bw = new BinaryWriter(ms);
|
||||||
|
@ -1960,14 +1963,14 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtTileCacheLayer DecompressTileCacheLayer(IRcCompressor comp, byte[] compressed, RcByteOrder order, bool cCompatibility)
|
public static DtTileCacheLayer DecompressTileCacheLayer(IRcCompressor comp, byte[] compressed, RcByteOrder order, bool cCompatibility)
|
||||||
{
|
{
|
||||||
RcByteBuffer buf = new RcByteBuffer(compressed);
|
RcByteBuffer buf = new RcByteBuffer(compressed);
|
||||||
buf.Order(order);
|
buf.Order(order);
|
||||||
DtTileCacheLayer layer = new DtTileCacheLayer();
|
DtTileCacheLayer layer = new DtTileCacheLayer();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
layer.header = reader.Read(buf, cCompatibility);
|
layer.header = DtTileCacheLayerHeaderReader.Read(buf, cCompatibility);
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
|
@ -1976,22 +1979,22 @@ namespace DotRecast.Detour.TileCache
|
||||||
|
|
||||||
int gridSize = layer.header.width * layer.header.height;
|
int gridSize = layer.header.width * layer.header.height;
|
||||||
byte[] grids = comp.Decompress(compressed, buf.Position(), compressed.Length - buf.Position(), gridSize * 3);
|
byte[] grids = comp.Decompress(compressed, buf.Position(), compressed.Length - buf.Position(), gridSize * 3);
|
||||||
layer.heights = new short[gridSize];
|
layer.heights = new byte[gridSize];
|
||||||
layer.areas = new short[gridSize];
|
layer.areas = new byte[gridSize];
|
||||||
layer.cons = new short[gridSize];
|
layer.cons = new byte[gridSize];
|
||||||
layer.regs = new short[gridSize];
|
layer.regs = new byte[gridSize];
|
||||||
for (int i = 0; i < gridSize; i++)
|
for (int i = 0; i < gridSize; i++)
|
||||||
{
|
{
|
||||||
layer.heights[i] = (short)(grids[i] & 0xFF);
|
layer.heights[i] = (byte)(grids[i] & 0xFF);
|
||||||
layer.areas[i] = (short)(grids[i + gridSize] & 0xFF);
|
layer.areas[i] = (byte)(grids[i + gridSize] & 0xFF);
|
||||||
layer.cons[i] = (short)(grids[i + gridSize * 2] & 0xFF);
|
layer.cons[i] = (byte)(grids[i + gridSize * 2] & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MarkBoxArea(DtTileCacheLayer layer, RcVec3f orig, float cs, float ch, RcVec3f center, RcVec3f extents,
|
public static void MarkBoxArea(DtTileCacheLayer layer, RcVec3f orig, float cs, float ch, RcVec3f center, RcVec3f extents,
|
||||||
float[] rotAux, int areaId)
|
float[] rotAux, byte areaId)
|
||||||
{
|
{
|
||||||
int w = layer.header.width;
|
int w = layer.header.width;
|
||||||
int h = layer.header.height;
|
int h = layer.header.height;
|
||||||
|
@ -2044,7 +2047,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
int y = layer.heights[x + z * w];
|
int y = layer.heights[x + z * w];
|
||||||
if (y < miny || y > maxy)
|
if (y < miny || y > maxy)
|
||||||
continue;
|
continue;
|
||||||
layer.areas[x + z * w] = (short)areaId;
|
layer.areas[x + z * w] = areaId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -24,7 +24,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
{
|
{
|
||||||
public int nverts;
|
public int nverts;
|
||||||
public int[] verts;
|
public int[] verts;
|
||||||
public int reg;
|
public byte reg;
|
||||||
public int area;
|
public byte area;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -23,13 +23,10 @@ namespace DotRecast.Detour.TileCache
|
||||||
public class DtTileCacheLayer
|
public class DtTileCacheLayer
|
||||||
{
|
{
|
||||||
public DtTileCacheLayerHeader header;
|
public DtTileCacheLayerHeader header;
|
||||||
public int regCount;
|
public byte regCount; // < Region count.
|
||||||
|
public byte[] heights; // unsigned char
|
||||||
/// < Region count.
|
public byte[] areas; // unsigned char
|
||||||
public short[] heights; // char
|
public byte[] cons; // unsigned char
|
||||||
|
public byte[] regs; // unsigned char
|
||||||
public short[] areas; // char
|
|
||||||
public short[] cons; // char
|
|
||||||
public short[] regs; // char
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache
|
namespace DotRecast.Detour.TileCache
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -100,7 +100,6 @@ namespace DotRecast.Detour.TileCache
|
||||||
List<byte[]> result = new List<byte[]>();
|
List<byte[]> result = new List<byte[]>();
|
||||||
if (lset != null)
|
if (lset != null)
|
||||||
{
|
{
|
||||||
DtTileCacheBuilder builder = new DtTileCacheBuilder();
|
|
||||||
for (int i = 0; i < lset.layers.Length; ++i)
|
for (int i = 0; i < lset.layers.Length; ++i)
|
||||||
{
|
{
|
||||||
RcHeightfieldLayer layer = lset.layers[i];
|
RcHeightfieldLayer layer = lset.layers[i];
|
||||||
|
@ -128,7 +127,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
header.hmax = layer.hmax;
|
header.hmax = layer.hmax;
|
||||||
|
|
||||||
var comp = _compFactory.Create(storageParams.Compatibility ? 0 : 1);
|
var comp = _compFactory.Create(storageParams.Compatibility ? 0 : 1);
|
||||||
var bytes = builder.CompressTileCacheLayer(header, layer.heights, layer.areas, layer.cons, storageParams.Order, storageParams.Compatibility, comp);
|
var bytes = DtTileCacheBuilder.CompressTileCacheLayer(header, layer.heights, layer.areas, layer.cons, storageParams.Order, storageParams.Compatibility, comp);
|
||||||
result.Add(bytes);
|
result.Add(bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -19,32 +19,28 @@ freely, subject to the following restrictions:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core.Numerics;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache
|
namespace DotRecast.Detour.TileCache
|
||||||
{
|
{
|
||||||
public class DtTileCacheObstacle
|
public class DtTileCacheObstacle
|
||||||
{
|
{
|
||||||
public readonly int index;
|
public readonly int index;
|
||||||
public DtTileCacheObstacleType type;
|
|
||||||
public RcVec3f pos = new RcVec3f();
|
public DtObstacleCylinder cylinder = new DtObstacleCylinder();
|
||||||
public RcVec3f bmin = new RcVec3f();
|
public DtObstacleBox box = new DtObstacleBox();
|
||||||
public RcVec3f bmax = new RcVec3f();
|
public DtObstacleOrientedBox orientedBox = new DtObstacleOrientedBox();
|
||||||
public float radius, height;
|
|
||||||
public RcVec3f center = new RcVec3f();
|
|
||||||
public RcVec3f extents = new RcVec3f();
|
|
||||||
public readonly float[] rotAux = new float[2]; // { Cos(0.5f*angle)*Sin(-0.5f*angle); Cos(0.5f*angle)*Cos(0.5f*angle) - 0.5 }
|
|
||||||
|
|
||||||
public List<long> touched = new List<long>();
|
public List<long> touched = new List<long>();
|
||||||
public readonly List<long> pending = new List<long>();
|
public readonly List<long> pending = new List<long>();
|
||||||
public int salt;
|
public int salt;
|
||||||
|
public DtTileCacheObstacleType type;
|
||||||
public DtObstacleState state = DtObstacleState.DT_OBSTACLE_EMPTY;
|
public DtObstacleState state = DtObstacleState.DT_OBSTACLE_EMPTY;
|
||||||
public DtTileCacheObstacle next;
|
public DtTileCacheObstacle next;
|
||||||
|
|
||||||
public DtTileCacheObstacle(int index)
|
public DtTileCacheObstacle(int index)
|
||||||
{
|
{
|
||||||
salt = 1;
|
|
||||||
this.index = index;
|
this.index = index;
|
||||||
|
salt = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
namespace DotRecast.Detour.TileCache
|
namespace DotRecast.Detour.TileCache
|
||||||
{
|
{
|
||||||
public enum DtTileCacheObstacleType
|
public enum DtTileCacheObstacleType
|
||||||
{
|
{
|
||||||
CYLINDER,
|
DT_OBSTACLE_CYLINDER,
|
||||||
BOX,
|
DT_OBSTACLE_BOX, // AABB
|
||||||
ORIENTED_BOX
|
DT_OBSTACLE_ORIENTED_BOX // OBB
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -23,24 +23,13 @@ namespace DotRecast.Detour.TileCache
|
||||||
public class DtTileCachePolyMesh
|
public class DtTileCachePolyMesh
|
||||||
{
|
{
|
||||||
public int nvp;
|
public int nvp;
|
||||||
public int nverts;
|
public int nverts; // < Number of vertices.
|
||||||
|
public int npolys; // < Number of polygons.
|
||||||
|
public int[] verts; // < Vertices of the mesh, 3 elements per vertex.
|
||||||
|
public int[] polys; // < Polygons of the mesh, nvp*2 elements per polygon.
|
||||||
|
public int[] flags; // < Per polygon flags.
|
||||||
|
public int[] areas; // < Area ID of polygons.
|
||||||
|
|
||||||
/// < Number of vertices.
|
|
||||||
public int npolys;
|
|
||||||
|
|
||||||
/// < Number of polygons.
|
|
||||||
public int[] verts;
|
|
||||||
|
|
||||||
/// < Vertices of the mesh, 3 elements per vertex.
|
|
||||||
public int[] polys;
|
|
||||||
|
|
||||||
/// < Polygons of the mesh, nvp*2 elements per polygon.
|
|
||||||
public int[] flags;
|
|
||||||
|
|
||||||
/// < Per polygon flags.
|
|
||||||
public int[] areas;
|
|
||||||
|
|
||||||
/// < Area ID of polygons.
|
|
||||||
public DtTileCachePolyMesh(int nvp)
|
public DtTileCachePolyMesh(int nvp)
|
||||||
{
|
{
|
||||||
this.nvp = nvp;
|
this.nvp = nvp;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache.Io.Compress
|
namespace DotRecast.Detour.TileCache.Io.Compress
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -23,9 +23,9 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache.Io
|
namespace DotRecast.Detour.TileCache.Io
|
||||||
{
|
{
|
||||||
public class DtTileCacheLayerHeaderReader
|
public static class DtTileCacheLayerHeaderReader
|
||||||
{
|
{
|
||||||
public DtTileCacheLayerHeader Read(RcByteBuffer data, bool cCompatibility)
|
public static DtTileCacheLayerHeader Read(RcByteBuffer data, bool cCompatibility)
|
||||||
{
|
{
|
||||||
DtTileCacheLayerHeader header = new DtTileCacheLayerHeader();
|
DtTileCacheLayerHeader header = new DtTileCacheLayerHeader();
|
||||||
header.magic = data.GetInt();
|
header.magic = data.GetInt();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -24,34 +24,34 @@ using DotRecast.Detour.Io;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache.Io
|
namespace DotRecast.Detour.TileCache.Io
|
||||||
{
|
{
|
||||||
public class DtTileCacheLayerHeaderWriter : DtWriter
|
public class DtTileCacheLayerHeaderWriter
|
||||||
{
|
{
|
||||||
public void Write(BinaryWriter stream, DtTileCacheLayerHeader header, RcByteOrder order, bool cCompatibility)
|
public void Write(BinaryWriter stream, DtTileCacheLayerHeader header, RcByteOrder order, bool cCompatibility)
|
||||||
{
|
{
|
||||||
Write(stream, header.magic, order);
|
RcIO.Write(stream, header.magic, order);
|
||||||
Write(stream, header.version, order);
|
RcIO.Write(stream, header.version, order);
|
||||||
Write(stream, header.tx, order);
|
RcIO.Write(stream, header.tx, order);
|
||||||
Write(stream, header.ty, order);
|
RcIO.Write(stream, header.ty, order);
|
||||||
Write(stream, header.tlayer, order);
|
RcIO.Write(stream, header.tlayer, order);
|
||||||
|
|
||||||
Write(stream, header.bmin.X, order);
|
RcIO.Write(stream, header.bmin.X, order);
|
||||||
Write(stream, header.bmin.Y, order);
|
RcIO.Write(stream, header.bmin.Y, order);
|
||||||
Write(stream, header.bmin.Z, order);
|
RcIO.Write(stream, header.bmin.Z, order);
|
||||||
Write(stream, header.bmax.X, order);
|
RcIO.Write(stream, header.bmax.X, order);
|
||||||
Write(stream, header.bmax.Y, order);
|
RcIO.Write(stream, header.bmax.Y, order);
|
||||||
Write(stream, header.bmax.Z, order);
|
RcIO.Write(stream, header.bmax.Z, order);
|
||||||
|
|
||||||
Write(stream, (short)header.hmin, order);
|
RcIO.Write(stream, (short)header.hmin, order);
|
||||||
Write(stream, (short)header.hmax, order);
|
RcIO.Write(stream, (short)header.hmax, order);
|
||||||
Write(stream, (byte)header.width);
|
RcIO.Write(stream, (byte)header.width);
|
||||||
Write(stream, (byte)header.height);
|
RcIO.Write(stream, (byte)header.height);
|
||||||
Write(stream, (byte)header.minx);
|
RcIO.Write(stream, (byte)header.minx);
|
||||||
Write(stream, (byte)header.maxx);
|
RcIO.Write(stream, (byte)header.maxx);
|
||||||
Write(stream, (byte)header.miny);
|
RcIO.Write(stream, (byte)header.miny);
|
||||||
Write(stream, (byte)header.maxy);
|
RcIO.Write(stream, (byte)header.maxy);
|
||||||
if (cCompatibility)
|
if (cCompatibility)
|
||||||
{
|
{
|
||||||
Write(stream, (short)0, order); // C struct padding
|
RcIO.Write(stream, (short)0, order); // C struct padding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -37,7 +37,7 @@ namespace DotRecast.Detour.TileCache.Io
|
||||||
|
|
||||||
public DtTileCache Read(BinaryReader @is, int maxVertPerPoly, IDtTileCacheMeshProcess meshProcessor)
|
public DtTileCache Read(BinaryReader @is, int maxVertPerPoly, IDtTileCacheMeshProcess meshProcessor)
|
||||||
{
|
{
|
||||||
RcByteBuffer bb = IOUtils.ToByteBuffer(@is);
|
RcByteBuffer bb = RcIO.ToByteBuffer(@is);
|
||||||
return Read(bb, maxVertPerPoly, meshProcessor);
|
return Read(bb, maxVertPerPoly, meshProcessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ namespace DotRecast.Detour.TileCache.Io
|
||||||
header.magic = bb.GetInt();
|
header.magic = bb.GetInt();
|
||||||
if (header.magic != DtTileCacheSetHeader.TILECACHESET_MAGIC)
|
if (header.magic != DtTileCacheSetHeader.TILECACHESET_MAGIC)
|
||||||
{
|
{
|
||||||
header.magic = IOUtils.SwapEndianness(header.magic);
|
header.magic = RcIO.SwapEndianness(header.magic);
|
||||||
if (header.magic != DtTileCacheSetHeader.TILECACHESET_MAGIC)
|
if (header.magic != DtTileCacheSetHeader.TILECACHESET_MAGIC)
|
||||||
{
|
{
|
||||||
throw new IOException("Invalid magic");
|
throw new IOException("Invalid magic");
|
||||||
|
@ -69,7 +69,8 @@ namespace DotRecast.Detour.TileCache.Io
|
||||||
header.numTiles = bb.GetInt();
|
header.numTiles = bb.GetInt();
|
||||||
header.meshParams = paramReader.Read(bb);
|
header.meshParams = paramReader.Read(bb);
|
||||||
header.cacheParams = ReadCacheParams(bb, cCompatibility);
|
header.cacheParams = ReadCacheParams(bb, cCompatibility);
|
||||||
DtNavMesh mesh = new DtNavMesh(header.meshParams, maxVertPerPoly);
|
DtNavMesh mesh = new DtNavMesh();
|
||||||
|
mesh.Init(header.meshParams, maxVertPerPoly);
|
||||||
IRcCompressor comp = _compFactory.Create(cCompatibility ? 0 : 1);
|
IRcCompressor comp = _compFactory.Create(cCompatibility ? 0 : 1);
|
||||||
DtTileCacheStorageParams storageParams = new DtTileCacheStorageParams(bb.Order(), cCompatibility);
|
DtTileCacheStorageParams storageParams = new DtTileCacheStorageParams(bb.Order(), cCompatibility);
|
||||||
DtTileCache tc = new DtTileCache(header.cacheParams, storageParams, mesh, comp, meshProcessor);
|
DtTileCache tc = new DtTileCache(header.cacheParams, storageParams, mesh, comp, meshProcessor);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -25,10 +25,9 @@ using DotRecast.Detour.TileCache.Io.Compress;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache.Io
|
namespace DotRecast.Detour.TileCache.Io
|
||||||
{
|
{
|
||||||
public class DtTileCacheWriter : DtWriter
|
public class DtTileCacheWriter
|
||||||
{
|
{
|
||||||
private readonly DtNavMeshParamWriter paramWriter = new DtNavMeshParamWriter();
|
private readonly DtNavMeshParamWriter paramWriter = new DtNavMeshParamWriter();
|
||||||
private readonly DtTileCacheBuilder builder = new DtTileCacheBuilder();
|
|
||||||
private readonly IDtTileCacheCompressorFactory _compFactory;
|
private readonly IDtTileCacheCompressorFactory _compFactory;
|
||||||
|
|
||||||
public DtTileCacheWriter(IDtTileCacheCompressorFactory compFactory)
|
public DtTileCacheWriter(IDtTileCacheCompressorFactory compFactory)
|
||||||
|
@ -39,8 +38,8 @@ namespace DotRecast.Detour.TileCache.Io
|
||||||
|
|
||||||
public void Write(BinaryWriter stream, DtTileCache cache, RcByteOrder order, bool cCompatibility)
|
public void Write(BinaryWriter stream, DtTileCache cache, RcByteOrder order, bool cCompatibility)
|
||||||
{
|
{
|
||||||
Write(stream, DtTileCacheSetHeader.TILECACHESET_MAGIC, order);
|
RcIO.Write(stream, DtTileCacheSetHeader.TILECACHESET_MAGIC, order);
|
||||||
Write(stream, cCompatibility
|
RcIO.Write(stream, cCompatibility
|
||||||
? DtTileCacheSetHeader.TILECACHESET_VERSION
|
? DtTileCacheSetHeader.TILECACHESET_VERSION
|
||||||
: DtTileCacheSetHeader.TILECACHESET_VERSION_RECAST4J, order);
|
: DtTileCacheSetHeader.TILECACHESET_VERSION_RECAST4J, order);
|
||||||
int numTiles = 0;
|
int numTiles = 0;
|
||||||
|
@ -52,7 +51,7 @@ namespace DotRecast.Detour.TileCache.Io
|
||||||
numTiles++;
|
numTiles++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Write(stream, numTiles, order);
|
RcIO.Write(stream, numTiles, order);
|
||||||
paramWriter.Write(stream, cache.GetNavMesh().GetParams(), order);
|
paramWriter.Write(stream, cache.GetNavMesh().GetParams(), order);
|
||||||
WriteCacheParams(stream, cache.GetParams(), order);
|
WriteCacheParams(stream, cache.GetParams(), order);
|
||||||
for (int i = 0; i < cache.GetTileCount(); i++)
|
for (int i = 0; i < cache.GetTileCount(); i++)
|
||||||
|
@ -60,32 +59,32 @@ namespace DotRecast.Detour.TileCache.Io
|
||||||
DtCompressedTile tile = cache.GetTile(i);
|
DtCompressedTile tile = cache.GetTile(i);
|
||||||
if (tile == null || tile.data == null)
|
if (tile == null || tile.data == null)
|
||||||
continue;
|
continue;
|
||||||
Write(stream, (int)cache.GetTileRef(tile), order);
|
RcIO.Write(stream, (int)cache.GetTileRef(tile), order);
|
||||||
byte[] data = tile.data;
|
byte[] data = tile.data;
|
||||||
DtTileCacheLayer layer = cache.DecompressTile(tile);
|
DtTileCacheLayer layer = cache.DecompressTile(tile);
|
||||||
var comp = _compFactory.Create(cCompatibility ? 0 : 1);
|
var comp = _compFactory.Create(cCompatibility ? 0 : 1);
|
||||||
data = builder.CompressTileCacheLayer(comp, layer, order, cCompatibility);
|
data = DtTileCacheBuilder.CompressTileCacheLayer(comp, layer, order, cCompatibility);
|
||||||
Write(stream, data.Length, order);
|
RcIO.Write(stream, data.Length, order);
|
||||||
stream.Write(data);
|
stream.Write(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteCacheParams(BinaryWriter stream, DtTileCacheParams option, RcByteOrder order)
|
private void WriteCacheParams(BinaryWriter stream, DtTileCacheParams option, RcByteOrder order)
|
||||||
{
|
{
|
||||||
Write(stream, option.orig.X, order);
|
RcIO.Write(stream, option.orig.X, order);
|
||||||
Write(stream, option.orig.Y, order);
|
RcIO.Write(stream, option.orig.Y, order);
|
||||||
Write(stream, option.orig.Z, order);
|
RcIO.Write(stream, option.orig.Z, order);
|
||||||
|
|
||||||
Write(stream, option.cs, order);
|
RcIO.Write(stream, option.cs, order);
|
||||||
Write(stream, option.ch, order);
|
RcIO.Write(stream, option.ch, order);
|
||||||
Write(stream, option.width, order);
|
RcIO.Write(stream, option.width, order);
|
||||||
Write(stream, option.height, order);
|
RcIO.Write(stream, option.height, order);
|
||||||
Write(stream, option.walkableHeight, order);
|
RcIO.Write(stream, option.walkableHeight, order);
|
||||||
Write(stream, option.walkableRadius, order);
|
RcIO.Write(stream, option.walkableRadius, order);
|
||||||
Write(stream, option.walkableClimb, order);
|
RcIO.Write(stream, option.walkableClimb, order);
|
||||||
Write(stream, option.maxSimplificationError, order);
|
RcIO.Write(stream, option.maxSimplificationError, order);
|
||||||
Write(stream, option.maxTiles, order);
|
RcIO.Write(stream, option.maxTiles, order);
|
||||||
Write(stream, option.maxObstacles, order);
|
RcIO.Write(stream, option.maxObstacles, order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
namespace DotRecast.Detour
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
public class BVItem
|
public class BVItem
|
||||||
{
|
{
|
||||||
public readonly int[] bmin = new int[3];
|
public RcVec3i bmin;
|
||||||
public readonly int[] bmax = new int[3];
|
public RcVec3i bmax;
|
||||||
public int i;
|
public int i;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
public int Compare(BVItem a, BVItem b)
|
public int Compare(BVItem a, BVItem b)
|
||||||
{
|
{
|
||||||
return a.bmin[0].CompareTo(b.bmin[0]);
|
return a.bmin.X.CompareTo(b.bmin.X);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
public int Compare(BVItem a, BVItem b)
|
public int Compare(BVItem a, BVItem b)
|
||||||
{
|
{
|
||||||
return a.bmin[1].CompareTo(b.bmin[1]);
|
return a.bmin.Y.CompareTo(b.bmin.Y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
public int Compare(BVItem a, BVItem b)
|
public int Compare(BVItem a, BVItem b)
|
||||||
{
|
{
|
||||||
return a.bmin[2].CompareTo(b.bmin[2]);
|
return a.bmin.Z.CompareTo(b.bmin.Z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -18,26 +18,17 @@ freely, subject to the following restrictions:
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/**
|
/// Bounding volume node.
|
||||||
* Bounding volume node.
|
/// @note This structure is rarely if ever used by the end user.
|
||||||
*
|
/// @see dtMeshTile
|
||||||
* @note This structure is rarely if ever used by the end user.
|
|
||||||
* @see MeshTile
|
|
||||||
*/
|
|
||||||
[Serializable]
|
|
||||||
public class DtBVNode
|
public class DtBVNode
|
||||||
{
|
{
|
||||||
/** Minimum bounds of the node's AABB. [(x, y, z)] */
|
public RcVec3i bmin; //< Minimum bounds of the node's AABB. [(x, y, z)]
|
||||||
public int[] bmin = new int[3];
|
public RcVec3i bmax; //< Maximum bounds of the node's AABB. [(x, y, z)]
|
||||||
|
public int i; //< The node's index. (Negative for escape sequence.)
|
||||||
/** Maximum bounds of the node's AABB. [(x, y, z)] */
|
|
||||||
public int[] bmax = new int[3];
|
|
||||||
|
|
||||||
/** The node's index. (Negative for escape sequence.) */
|
|
||||||
public int i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace DotRecast.Detour
|
||||||
|
{
|
||||||
|
public class DtCallbackPolyQuery : IDtPolyQuery
|
||||||
|
{
|
||||||
|
private readonly Action<DtMeshTile, DtPoly, long> _callback;
|
||||||
|
|
||||||
|
public DtCallbackPolyQuery(Action<DtMeshTile, DtPoly, long> callback)
|
||||||
|
{
|
||||||
|
_callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Process(DtMeshTile tile, DtPoly[] poly, Span<long> refs, int count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
_callback?.Invoke(tile, poly[i], refs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
using System;
|
||||||
|
using DotRecast.Core;
|
||||||
|
|
||||||
|
namespace DotRecast.Detour
|
||||||
|
{
|
||||||
|
public class DtCollectPolysQuery : IDtPolyQuery
|
||||||
|
{
|
||||||
|
private long[] m_polys;
|
||||||
|
private int m_maxPolys;
|
||||||
|
private int m_numCollected;
|
||||||
|
private bool m_overflow;
|
||||||
|
|
||||||
|
public DtCollectPolysQuery(long[] polys, int maxPolys)
|
||||||
|
{
|
||||||
|
m_polys = polys;
|
||||||
|
m_maxPolys = maxPolys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int NumCollected()
|
||||||
|
{
|
||||||
|
return m_numCollected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Overflowed()
|
||||||
|
{
|
||||||
|
return m_overflow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Process(DtMeshTile tile, DtPoly[] poly, Span<long> refs, int count)
|
||||||
|
{
|
||||||
|
int numLeft = m_maxPolys - m_numCollected;
|
||||||
|
int toCopy = count;
|
||||||
|
if (toCopy > numLeft)
|
||||||
|
{
|
||||||
|
m_overflow = true;
|
||||||
|
toCopy = numLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
RcSpans.Copy<long>(refs, 0, m_polys, m_numCollected, toCopy);
|
||||||
|
m_numCollected += toCopy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
public enum DtConvexConvexInFlag
|
public enum DtConvexConvexInFlag
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
public enum DtConvexConvexIntersection
|
public enum DtConvexConvexIntersection
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -18,23 +18,20 @@ freely, subject to the following restrictions:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using DotRecast.Core;
|
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/**
|
// Convex-convex intersection based on "Computational Geometry in C" by Joseph O'Rourke
|
||||||
* Convex-convex intersection based on "Computational Geometry in C" by Joseph O'Rourke
|
|
||||||
*/
|
|
||||||
public static class DtConvexConvexIntersections
|
public static class DtConvexConvexIntersections
|
||||||
{
|
{
|
||||||
private static readonly float EPSILON = 0.0001f;
|
private const float EPSILON = 0.0001f;
|
||||||
|
|
||||||
public static float[] Intersect(float[] p, float[] q)
|
public static float[] Intersect(Span<float> p, Span<float> q)
|
||||||
{
|
{
|
||||||
int n = p.Length / 3;
|
int n = p.Length / 3;
|
||||||
int m = q.Length / 3;
|
int m = q.Length / 3;
|
||||||
float[] inters = new float[Math.Max(m, n) * 3 * 3];
|
Span<float> inters = stackalloc float[Math.Max(m, n) * 3 * 3];
|
||||||
int ii = 0;
|
int ii = 0;
|
||||||
/* Initialize variables. */
|
/* Initialize variables. */
|
||||||
RcVec3f a = new RcVec3f();
|
RcVec3f a = new RcVec3f();
|
||||||
|
@ -54,10 +51,10 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
a = RcVecUtils.Create(p, 3 * (ai % n));
|
a = RcVec.Create(p, 3 * (ai % n));
|
||||||
b = RcVecUtils.Create(q, 3 * (bi % m));
|
b = RcVec.Create(q, 3 * (bi % m));
|
||||||
a1 = RcVecUtils.Create(p, 3 * ((ai + n - 1) % n)); // prev a
|
a1 = RcVec.Create(p, 3 * ((ai + n - 1) % n)); // prev a
|
||||||
b1 = RcVecUtils.Create(q, 3 * ((bi + m - 1) % m)); // prev b
|
b1 = RcVec.Create(q, 3 * ((bi + m - 1) % m)); // prev b
|
||||||
|
|
||||||
RcVec3f A = RcVec3f.Subtract(a, a1);
|
RcVec3f A = RcVec3f.Subtract(a, a1);
|
||||||
RcVec3f B = RcVec3f.Subtract(b, b1);
|
RcVec3f B = RcVec3f.Subtract(b, b1);
|
||||||
|
@ -171,12 +168,11 @@ namespace DotRecast.Detour
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
float[] copied = new float[ii];
|
float[] copied = inters.Slice(0, ii).ToArray();
|
||||||
RcArrays.Copy(inters, copied, ii);
|
|
||||||
return copied;
|
return copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int AddVertex(float[] inters, int ii, RcVec3f p)
|
private static int AddVertex(Span<float> inters, int ii, RcVec3f p)
|
||||||
{
|
{
|
||||||
if (ii > 0)
|
if (ii > 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
public static class DtDetailTriEdgeFlags
|
public static class DtDetailTriEdgeFlags
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,184 @@
|
||||||
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
|
namespace DotRecast.Detour
|
||||||
|
{
|
||||||
|
public static class DtDetour
|
||||||
|
{
|
||||||
|
/// The maximum number of vertices per navigation polygon.
|
||||||
|
/// @ingroup detour
|
||||||
|
public const int DT_VERTS_PER_POLYGON = 6;
|
||||||
|
|
||||||
|
/** A magic number used to detect compatibility of navigation tile data. */
|
||||||
|
public const int DT_NAVMESH_MAGIC = 'D' << 24 | 'N' << 16 | 'A' << 8 | 'V';
|
||||||
|
|
||||||
|
/** A version number used to detect compatibility of navigation tile data. */
|
||||||
|
public const int DT_NAVMESH_VERSION = 7;
|
||||||
|
|
||||||
|
public const int DT_NAVMESH_VERSION_RECAST4J_FIRST = 0x8807;
|
||||||
|
public const int DT_NAVMESH_VERSION_RECAST4J_NO_POLY_FIRSTLINK = 0x8808;
|
||||||
|
public const int DT_NAVMESH_VERSION_RECAST4J_32BIT_BVTREE = 0x8809;
|
||||||
|
public const int DT_NAVMESH_VERSION_RECAST4J_LAST = 0x8809;
|
||||||
|
|
||||||
|
/** A magic number used to detect the compatibility of navigation tile states. */
|
||||||
|
public const int DT_NAVMESH_STATE_MAGIC = 'D' << 24 | 'N' << 16 | 'M' << 8 | 'S';
|
||||||
|
|
||||||
|
/** A version number used to detect compatibility of navigation tile states. */
|
||||||
|
public const int DT_NAVMESH_STATE_VERSION = 1;
|
||||||
|
|
||||||
|
public const int DT_SALT_BITS = 16;
|
||||||
|
public const int DT_TILE_BITS = 28;
|
||||||
|
public const int DT_POLY_BITS = 20;
|
||||||
|
|
||||||
|
/// A flag that indicates that an entity links to an external entity.
|
||||||
|
/// (E.g. A polygon edge is a portal that links to another polygon.)
|
||||||
|
public const int DT_EXT_LINK = 0x8000;
|
||||||
|
|
||||||
|
/// A value that indicates the entity does not link to anything.
|
||||||
|
public const int DT_NULL_LINK = unchecked((int)0xffffffff);
|
||||||
|
|
||||||
|
public const int DT_NODE_PARENT_BITS = 24;
|
||||||
|
public const int DT_NODE_STATE_BITS = 2;
|
||||||
|
public const int DT_MAX_STATES_PER_NODE = 1 << DT_NODE_STATE_BITS; // number of extra states per node. See dtNode::state
|
||||||
|
|
||||||
|
/// A flag that indicates that an off-mesh connection can be traversed in
|
||||||
|
/// both directions. (Is bidirectional.)
|
||||||
|
public const int DT_OFFMESH_CON_BIDIR = 1;
|
||||||
|
|
||||||
|
/// The maximum number of user defined area ids.
|
||||||
|
public const int DT_MAX_AREAS = 64;
|
||||||
|
|
||||||
|
/// Limit raycasting during any angle pahfinding
|
||||||
|
/// The limit is given as a multiple of the character radius
|
||||||
|
public const float DT_RAY_CAST_LIMIT_PROPORTIONS = 50.0f;
|
||||||
|
|
||||||
|
/// @{
|
||||||
|
/// @name Encoding and Decoding
|
||||||
|
/// These functions are generally meant for internal use only.
|
||||||
|
/// Derives a standard polygon reference.
|
||||||
|
/// @note This function is generally meant for internal use only.
|
||||||
|
/// @param[in] salt The tile's salt value.
|
||||||
|
/// @param[in] it The index of the tile.
|
||||||
|
/// @param[in] ip The index of the polygon within the tile.
|
||||||
|
public static long EncodePolyId(int salt, int it, int ip)
|
||||||
|
{
|
||||||
|
return (((long)salt) << (DT_POLY_BITS + DT_TILE_BITS)) | ((long)it << DT_POLY_BITS) | (long)ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decodes a standard polygon reference.
|
||||||
|
/// @note This function is generally meant for internal use only.
|
||||||
|
/// @param[in] ref The polygon reference to decode.
|
||||||
|
/// @param[out] salt The tile's salt value.
|
||||||
|
/// @param[out] it The index of the tile.
|
||||||
|
/// @param[out] ip The index of the polygon within the tile.
|
||||||
|
/// @see #encodePolyId
|
||||||
|
public static void DecodePolyId(long refs, out int salt, out int it, out int ip)
|
||||||
|
{
|
||||||
|
long saltMask = (1L << DT_SALT_BITS) - 1;
|
||||||
|
long tileMask = (1L << DT_TILE_BITS) - 1;
|
||||||
|
long polyMask = (1L << DT_POLY_BITS) - 1;
|
||||||
|
salt = (int)((refs >> (DT_POLY_BITS + DT_TILE_BITS)) & saltMask);
|
||||||
|
it = (int)((refs >> DT_POLY_BITS) & tileMask);
|
||||||
|
ip = (int)(refs & polyMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extracts a tile's salt value from the specified polygon reference.
|
||||||
|
/// @note This function is generally meant for internal use only.
|
||||||
|
/// @param[in] ref The polygon reference.
|
||||||
|
/// @see #encodePolyId
|
||||||
|
public static int DecodePolyIdSalt(long refs)
|
||||||
|
{
|
||||||
|
long saltMask = (1L << DT_SALT_BITS) - 1;
|
||||||
|
return (int)((refs >> (DT_POLY_BITS + DT_TILE_BITS)) & saltMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extracts the tile's index from the specified polygon reference.
|
||||||
|
/// @note This function is generally meant for internal use only.
|
||||||
|
/// @param[in] ref The polygon reference.
|
||||||
|
/// @see #encodePolyId
|
||||||
|
public static int DecodePolyIdTile(long refs)
|
||||||
|
{
|
||||||
|
long tileMask = (1L << DT_TILE_BITS) - 1;
|
||||||
|
return (int)((refs >> DT_POLY_BITS) & tileMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extracts the polygon's index (within its tile) from the specified
|
||||||
|
/// polygon reference.
|
||||||
|
/// @note This function is generally meant for internal use only.
|
||||||
|
/// @param[in] ref The polygon reference.
|
||||||
|
/// @see #encodePolyId
|
||||||
|
public static int DecodePolyIdPoly(long refs)
|
||||||
|
{
|
||||||
|
long polyMask = (1L << DT_POLY_BITS) - 1;
|
||||||
|
return (int)(refs & polyMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ComputeTileHash(int x, int y, int mask)
|
||||||
|
{
|
||||||
|
uint h1 = 0x8da6b343; // Large multiplicative constants;
|
||||||
|
uint h2 = 0xd8163841; // here arbitrarily chosen primes
|
||||||
|
uint n = h1 * (uint)x + h2 * (uint)y;
|
||||||
|
return (int)(n & mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float GetSlabCoord(float[] verts, int va, int side)
|
||||||
|
{
|
||||||
|
if (side == 0 || side == 4)
|
||||||
|
{
|
||||||
|
return verts[va];
|
||||||
|
}
|
||||||
|
else if (side == 2 || side == 6)
|
||||||
|
{
|
||||||
|
return verts[va + 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CalcSlabEndPoints(float[] verts, int va, int vb, ref RcVec2f bmin, ref RcVec2f bmax, int side)
|
||||||
|
{
|
||||||
|
if (side == 0 || side == 4)
|
||||||
|
{
|
||||||
|
if (verts[va + 2] < verts[vb + 2])
|
||||||
|
{
|
||||||
|
bmin.X = verts[va + 2];
|
||||||
|
bmin.Y = verts[va + 1];
|
||||||
|
bmax.X = verts[vb + 2];
|
||||||
|
bmax.Y = verts[vb + 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bmin.X = verts[vb + 2];
|
||||||
|
bmin.Y = verts[vb + 1];
|
||||||
|
bmax.X = verts[va + 2];
|
||||||
|
bmax.Y = verts[va + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (side == 2 || side == 6)
|
||||||
|
{
|
||||||
|
if (verts[va + 0] < verts[vb + 0])
|
||||||
|
{
|
||||||
|
bmin.X = verts[va + 0];
|
||||||
|
bmin.Y = verts[va + 1];
|
||||||
|
bmax.X = verts[vb + 0];
|
||||||
|
bmax.Y = verts[vb + 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bmin.X = verts[vb + 0];
|
||||||
|
bmin.Y = verts[vb + 1];
|
||||||
|
bmax.X = verts[va + 0];
|
||||||
|
bmax.Y = verts[va + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get flags for edge in detail triangle.
|
||||||
|
/// @param[in] triFlags The flags for the triangle (last component of detail vertices above).
|
||||||
|
/// @param[in] edgeIndex The index of the first vertex of the edge. For instance, if 0,
|
||||||
|
/// returns flags for edge AB.
|
||||||
|
public static int GetDetailTriEdgeFlags(int triFlags, int edgeIndex)
|
||||||
|
{
|
||||||
|
return (triFlags >> (edgeIndex * 2)) & 0x3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,44 +7,49 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
private readonly DtNavMeshQuery _query;
|
private readonly DtNavMeshQuery _query;
|
||||||
private readonly RcVec3f _center;
|
private readonly RcVec3f _center;
|
||||||
private long _nearestRef;
|
|
||||||
private RcVec3f _nearestPt;
|
|
||||||
private bool _overPoly;
|
|
||||||
private float _nearestDistanceSqr;
|
private float _nearestDistanceSqr;
|
||||||
|
private long _nearestRef;
|
||||||
|
private RcVec3f _nearestPoint;
|
||||||
|
private bool _overPoly;
|
||||||
|
|
||||||
public DtFindNearestPolyQuery(DtNavMeshQuery query, RcVec3f center)
|
public DtFindNearestPolyQuery(DtNavMeshQuery query, RcVec3f center)
|
||||||
{
|
{
|
||||||
this._query = query;
|
_query = query;
|
||||||
this._center = center;
|
_center = center;
|
||||||
_nearestDistanceSqr = float.MaxValue;
|
_nearestDistanceSqr = float.MaxValue;
|
||||||
_nearestPt = center;
|
_nearestPoint = center;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Process(DtMeshTile tile, DtPoly poly, long refs)
|
public void Process(DtMeshTile tile, DtPoly[] poly, Span<long> refs, int count)
|
||||||
{
|
{
|
||||||
// Find nearest polygon amongst the nearby polygons.
|
for (int i = 0; i < count; ++i)
|
||||||
_query.ClosestPointOnPoly(refs, _center, out var closestPtPoly, out var posOverPoly);
|
{
|
||||||
|
long polyRef = refs[i];
|
||||||
|
float d;
|
||||||
|
|
||||||
// If a point is directly over a polygon and closer than
|
// Find nearest polygon amongst the nearby polygons.
|
||||||
// climb height, favor that instead of straight line nearest point.
|
_query.ClosestPointOnPoly(polyRef, _center, out var closestPtPoly, out var posOverPoly);
|
||||||
float d = 0;
|
|
||||||
RcVec3f diff = RcVec3f.Subtract(_center, closestPtPoly);
|
|
||||||
if (posOverPoly)
|
|
||||||
{
|
|
||||||
d = MathF.Abs(diff.Y) - tile.data.header.walkableClimb;
|
|
||||||
d = d > 0 ? d * d : 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d = diff.LengthSquared();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d < _nearestDistanceSqr)
|
// If a point is directly over a polygon and closer than
|
||||||
{
|
// climb height, favor that instead of straight line nearest point.
|
||||||
_nearestPt = closestPtPoly;
|
RcVec3f diff = RcVec3f.Subtract(_center, closestPtPoly);
|
||||||
_nearestDistanceSqr = d;
|
if (posOverPoly)
|
||||||
_nearestRef = refs;
|
{
|
||||||
_overPoly = posOverPoly;
|
d = MathF.Abs(diff.Y) - tile.data.header.walkableClimb;
|
||||||
|
d = d > 0 ? d * d : 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d = diff.LengthSquared();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d < _nearestDistanceSqr)
|
||||||
|
{
|
||||||
|
_nearestPoint = closestPtPoly;
|
||||||
|
_nearestDistanceSqr = d;
|
||||||
|
_nearestRef = polyRef;
|
||||||
|
_overPoly = posOverPoly;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +60,7 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
public RcVec3f NearestPt()
|
public RcVec3f NearestPt()
|
||||||
{
|
{
|
||||||
return _nearestPt;
|
return _nearestPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool OverPoly()
|
public bool OverPoly()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
public readonly struct DtFindPathOption
|
public readonly struct DtFindPathOption
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/// Options for dtNavMeshQuery::initSlicedFindPath and updateSlicedFindPath
|
/// Options for dtNavMeshQuery::initSlicedFindPath and updateSlicedFindPath
|
||||||
public static class DtFindPathOptions
|
public static class DtFindPathOptions
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -18,32 +18,20 @@ freely, subject to the following restrictions:
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/**
|
/// Defines a link between polygons.
|
||||||
* Defines a link between polygons.
|
/// @note This structure is rarely if ever used by the end user.
|
||||||
*
|
/// @see dtMeshTile
|
||||||
* @note This structure is rarely if ever used by the end user.
|
|
||||||
* @see MeshTile
|
|
||||||
*/
|
|
||||||
public class DtLink
|
public class DtLink
|
||||||
{
|
{
|
||||||
/** Neighbour reference. (The neighbor that is linked to.) */
|
public long refs; //< Neighbour reference. (The neighbor that is linked to.)
|
||||||
public long refs;
|
public int next; //< Index of the next link.
|
||||||
|
public byte edge; //< Index of the polygon edge that owns this link.
|
||||||
/** Index of the next link. */
|
public byte side; //< If a boundary link, defines on which side the link is.
|
||||||
public int next;
|
public byte bmin; //< If a boundary link, defines the minimum sub-edge area.
|
||||||
|
public byte bmax; //< If a boundary link, defines the maximum sub-edge area.
|
||||||
/** Index of the polygon edge that owns this link. */
|
|
||||||
public int edge;
|
|
||||||
|
|
||||||
/** If a boundary link, defines on which side the link is. */
|
|
||||||
public int side;
|
|
||||||
|
|
||||||
/** If a boundary link, defines the minimum sub-edge area. */
|
|
||||||
public int bmin;
|
|
||||||
|
|
||||||
/** If a boundary link, defines the maximum sub-edge area. */
|
|
||||||
public int bmax;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -25,33 +25,22 @@ namespace DotRecast.Detour
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class DtMeshData
|
public class DtMeshData
|
||||||
{
|
{
|
||||||
/** The tile header. */
|
public DtMeshHeader header; //< The tile header.
|
||||||
public DtMeshHeader header;
|
public DtPoly[] polys; //< The tile polygons. [Size: dtMeshHeader::polyCount]
|
||||||
|
public float[] verts; //< The tile vertices. [(x, y, z) * dtMeshHeader::vertCount]
|
||||||
|
public DtPolyDetail[] detailMeshes; //< The tile's detail sub-meshes. [Size: dtMeshHeader::detailMeshCount]
|
||||||
|
|
||||||
/** The tile vertices. [Size: MeshHeader::vertCount] */
|
/// The detail mesh's unique vertices. [(x, y, z) * dtMeshHeader::detailVertCount]
|
||||||
public float[] verts;
|
|
||||||
|
|
||||||
/** The tile polygons. [Size: MeshHeader::polyCount] */
|
|
||||||
public DtPoly[] polys;
|
|
||||||
|
|
||||||
/** The tile's detail sub-meshes. [Size: MeshHeader::detailMeshCount] */
|
|
||||||
public DtPolyDetail[] detailMeshes;
|
|
||||||
|
|
||||||
/** The detail mesh's unique vertices. [(x, y, z) * MeshHeader::detailVertCount] */
|
|
||||||
public float[] detailVerts;
|
public float[] detailVerts;
|
||||||
|
|
||||||
/**
|
/// The detail mesh's triangles. [(vertA, vertB, vertC, triFlags) * dtMeshHeader::detailTriCount].
|
||||||
* The detail mesh's triangles. [(vertA, vertB, vertC) * MeshHeader::detailTriCount] See DetailTriEdgeFlags and
|
/// See dtDetailTriEdgeFlags and dtGetDetailTriEdgeFlags.
|
||||||
* NavMesh::getDetailTriEdgeFlags.
|
|
||||||
*/
|
|
||||||
public int[] detailTris;
|
public int[] detailTris;
|
||||||
|
|
||||||
/**
|
/// The tile bounding volume nodes. [Size: dtMeshHeader::bvNodeCount]
|
||||||
* The tile bounding volume nodes. [Size: MeshHeader::bvNodeCount] (Will be null if bounding volumes are disabled.)
|
/// (Will be null if bounding volumes are disabled.)
|
||||||
*/
|
|
||||||
public DtBVNode[] bvTree;
|
public DtBVNode[] bvTree;
|
||||||
|
|
||||||
/** The tile off-mesh connections. [Size: MeshHeader::offMeshConCount] */
|
public DtOffMeshConnection[] offMeshCons; //< The tile off-mesh connections. [Size: dtMeshHeader::offMeshConCount]
|
||||||
public DtOffMeshConnection[] offMeshCons;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -18,33 +18,22 @@ freely, subject to the following restrictions:
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/**
|
using static DtDetour;
|
||||||
* Defines a navigation mesh tile.
|
|
||||||
*/
|
/// Defines a navigation mesh tile.
|
||||||
|
/// @ingroup detour
|
||||||
public class DtMeshTile
|
public class DtMeshTile
|
||||||
{
|
{
|
||||||
public readonly int index;
|
public readonly int index; // DtNavMesh.m_tiles array index
|
||||||
|
public int linksFreeList = DT_NULL_LINK; //< Index to the next free link.
|
||||||
|
public int salt; //< Counter describing modifications to the tile.
|
||||||
|
public DtMeshData data; // The tile data.
|
||||||
|
public DtLink[] links; // The tile links. [Size: dtMeshHeader::maxLinkCount]
|
||||||
|
|
||||||
/** Counter describing modifications to the tile. */
|
public int flags; //< Tile flags. (See: #dtTileFlags)
|
||||||
public int salt;
|
public DtMeshTile next; //< The next free tile, or the next tile in the spatial grid.
|
||||||
|
|
||||||
/** The tile data. */
|
|
||||||
public DtMeshData data;
|
|
||||||
|
|
||||||
public int[] polyLinks;
|
|
||||||
|
|
||||||
/** The tile links. */
|
|
||||||
public readonly List<DtLink> links = new List<DtLink>();
|
|
||||||
|
|
||||||
/** Index to the next free link. */
|
|
||||||
public int linksFreeList = DtNavMesh.DT_NULL_LINK; // FIXME: Remove
|
|
||||||
|
|
||||||
/** Tile flags. (See: #dtTileFlags) */
|
|
||||||
public int flags;
|
|
||||||
|
|
||||||
public DtMeshTile(int index)
|
public DtMeshTile(int index)
|
||||||
{
|
{
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -24,42 +24,35 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
using static DtDetour;
|
||||||
|
|
||||||
public static class DtNavMeshBuilder
|
public static class DtNavMeshBuilder
|
||||||
{
|
{
|
||||||
const int MESH_NULL_IDX = 0xffff;
|
const int MESH_NULL_IDX = 0xffff;
|
||||||
|
|
||||||
|
|
||||||
private static int[][] CalcExtends(BVItem[] items, int nitems, int imin, int imax)
|
private static void CalcExtends(BVItem[] items, int nitems, int imin, int imax, ref RcVec3i bmin, ref RcVec3i bmax)
|
||||||
{
|
{
|
||||||
int[] bmin = new int[3];
|
bmin = items[imin].bmin;
|
||||||
int[] bmax = new int[3];
|
bmax = items[imin].bmax;
|
||||||
bmin[0] = items[imin].bmin[0];
|
|
||||||
bmin[1] = items[imin].bmin[1];
|
|
||||||
bmin[2] = items[imin].bmin[2];
|
|
||||||
|
|
||||||
bmax[0] = items[imin].bmax[0];
|
|
||||||
bmax[1] = items[imin].bmax[1];
|
|
||||||
bmax[2] = items[imin].bmax[2];
|
|
||||||
|
|
||||||
for (int i = imin + 1; i < imax; ++i)
|
for (int i = imin + 1; i < imax; ++i)
|
||||||
{
|
{
|
||||||
BVItem it = items[i];
|
BVItem it = items[i];
|
||||||
if (it.bmin[0] < bmin[0])
|
if (it.bmin.X < bmin.X)
|
||||||
bmin[0] = it.bmin[0];
|
bmin.X = it.bmin.X;
|
||||||
if (it.bmin[1] < bmin[1])
|
if (it.bmin.Y < bmin.Y)
|
||||||
bmin[1] = it.bmin[1];
|
bmin.Y = it.bmin.Y;
|
||||||
if (it.bmin[2] < bmin[2])
|
if (it.bmin.Z < bmin.Z)
|
||||||
bmin[2] = it.bmin[2];
|
bmin.Z = it.bmin.Z;
|
||||||
|
|
||||||
if (it.bmax[0] > bmax[0])
|
if (it.bmax.X > bmax.X)
|
||||||
bmax[0] = it.bmax[0];
|
bmax.X = it.bmax.X;
|
||||||
if (it.bmax[1] > bmax[1])
|
if (it.bmax.Y > bmax.Y)
|
||||||
bmax[1] = it.bmax[1];
|
bmax.Y = it.bmax.Y;
|
||||||
if (it.bmax[2] > bmax[2])
|
if (it.bmax.Z > bmax.Z)
|
||||||
bmax[2] = it.bmax[2];
|
bmax.Z = it.bmax.Z;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new int[][] { bmin, bmax };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int LongestAxis(int x, int y, int z)
|
private static int LongestAxis(int x, int y, int z)
|
||||||
|
@ -92,25 +85,21 @@ namespace DotRecast.Detour
|
||||||
if (inum == 1)
|
if (inum == 1)
|
||||||
{
|
{
|
||||||
// Leaf
|
// Leaf
|
||||||
node.bmin[0] = items[imin].bmin[0];
|
node.bmin = items[imin].bmin;
|
||||||
node.bmin[1] = items[imin].bmin[1];
|
node.bmax = items[imin].bmax;
|
||||||
node.bmin[2] = items[imin].bmin[2];
|
|
||||||
|
|
||||||
node.bmax[0] = items[imin].bmax[0];
|
|
||||||
node.bmax[1] = items[imin].bmax[1];
|
|
||||||
node.bmax[2] = items[imin].bmax[2];
|
|
||||||
|
|
||||||
node.i = items[imin].i;
|
node.i = items[imin].i;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Split
|
// Split
|
||||||
int[][] minmax = CalcExtends(items, nitems, imin, imax);
|
CalcExtends(items, nitems, imin, imax, ref node.bmin, ref node.bmax);
|
||||||
node.bmin = minmax[0];
|
|
||||||
node.bmax = minmax[1];
|
|
||||||
|
|
||||||
int axis = LongestAxis(node.bmax[0] - node.bmin[0], node.bmax[1] - node.bmin[1],
|
int axis = LongestAxis(
|
||||||
node.bmax[2] - node.bmin[2]);
|
node.bmax.X - node.bmin.X,
|
||||||
|
node.bmax.Y - node.bmin.Y,
|
||||||
|
node.bmax.Z - node.bmin.Z
|
||||||
|
);
|
||||||
|
|
||||||
if (axis == 0)
|
if (axis == 0)
|
||||||
{
|
{
|
||||||
|
@ -159,29 +148,29 @@ namespace DotRecast.Detour
|
||||||
int vb = option.detailMeshes[i * 4 + 0];
|
int vb = option.detailMeshes[i * 4 + 0];
|
||||||
int ndv = option.detailMeshes[i * 4 + 1];
|
int ndv = option.detailMeshes[i * 4 + 1];
|
||||||
int dv = vb * 3;
|
int dv = vb * 3;
|
||||||
var bmin = RcVecUtils.Create(option.detailVerts, dv);
|
var bmin = RcVec.Create(option.detailVerts, dv);
|
||||||
var bmax = RcVecUtils.Create(option.detailVerts, dv);
|
var bmax = RcVec.Create(option.detailVerts, dv);
|
||||||
for (int j = 1; j < ndv; j++)
|
for (int j = 1; j < ndv; j++)
|
||||||
{
|
{
|
||||||
bmin = RcVecUtils.Min(bmin, option.detailVerts, dv + j * 3);
|
bmin = RcVec3f.Min(bmin, RcVec.Create(option.detailVerts, dv + j * 3));
|
||||||
bmax = RcVecUtils.Max(bmax, option.detailVerts, dv + j * 3);
|
bmax = RcVec3f.Max(bmax, RcVec.Create(option.detailVerts, dv + j * 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
// BV-tree uses cs for all dimensions
|
// BV-tree uses cs for all dimensions
|
||||||
it.bmin[0] = Math.Clamp((int)((bmin.X - option.bmin.X) * quantFactor), 0, int.MaxValue);
|
it.bmin.X = Math.Clamp((int)((bmin.X - option.bmin.X) * quantFactor), 0, int.MaxValue);
|
||||||
it.bmin[1] = Math.Clamp((int)((bmin.Y - option.bmin.Y) * quantFactor), 0, int.MaxValue);
|
it.bmin.Y = Math.Clamp((int)((bmin.Y - option.bmin.Y) * quantFactor), 0, int.MaxValue);
|
||||||
it.bmin[2] = Math.Clamp((int)((bmin.Z - option.bmin.Z) * quantFactor), 0, int.MaxValue);
|
it.bmin.Z = Math.Clamp((int)((bmin.Z - option.bmin.Z) * quantFactor), 0, int.MaxValue);
|
||||||
|
|
||||||
it.bmax[0] = Math.Clamp((int)((bmax.X - option.bmin.X) * quantFactor), 0, int.MaxValue);
|
it.bmax.X = Math.Clamp((int)((bmax.X - option.bmin.X) * quantFactor), 0, int.MaxValue);
|
||||||
it.bmax[1] = Math.Clamp((int)((bmax.Y - option.bmin.Y) * quantFactor), 0, int.MaxValue);
|
it.bmax.Y = Math.Clamp((int)((bmax.Y - option.bmin.Y) * quantFactor), 0, int.MaxValue);
|
||||||
it.bmax[2] = Math.Clamp((int)((bmax.Z - option.bmin.Z) * quantFactor), 0, int.MaxValue);
|
it.bmax.Z = Math.Clamp((int)((bmax.Z - option.bmin.Z) * quantFactor), 0, int.MaxValue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int p = i * option.nvp * 2;
|
int p = i * option.nvp * 2;
|
||||||
it.bmin[0] = it.bmax[0] = option.verts[option.polys[p] * 3 + 0];
|
it.bmin.X = it.bmax.X = option.verts[option.polys[p] * 3 + 0];
|
||||||
it.bmin[1] = it.bmax[1] = option.verts[option.polys[p] * 3 + 1];
|
it.bmin.Y = it.bmax.Y = option.verts[option.polys[p] * 3 + 1];
|
||||||
it.bmin[2] = it.bmax[2] = option.verts[option.polys[p] * 3 + 2];
|
it.bmin.Z = it.bmax.Z = option.verts[option.polys[p] * 3 + 2];
|
||||||
|
|
||||||
for (int j = 1; j < option.nvp; ++j)
|
for (int j = 1; j < option.nvp; ++j)
|
||||||
{
|
{
|
||||||
|
@ -191,24 +180,24 @@ namespace DotRecast.Detour
|
||||||
int y = option.verts[option.polys[p + j] * 3 + 1];
|
int y = option.verts[option.polys[p + j] * 3 + 1];
|
||||||
int z = option.verts[option.polys[p + j] * 3 + 2];
|
int z = option.verts[option.polys[p + j] * 3 + 2];
|
||||||
|
|
||||||
if (x < it.bmin[0])
|
if (x < it.bmin.X)
|
||||||
it.bmin[0] = x;
|
it.bmin.X = x;
|
||||||
if (y < it.bmin[1])
|
if (y < it.bmin.Y)
|
||||||
it.bmin[1] = y;
|
it.bmin.Y = y;
|
||||||
if (z < it.bmin[2])
|
if (z < it.bmin.Z)
|
||||||
it.bmin[2] = z;
|
it.bmin.Z = z;
|
||||||
|
|
||||||
if (x > it.bmax[0])
|
if (x > it.bmax.X)
|
||||||
it.bmax[0] = x;
|
it.bmax.X = x;
|
||||||
if (y > it.bmax[1])
|
if (y > it.bmax.Y)
|
||||||
it.bmax[1] = y;
|
it.bmax.Y = y;
|
||||||
if (z > it.bmax[2])
|
if (z > it.bmax.Z)
|
||||||
it.bmax[2] = z;
|
it.bmax.Z = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remap y
|
// Remap y
|
||||||
it.bmin[1] = (int)MathF.Floor(it.bmin[1] * option.ch * quantFactor);
|
it.bmin.Y = (int)MathF.Floor(it.bmin.Y * option.ch * quantFactor);
|
||||||
it.bmax[1] = (int)MathF.Ceiling(it.bmax[1] * option.ch * quantFactor);
|
it.bmax.Y = (int)MathF.Ceiling(it.bmax.Y * option.ch * quantFactor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,14 +240,15 @@ namespace DotRecast.Detour
|
||||||
return 0xff;
|
return 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// TODO: Better error handling.
|
||||||
* Builds navigation mesh tile data from the provided tile creation data.
|
|
||||||
*
|
/// @par
|
||||||
* @param option
|
///
|
||||||
* Tile creation data.
|
/// The output data array is allocated using the detour allocator (dtAlloc()). The method
|
||||||
*
|
/// used to free the memory will be determined by how the tile is added to the navigation
|
||||||
* @return created tile data
|
/// mesh.
|
||||||
*/
|
///
|
||||||
|
/// @see dtNavMesh, dtNavMesh::addTile()
|
||||||
public static DtMeshData CreateNavMeshData(DtNavMeshCreateParams option)
|
public static DtMeshData CreateNavMeshData(DtNavMeshCreateParams option)
|
||||||
{
|
{
|
||||||
if (option.vertCount >= 0xffff)
|
if (option.vertCount >= 0xffff)
|
||||||
|
@ -316,8 +306,8 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
for (int i = 0; i < option.offMeshConCount; ++i)
|
for (int i = 0; i < option.offMeshConCount; ++i)
|
||||||
{
|
{
|
||||||
var p0 = RcVecUtils.Create(option.offMeshConVerts, (i * 2 + 0) * 3);
|
var p0 = RcVec.Create(option.offMeshConVerts, (i * 2 + 0) * 3);
|
||||||
var p1 = RcVecUtils.Create(option.offMeshConVerts, (i * 2 + 1) * 3);
|
var p1 = RcVec.Create(option.offMeshConVerts, (i * 2 + 1) * 3);
|
||||||
|
|
||||||
offMeshConClass[i * 2 + 0] = ClassifyOffMeshPoint(p0, bmin, bmax);
|
offMeshConClass[i * 2 + 0] = ClassifyOffMeshPoint(p0, bmin, bmax);
|
||||||
offMeshConClass[i * 2 + 1] = ClassifyOffMeshPoint(p1, bmin, bmax);
|
offMeshConClass[i * 2 + 1] = ClassifyOffMeshPoint(p1, bmin, bmax);
|
||||||
|
@ -424,8 +414,8 @@ namespace DotRecast.Detour
|
||||||
DtOffMeshConnection[] offMeshCons = new DtOffMeshConnection[storedOffMeshConCount];
|
DtOffMeshConnection[] offMeshCons = new DtOffMeshConnection[storedOffMeshConCount];
|
||||||
|
|
||||||
// Store header
|
// Store header
|
||||||
header.magic = DtNavMesh.DT_NAVMESH_MAGIC;
|
header.magic = DT_NAVMESH_MAGIC;
|
||||||
header.version = DtNavMesh.DT_NAVMESH_VERSION;
|
header.version = DT_NAVMESH_VERSION;
|
||||||
header.x = option.tileX;
|
header.x = option.tileX;
|
||||||
header.y = option.tileZ;
|
header.y = option.tileZ;
|
||||||
header.layer = option.tileLayer;
|
header.layer = option.tileLayer;
|
||||||
|
@ -497,13 +487,13 @@ namespace DotRecast.Detour
|
||||||
if (dir == 0xf) // Border
|
if (dir == 0xf) // Border
|
||||||
p.neis[j] = 0;
|
p.neis[j] = 0;
|
||||||
else if (dir == 0) // Portal x-
|
else if (dir == 0) // Portal x-
|
||||||
p.neis[j] = DtNavMesh.DT_EXT_LINK | 4;
|
p.neis[j] = DT_EXT_LINK | 4;
|
||||||
else if (dir == 1) // Portal z+
|
else if (dir == 1) // Portal z+
|
||||||
p.neis[j] = DtNavMesh.DT_EXT_LINK | 2;
|
p.neis[j] = DT_EXT_LINK | 2;
|
||||||
else if (dir == 2) // Portal x+
|
else if (dir == 2) // Portal x+
|
||||||
p.neis[j] = DtNavMesh.DT_EXT_LINK | 0;
|
p.neis[j] = DT_EXT_LINK | 0;
|
||||||
else if (dir == 3) // Portal z-
|
else if (dir == 3) // Portal z-
|
||||||
p.neis[j] = DtNavMesh.DT_EXT_LINK | 6;
|
p.neis[j] = DT_EXT_LINK | 6;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -550,9 +540,9 @@ namespace DotRecast.Detour
|
||||||
int ndv = option.detailMeshes[i * 4 + 1];
|
int ndv = option.detailMeshes[i * 4 + 1];
|
||||||
int nv = navPolys[i].vertCount;
|
int nv = navPolys[i].vertCount;
|
||||||
int vertBase = vbase;
|
int vertBase = vbase;
|
||||||
int vertCount = (ndv - nv);
|
byte vertCount = (byte)(ndv - nv);
|
||||||
int triBase = option.detailMeshes[i * 4 + 2];
|
int triBase = option.detailMeshes[i * 4 + 2];
|
||||||
int triCount = option.detailMeshes[i * 4 + 3];
|
byte triCount = (byte)option.detailMeshes[i * 4 + 3];
|
||||||
navDMeshes[i] = new DtPolyDetail(vertBase, triBase, vertCount, triCount);
|
navDMeshes[i] = new DtPolyDetail(vertBase, triBase, vertCount, triCount);
|
||||||
// Copy vertices except the first 'nv' verts which are equal to
|
// Copy vertices except the first 'nv' verts which are equal to
|
||||||
// nav poly verts.
|
// nav poly verts.
|
||||||
|
@ -574,9 +564,9 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
int nv = navPolys[i].vertCount;
|
int nv = navPolys[i].vertCount;
|
||||||
int vertBase = 0;
|
int vertBase = 0;
|
||||||
int vertCount = 0;
|
byte vertCount = 0;
|
||||||
int triBase = tbase;
|
int triBase = tbase;
|
||||||
int triCount = (nv - 2);
|
byte triCount = (byte)(nv - 2);
|
||||||
navDMeshes[i] = new DtPolyDetail(vertBase, triBase, vertCount, triCount);
|
navDMeshes[i] = new DtPolyDetail(vertBase, triBase, vertCount, triCount);
|
||||||
// Triangulate polygon (local indices).
|
// Triangulate polygon (local indices).
|
||||||
for (int j = 2; j < nv; ++j)
|
for (int j = 2; j < nv; ++j)
|
||||||
|
@ -618,11 +608,11 @@ namespace DotRecast.Detour
|
||||||
int endPts = i * 2 * 3;
|
int endPts = i * 2 * 3;
|
||||||
for (int j = 0; j < 2; ++j)
|
for (int j = 0; j < 2; ++j)
|
||||||
{
|
{
|
||||||
con.pos[j] = RcVecUtils.Create(option.offMeshConVerts, endPts + (j * 3));
|
con.pos[j] = RcVec.Create(option.offMeshConVerts, endPts + (j * 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
con.rad = option.offMeshConRad[i];
|
con.rad = option.offMeshConRad[i];
|
||||||
con.flags = option.offMeshConDir[i] != 0 ? DtNavMesh.DT_OFFMESH_CON_BIDIR : 0;
|
con.flags = option.offMeshConDir[i] != 0 ? DT_OFFMESH_CON_BIDIR : 0;
|
||||||
con.side = offMeshConClass[i * 2 + 1];
|
con.side = offMeshConClass[i * 2 + 1];
|
||||||
if (option.offMeshConUserID != null)
|
if (option.offMeshConUserID != null)
|
||||||
con.userId = option.offMeshConUserID[i];
|
con.userId = option.offMeshConUserID[i];
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -23,27 +23,16 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/**
|
/// Configuration parameters used to define multi-tile navigation meshes.
|
||||||
* Configuration parameters used to define multi-tile navigation meshes. The values are used to allocate space during
|
/// The values are used to allocate space during the initialization of a navigation mesh.
|
||||||
* the initialization of a navigation mesh.
|
/// @see dtNavMesh::init()
|
||||||
*
|
/// @ingroup detour
|
||||||
* @see NavMesh
|
|
||||||
*/
|
|
||||||
public struct DtNavMeshParams
|
public struct DtNavMeshParams
|
||||||
{
|
{
|
||||||
/** The world space origin of the navigation mesh's tile space. [(x, y, z)] */
|
public RcVec3f orig; //< The world space origin of the navigation mesh's tile space. [(x, y, z)]
|
||||||
public RcVec3f orig;
|
public float tileWidth; //< The width of each tile. (Along the x-axis.)
|
||||||
|
public float tileHeight; //< The height of each tile. (Along the z-axis.)
|
||||||
/** The width of each tile. (Along the x-axis.) */
|
public int maxTiles; //< The maximum number of tiles the navigation mesh can contain. This and maxPolys are used to calculate how many bits are needed to identify tiles and polygons uniquely.
|
||||||
public float tileWidth;
|
public int maxPolys; //< The maximum number of polygons each tile can contain. This and maxTiles are used to calculate how many bits are needed to identify tiles and polygons uniquely.
|
||||||
|
|
||||||
/** The height of each tile. (Along the z-axis.) */
|
|
||||||
public float tileHeight;
|
|
||||||
|
|
||||||
/** The maximum number of tiles the navigation mesh can contain. */
|
|
||||||
public int maxTiles;
|
|
||||||
|
|
||||||
/** The maximum number of polygons each tile can contain. */
|
|
||||||
public int maxPolys;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,34 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
|
namespace DotRecast.Detour
|
||||||
|
{
|
||||||
|
public class DtNavMeshQueryMock : DtNavMeshQuery
|
||||||
|
{
|
||||||
|
private readonly DtStraightPath[] _straightPath;
|
||||||
|
private readonly DtStatus _status;
|
||||||
|
|
||||||
|
public DtNavMeshQueryMock(DtStraightPath[] straightPath, DtStatus status)
|
||||||
|
: base(null)
|
||||||
|
{
|
||||||
|
_straightPath = straightPath;
|
||||||
|
_status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override DtStatus FindStraightPath(RcVec3f startPos, RcVec3f endPos,
|
||||||
|
List<long> path, int pathSize,
|
||||||
|
Span<DtStraightPath> straightPath, out int straightPathCount, int maxStraightPath,
|
||||||
|
int options)
|
||||||
|
{
|
||||||
|
straightPathCount = 0;
|
||||||
|
for (int i = 0; i < _straightPath.Length && i < maxStraightPath; ++i)
|
||||||
|
{
|
||||||
|
straightPath[i] = _straightPath[i];
|
||||||
|
straightPathCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -17,6 +17,7 @@ freely, subject to the following restrictions:
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
|
@ -48,6 +49,7 @@ namespace DotRecast.Detour
|
||||||
private static bool Raycast(DtMeshTile tile, RcVec3f sp, RcVec3f sq, out float hitTime)
|
private static bool Raycast(DtMeshTile tile, RcVec3f sp, RcVec3f sq, out float hitTime)
|
||||||
{
|
{
|
||||||
hitTime = 0.0f;
|
hitTime = 0.0f;
|
||||||
|
Span<RcVec3f> tempVerts = stackalloc RcVec3f[3];
|
||||||
for (int i = 0; i < tile.data.header.polyCount; ++i)
|
for (int i = 0; i < tile.data.header.polyCount; ++i)
|
||||||
{
|
{
|
||||||
DtPoly p = tile.data.polys[i];
|
DtPoly p = tile.data.polys[i];
|
||||||
|
@ -58,7 +60,7 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
ref DtPolyDetail pd = ref tile.data.detailMeshes[i];
|
ref DtPolyDetail pd = ref tile.data.detailMeshes[i];
|
||||||
|
|
||||||
RcVec3f[] verts = new RcVec3f[3];
|
Span<RcVec3f> verts = tempVerts;
|
||||||
for (int j = 0; j < pd.triCount; ++j)
|
for (int j = 0; j < pd.triCount; ++j)
|
||||||
{
|
{
|
||||||
int t = (pd.triBase + j) * 4;
|
int t = (pd.triBase + j) * 4;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
public static class DtNodeFlags
|
public static class DtNodeFlags
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -24,22 +24,24 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
using static DtDetour;
|
||||||
|
|
||||||
public static class DtPathUtils
|
public static class DtPathUtils
|
||||||
{
|
{
|
||||||
private const int MAX_STEER_POINTS = 3;
|
|
||||||
|
|
||||||
public static bool GetSteerTarget(DtNavMeshQuery navQuery, RcVec3f startPos, RcVec3f endPos,
|
public static bool GetSteerTarget(DtNavMeshQuery navQuery, RcVec3f startPos, RcVec3f endPos,
|
||||||
float minTargetDist,
|
float minTargetDist,
|
||||||
List<long> path,
|
List<long> path, int pathSize,
|
||||||
out RcVec3f steerPos, out int steerPosFlag, out long steerPosRef)
|
out RcVec3f steerPos, out int steerPosFlag, out long steerPosRef)
|
||||||
{
|
{
|
||||||
|
const int MAX_STEER_POINTS = 3;
|
||||||
|
|
||||||
steerPos = RcVec3f.Zero;
|
steerPos = RcVec3f.Zero;
|
||||||
steerPosFlag = 0;
|
steerPosFlag = 0;
|
||||||
steerPosRef = 0;
|
steerPosRef = 0;
|
||||||
|
|
||||||
// Find steer target.
|
// Find steer target.
|
||||||
var straightPath = new List<DtStraightPath>(MAX_STEER_POINTS);
|
Span<DtStraightPath> straightPath = stackalloc DtStraightPath[MAX_STEER_POINTS];
|
||||||
var result = navQuery.FindStraightPath(startPos, endPos, path, ref straightPath, MAX_STEER_POINTS, 0);
|
var result = navQuery.FindStraightPath(startPos, endPos, path, pathSize, straightPath, out var nsteerPath, MAX_STEER_POINTS, 0);
|
||||||
if (result.Failed())
|
if (result.Failed())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -47,7 +49,7 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
// Find vertex far enough to steer to.
|
// Find vertex far enough to steer to.
|
||||||
int ns = 0;
|
int ns = 0;
|
||||||
while (ns < straightPath.Count)
|
while (ns < nsteerPath)
|
||||||
{
|
{
|
||||||
// Stop at Off-Mesh link or when point is further than slop away.
|
// Stop at Off-Mesh link or when point is further than slop away.
|
||||||
if (((straightPath[ns].flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
if (((straightPath[ns].flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
||||||
|
@ -57,7 +59,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failed to find good point to steer to.
|
// Failed to find good point to steer to.
|
||||||
if (ns >= straightPath.Count)
|
if (ns >= nsteerPath)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
steerPos = straightPath[ns].pos;
|
steerPos = straightPath[ns].pos;
|
||||||
|
@ -88,29 +90,32 @@ namespace DotRecast.Detour
|
||||||
// +-S-+-T-+
|
// +-S-+-T-+
|
||||||
// |:::| | <-- the step can end up in here, resulting U-turn path.
|
// |:::| | <-- the step can end up in here, resulting U-turn path.
|
||||||
// +---+---+
|
// +---+---+
|
||||||
public static List<long> FixupShortcuts(List<long> path, DtNavMeshQuery navQuery)
|
public static int FixupShortcuts(ref List<long> path, int npath, DtNavMeshQuery navQuery)
|
||||||
{
|
{
|
||||||
if (path.Count < 3)
|
if (npath < 3)
|
||||||
{
|
{
|
||||||
return path;
|
return npath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get connected polygons
|
// Get connected polygons
|
||||||
List<long> neis = new List<long>();
|
const int maxNeis = 16;
|
||||||
|
Span<long> neis = stackalloc long[maxNeis];
|
||||||
|
int nneis = 0;
|
||||||
|
|
||||||
var status = navQuery.GetAttachedNavMesh().GetTileAndPolyByRef(path[0], out var tile, out var poly);
|
var status = navQuery.GetAttachedNavMesh().GetTileAndPolyByRef(path[0], out var tile, out var poly);
|
||||||
if (status.Failed())
|
if (status.Failed())
|
||||||
{
|
{
|
||||||
return path;
|
return npath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (int k = tile.polyLinks[poly.index]; k != DtNavMesh.DT_NULL_LINK; k = tile.links[k].next)
|
for (int k = poly.firstLink; k != DT_NULL_LINK; k = tile.links[k].next)
|
||||||
{
|
{
|
||||||
DtLink link = tile.links[k];
|
DtLink link = tile.links[k];
|
||||||
if (link.refs != 0)
|
if (link.refs != 0)
|
||||||
{
|
{
|
||||||
neis.Add(link.refs);
|
if (nneis < maxNeis)
|
||||||
|
neis[nneis++] = link.refs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,9 +123,9 @@ namespace DotRecast.Detour
|
||||||
// in the path, short cut to that polygon directly.
|
// in the path, short cut to that polygon directly.
|
||||||
const int maxLookAhead = 6;
|
const int maxLookAhead = 6;
|
||||||
int cut = 0;
|
int cut = 0;
|
||||||
for (int i = Math.Min(maxLookAhead, path.Count) - 1; i > 1 && cut == 0; i--)
|
for (int i = Math.Min(maxLookAhead, npath) - 1; i > 1 && cut == 0; i--)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < neis.Count; j++)
|
for (int j = 0; j < nneis; j++)
|
||||||
{
|
{
|
||||||
if (path[i] == neis[j])
|
if (path[i] == neis[j])
|
||||||
{
|
{
|
||||||
|
@ -134,23 +139,25 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
List<long> shortcut = new List<long>();
|
List<long> shortcut = new List<long>();
|
||||||
shortcut.Add(path[0]);
|
shortcut.Add(path[0]);
|
||||||
shortcut.AddRange(path.GetRange(cut, path.Count - cut));
|
shortcut.AddRange(path.GetRange(cut, npath - cut));
|
||||||
return shortcut;
|
|
||||||
|
path = shortcut;
|
||||||
|
return shortcut.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return npath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<long> MergeCorridorStartMoved(List<long> path, int npath, int maxPath, List<long> visited)
|
public static int MergeCorridorStartMoved(ref List<long> path, int npath, int maxPath, Span<long> visited, int nvisited)
|
||||||
{
|
{
|
||||||
int furthestPath = -1;
|
int furthestPath = -1;
|
||||||
int furthestVisited = -1;
|
int furthestVisited = -1;
|
||||||
|
|
||||||
// Find furthest common polygon.
|
// Find furthest common polygon.
|
||||||
for (int i = path.Count - 1; i >= 0; --i)
|
for (int i = npath - 1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (int j = visited.Count - 1; j >= 0; --j)
|
for (int j = nvisited - 1; j >= 0; --j)
|
||||||
{
|
{
|
||||||
if (path[i] == visited[j])
|
if (path[i] == visited[j])
|
||||||
{
|
{
|
||||||
|
@ -169,7 +176,7 @@ namespace DotRecast.Detour
|
||||||
// If no intersection found just return current path.
|
// If no intersection found just return current path.
|
||||||
if (furthestPath == -1 || furthestVisited == -1)
|
if (furthestPath == -1 || furthestVisited == -1)
|
||||||
{
|
{
|
||||||
return path;
|
return npath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concatenate paths.
|
// Concatenate paths.
|
||||||
|
@ -177,25 +184,27 @@ namespace DotRecast.Detour
|
||||||
// Adjust beginning of the buffer to include the visited.
|
// Adjust beginning of the buffer to include the visited.
|
||||||
List<long> result = new List<long>();
|
List<long> result = new List<long>();
|
||||||
// Store visited
|
// Store visited
|
||||||
for (int i = visited.Count - 1; i > furthestVisited; --i)
|
for (int i = nvisited - 1; i > furthestVisited; --i)
|
||||||
{
|
{
|
||||||
result.Add(visited[i]);
|
result.Add(visited[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.AddRange(path.GetRange(furthestPath, path.Count - furthestPath));
|
result.AddRange(path.GetRange(furthestPath, npath - furthestPath));
|
||||||
return result;
|
|
||||||
|
path = result;
|
||||||
|
return result.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<long> MergeCorridorEndMoved(List<long> path, int npath, int maxPath, List<long> visited)
|
public static int MergeCorridorEndMoved(ref List<long> path, int npath, int maxPath, Span<long> visited, int nvisited)
|
||||||
{
|
{
|
||||||
int furthestPath = -1;
|
int furthestPath = -1;
|
||||||
int furthestVisited = -1;
|
int furthestVisited = -1;
|
||||||
|
|
||||||
// Find furthest common polygon.
|
// Find furthest common polygon.
|
||||||
for (int i = 0; i < path.Count; ++i)
|
for (int i = 0; i < npath; ++i)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (int j = visited.Count - 1; j >= 0; --j)
|
for (int j = nvisited - 1; j >= 0; --j)
|
||||||
{
|
{
|
||||||
if (path[i] == visited[j])
|
if (path[i] == visited[j])
|
||||||
{
|
{
|
||||||
|
@ -214,25 +223,30 @@ namespace DotRecast.Detour
|
||||||
// If no intersection found just return current path.
|
// If no intersection found just return current path.
|
||||||
if (furthestPath == -1 || furthestVisited == -1)
|
if (furthestPath == -1 || furthestVisited == -1)
|
||||||
{
|
{
|
||||||
return path;
|
return npath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concatenate paths.
|
// Concatenate paths.
|
||||||
List<long> result = path.GetRange(0, furthestPath);
|
List<long> result = path.GetRange(0, furthestPath);
|
||||||
result.AddRange(visited.GetRange(furthestVisited, visited.Count - furthestVisited));
|
foreach (var v in visited.Slice(furthestVisited, nvisited - furthestVisited))
|
||||||
return result;
|
{
|
||||||
|
result.Add(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
path = result;
|
||||||
|
return result.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<long> MergeCorridorStartShortcut(List<long> path, int npath, int maxPath, List<long> visited)
|
public static int MergeCorridorStartShortcut(ref List<long> path, int npath, int maxPath, List<long> visited, int nvisited)
|
||||||
{
|
{
|
||||||
int furthestPath = -1;
|
int furthestPath = -1;
|
||||||
int furthestVisited = -1;
|
int furthestVisited = -1;
|
||||||
|
|
||||||
// Find furthest common polygon.
|
// Find furthest common polygon.
|
||||||
for (int i = path.Count - 1; i >= 0; --i)
|
for (int i = npath - 1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (int j = visited.Count - 1; j >= 0; --j)
|
for (int j = nvisited - 1; j >= 0; --j)
|
||||||
{
|
{
|
||||||
if (path[i] == visited[j])
|
if (path[i] == visited[j])
|
||||||
{
|
{
|
||||||
|
@ -251,15 +265,17 @@ namespace DotRecast.Detour
|
||||||
// If no intersection found just return current path.
|
// If no intersection found just return current path.
|
||||||
if (furthestPath == -1 || furthestVisited <= 0)
|
if (furthestPath == -1 || furthestVisited <= 0)
|
||||||
{
|
{
|
||||||
return path;
|
return npath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concatenate paths.
|
// Concatenate paths.
|
||||||
|
|
||||||
// Adjust beginning of the buffer to include the visited.
|
// Adjust beginning of the buffer to include the visited.
|
||||||
List<long> result = visited.GetRange(0, furthestVisited);
|
List<long> result = visited.GetRange(0, furthestVisited);
|
||||||
result.AddRange(path.GetRange(furthestPath, path.Count - furthestPath));
|
result.AddRange(path.GetRange(furthestPath, npath - furthestPath));
|
||||||
return result;
|
|
||||||
|
path = result;
|
||||||
|
return result.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -18,26 +18,28 @@ freely, subject to the following restrictions:
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/** Defines a polygon within a MeshTile object. */
|
/// Defines a polygon within a dtMeshTile object.
|
||||||
[Serializable]
|
/// @ingroup detour
|
||||||
public class DtPoly
|
public class DtPoly
|
||||||
{
|
{
|
||||||
public int index;
|
public readonly int index;
|
||||||
|
|
||||||
/** The indices of the polygon's vertices. The actual vertices are located in MeshTile::verts. */
|
/// Index to first link in linked list. (Or #DT_NULL_LINK if there is no link.)
|
||||||
public int[] verts;
|
public int firstLink;
|
||||||
|
|
||||||
/** Packed data representing neighbor polygons references and flags for each edge. */
|
/// The indices of the polygon's vertices.
|
||||||
public int[] neis;
|
/// The actual vertices are located in dtMeshTile::verts.
|
||||||
|
public readonly int[] verts;
|
||||||
|
|
||||||
/** The user defined polygon flags. */
|
/// Packed data representing neighbor polygons references and flags for each edge.
|
||||||
|
public readonly int[] neis;
|
||||||
|
|
||||||
|
/// The user defined polygon flags.
|
||||||
public int flags;
|
public int flags;
|
||||||
|
|
||||||
/** The number of vertices in the polygon. */
|
/// The number of vertices in the polygon.
|
||||||
public int vertCount;
|
public int vertCount;
|
||||||
|
|
||||||
/// The bit packed area id and polygon type.
|
/// The bit packed area id and polygon type.
|
||||||
|
@ -51,25 +53,25 @@ namespace DotRecast.Detour
|
||||||
neis = new int[maxVertsPerPoly];
|
neis = new int[maxVertsPerPoly];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the user defined area id. [Limit: < {@link org.recast4j.detour.NavMesh#DT_MAX_AREAS}] */
|
/// Sets the user defined area id. [Limit: < #DT_MAX_AREAS]
|
||||||
public void SetArea(int a)
|
public void SetArea(int a)
|
||||||
{
|
{
|
||||||
areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f);
|
areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the polygon type. (See: #dtPolyTypes.) */
|
/// Sets the polygon type. (See: #dtPolyTypes.)
|
||||||
public void SetPolyType(int t)
|
public void SetPolyType(int t)
|
||||||
{
|
{
|
||||||
areaAndtype = (areaAndtype & 0x3f) | (t << 6);
|
areaAndtype = (areaAndtype & 0x3f) | (t << 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the user defined area id. */
|
/// Gets the user defined area id.
|
||||||
public int GetArea()
|
public int GetArea()
|
||||||
{
|
{
|
||||||
return areaAndtype & 0x3f;
|
return areaAndtype & 0x3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the polygon type. (See: #dtPolyTypes) */
|
/// Gets the polygon type. (See: #dtPolyTypes)
|
||||||
public int GetPolyType()
|
public int GetPolyType()
|
||||||
{
|
{
|
||||||
return areaAndtype >> 6;
|
return areaAndtype >> 6;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -20,22 +20,15 @@ freely, subject to the following restrictions:
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/** Defines the location of detail sub-mesh data within a dtMeshTile. */
|
/// Defines the location of detail sub-mesh data within a dtMeshTile.
|
||||||
public struct DtPolyDetail
|
public readonly struct DtPolyDetail
|
||||||
{
|
{
|
||||||
/** The offset of the vertices in the MeshTile::detailVerts array. */
|
public readonly int vertBase; //< The offset of the vertices in the dtMeshTile::detailVerts array.
|
||||||
public int vertBase;
|
public readonly int triBase; //< The offset of the triangles in the dtMeshTile::detailTris array.
|
||||||
|
public readonly byte vertCount; //< The number of vertices in the sub-mesh.
|
||||||
|
public readonly byte triCount; //< The number of triangles in the sub-mesh.
|
||||||
|
|
||||||
/** The offset of the triangles in the MeshTile::detailTris array. */
|
public DtPolyDetail(int vertBase, int triBase, byte vertCount, byte triCount)
|
||||||
public int triBase;
|
|
||||||
|
|
||||||
/** The number of vertices in the sub-mesh. */
|
|
||||||
public int vertCount;
|
|
||||||
|
|
||||||
/** The number of triangles in the sub-mesh. */
|
|
||||||
public int triCount;
|
|
||||||
|
|
||||||
public DtPolyDetail(int vertBase, int triBase, int vertCount, int triCount)
|
|
||||||
{
|
{
|
||||||
this.vertBase = vertBase;
|
this.vertBase = vertBase;
|
||||||
this.triBase = triBase;
|
this.triBase = triBase;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/// Flags representing the type of a navigation mesh polygon.
|
/// Flags representing the type of a navigation mesh polygon.
|
||||||
public static class DtPolyTypes
|
public static class DtPolyTypes
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -23,6 +23,8 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
using static DtDetour;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <b>The Default Implementation</b>
|
* <b>The Default Implementation</b>
|
||||||
*
|
*
|
||||||
|
@ -50,7 +52,7 @@ namespace DotRecast.Detour
|
||||||
*/
|
*/
|
||||||
public class DtQueryDefaultFilter : IDtQueryFilter
|
public class DtQueryDefaultFilter : IDtQueryFilter
|
||||||
{
|
{
|
||||||
private readonly float[] m_areaCost = new float[DtNavMesh.DT_MAX_AREAS]; //< Cost per area type. (Used by default implementation.)
|
private readonly float[] m_areaCost = new float[DT_MAX_AREAS]; //< Cost per area type. (Used by default implementation.)
|
||||||
private int m_includeFlags; //< Flags for polygons that can be visited. (Used by default implementation.)
|
private int m_includeFlags; //< Flags for polygons that can be visited. (Used by default implementation.)
|
||||||
private int m_excludeFlags; //< Flags for polygons that should not be visited. (Used by default implementation.)
|
private int m_excludeFlags; //< Flags for polygons that should not be visited. (Used by default implementation.)
|
||||||
|
|
||||||
|
@ -58,7 +60,7 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
m_includeFlags = 0xffff;
|
m_includeFlags = 0xffff;
|
||||||
m_excludeFlags = 0;
|
m_excludeFlags = 0;
|
||||||
for (int i = 0; i < DtNavMesh.DT_MAX_AREAS; ++i)
|
for (int i = 0; i < DT_MAX_AREAS; ++i)
|
||||||
{
|
{
|
||||||
m_areaCost[i] = 1.0f;
|
m_areaCost[i] = 1.0f;
|
||||||
}
|
}
|
||||||
|
@ -68,12 +70,12 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
m_includeFlags = includeFlags;
|
m_includeFlags = includeFlags;
|
||||||
m_excludeFlags = excludeFlags;
|
m_excludeFlags = excludeFlags;
|
||||||
for (int i = 0; i < Math.Min(DtNavMesh.DT_MAX_AREAS, areaCost.Length); ++i)
|
for (int i = 0; i < Math.Min(DT_MAX_AREAS, areaCost.Length); ++i)
|
||||||
{
|
{
|
||||||
m_areaCost[i] = areaCost[i];
|
m_areaCost[i] = areaCost[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = areaCost.Length; i < DtNavMesh.DT_MAX_AREAS; ++i)
|
for (int i = areaCost.Length; i < DT_MAX_AREAS; ++i)
|
||||||
{
|
{
|
||||||
m_areaCost[i] = 1.0f;
|
m_areaCost[i] = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/// Options for dtNavMeshQuery::raycast
|
/// Options for dtNavMeshQuery::raycast
|
||||||
public static class DtRaycastOptions
|
public static class DtRaycastOptions
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
public readonly struct DtSegInterval
|
public readonly struct DtSegInterval
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -25,11 +25,16 @@ namespace DotRecast.Detour
|
||||||
//TODO: (PP) Add comments
|
//TODO: (PP) Add comments
|
||||||
public readonly struct DtStraightPath
|
public readonly struct DtStraightPath
|
||||||
{
|
{
|
||||||
|
/// The local path corridor corners for the agent. (Staight path.) [(x, y, z) * #ncorners]
|
||||||
public readonly RcVec3f pos;
|
public readonly RcVec3f pos;
|
||||||
public readonly int flags;
|
|
||||||
|
/// The local path corridor corner flags. (See: #dtStraightPathFlags) [(flags) * #ncorners]
|
||||||
|
public readonly byte flags;
|
||||||
|
|
||||||
|
/// The reference id of the polygon being entered at the corner. [(polyRef) * #ncorners]
|
||||||
public readonly long refs;
|
public readonly long refs;
|
||||||
|
|
||||||
public DtStraightPath(RcVec3f pos, int flags, long refs)
|
public DtStraightPath(RcVec3f pos, byte flags, long refs)
|
||||||
{
|
{
|
||||||
this.pos = pos;
|
this.pos = pos;
|
||||||
this.flags = flags;
|
this.flags = flags;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/// Vertex flags returned by dtNavMeshQuery::findStraightPath.
|
/// Vertex flags returned by dtNavMeshQuery::findStraightPath.
|
||||||
public static class DtStraightPathFlags
|
public static class DtStraightPathFlags
|
||||||
{
|
{
|
||||||
public const int DT_STRAIGHTPATH_START = 0x01; //< The vertex is the start position in the path.
|
public const byte DT_STRAIGHTPATH_START = 0x01; //< The vertex is the start position in the path.
|
||||||
public const int DT_STRAIGHTPATH_END = 0x02; //< The vertex is the end position in the path.
|
public const byte DT_STRAIGHTPATH_END = 0x02; //< The vertex is the end position in the path.
|
||||||
public const int DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04; //< The vertex is the start of an off-mesh connection.
|
public const byte DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04; //< The vertex is the start of an off-mesh connection.
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/// Options for dtNavMeshQuery::findStraightPath.
|
/// Options for dtNavMeshQuery::findStraightPath.
|
||||||
public static class DtStraightPathOptions
|
public static class DtStraightPathOptions
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/**
|
// Calculate the intersection between a polygon and a circle. A dodecagon is used as an approximation of the circle.
|
||||||
* Calculate the intersection between a polygon and a circle. A dodecagon is used as an approximation of the circle.
|
|
||||||
*/
|
|
||||||
public class DtStrictDtPolygonByCircleConstraint : IDtPolygonByCircleConstraint
|
public class DtStrictDtPolygonByCircleConstraint : IDtPolygonByCircleConstraint
|
||||||
{
|
{
|
||||||
private const int CIRCLE_SEGMENTS = 12;
|
private const int CIRCLE_SEGMENTS = 12;
|
||||||
private static readonly float[] UnitCircle = MakeUnitCircle();
|
private static readonly float[] UnitCircle = CreateCircle();
|
||||||
|
|
||||||
public static readonly IDtPolygonByCircleConstraint Shared = new DtStrictDtPolygonByCircleConstraint();
|
public static readonly IDtPolygonByCircleConstraint Shared = new DtStrictDtPolygonByCircleConstraint();
|
||||||
|
|
||||||
|
@ -17,7 +15,7 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float[] MakeUnitCircle()
|
public static float[] CreateCircle()
|
||||||
{
|
{
|
||||||
var temp = new float[CIRCLE_SEGMENTS * 3];
|
var temp = new float[CIRCLE_SEGMENTS * 3];
|
||||||
for (int i = 0; i < CIRCLE_SEGMENTS; i++)
|
for (int i = 0; i < CIRCLE_SEGMENTS; i++)
|
||||||
|
@ -31,13 +29,24 @@ namespace DotRecast.Detour
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ScaleCircle(Span<float> src, RcVec3f center, float radius, Span<float> dst)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < CIRCLE_SEGMENTS; i++)
|
||||||
|
{
|
||||||
|
dst[3 * i] = src[3 * i] * radius + center.X;
|
||||||
|
dst[3 * i + 1] = center.Y;
|
||||||
|
dst[3 * i + 2] = src[3 * i + 2] * radius + center.Z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public float[] Apply(float[] verts, RcVec3f center, float radius)
|
public float[] Apply(float[] verts, RcVec3f center, float radius)
|
||||||
{
|
{
|
||||||
float radiusSqr = radius * radius;
|
float radiusSqr = radius * radius;
|
||||||
int outsideVertex = -1;
|
int outsideVertex = -1;
|
||||||
for (int pv = 0; pv < verts.Length; pv += 3)
|
for (int pv = 0; pv < verts.Length; pv += 3)
|
||||||
{
|
{
|
||||||
if (RcVecUtils.Dist2DSqr(center, verts, pv) > radiusSqr)
|
if (RcVec.Dist2DSqr(center, verts, pv) > radiusSqr)
|
||||||
{
|
{
|
||||||
outsideVertex = pv;
|
outsideVertex = pv;
|
||||||
break;
|
break;
|
||||||
|
@ -50,29 +59,16 @@ namespace DotRecast.Detour
|
||||||
return verts;
|
return verts;
|
||||||
}
|
}
|
||||||
|
|
||||||
float[] qCircle = Circle(center, radius);
|
Span<float> qCircle = stackalloc float[UnitCircle.Length];
|
||||||
|
ScaleCircle(UnitCircle, center, radius, qCircle);
|
||||||
float[] intersection = DtConvexConvexIntersections.Intersect(verts, qCircle);
|
float[] intersection = DtConvexConvexIntersections.Intersect(verts, qCircle);
|
||||||
if (intersection == null && DtUtils.PointInPolygon(center, verts, verts.Length / 3))
|
if (intersection == null && DtUtils.PointInPolygon(center, verts, verts.Length / 3))
|
||||||
{
|
{
|
||||||
// circle inside polygon
|
// circle inside polygon
|
||||||
return qCircle;
|
return qCircle.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
return intersection;
|
return intersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private float[] Circle(RcVec3f center, float radius)
|
|
||||||
{
|
|
||||||
float[] circle = new float[12 * 3];
|
|
||||||
for (int i = 0; i < CIRCLE_SEGMENTS * 3; i += 3)
|
|
||||||
{
|
|
||||||
circle[i] = UnitCircle[i] * radius + center.X;
|
|
||||||
circle[i + 1] = center.Y;
|
|
||||||
circle[i + 2] = UnitCircle[i + 2] * radius + center.Z;
|
|
||||||
}
|
|
||||||
|
|
||||||
return circle;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,13 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using DotRecast.Core;
|
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
public static class DtUtils
|
public static class DtUtils
|
||||||
{
|
{
|
||||||
private static readonly float EQUAL_THRESHOLD = RcMath.Sqr(1.0f / 16384.0f);
|
|
||||||
|
|
||||||
public static int NextPow2(int v)
|
public static int NextPow2(int v)
|
||||||
{
|
{
|
||||||
v--;
|
v--;
|
||||||
|
@ -39,24 +36,6 @@ namespace DotRecast.Detour
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs a 'sloppy' colocation check of the specified points.
|
|
||||||
/// @param[in] p0 A point. [(x, y, z)]
|
|
||||||
/// @param[in] p1 A point. [(x, y, z)]
|
|
||||||
/// @return True if the points are considered to be at the same location.
|
|
||||||
///
|
|
||||||
/// Basically, this function will return true if the specified points are
|
|
||||||
/// close enough to eachother to be considered colocated.
|
|
||||||
public static bool VEqual(RcVec3f p0, RcVec3f p1)
|
|
||||||
{
|
|
||||||
return VEqual(p0, p1, EQUAL_THRESHOLD);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool VEqual(RcVec3f p0, RcVec3f p1, float thresholdSqr)
|
|
||||||
{
|
|
||||||
float d = RcVec3f.DistanceSquared(p0, p1);
|
|
||||||
return d < thresholdSqr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Determines if two axis-aligned bounding boxes overlap.
|
/// Determines if two axis-aligned bounding boxes overlap.
|
||||||
/// @param[in] amin Minimum bounds of box A. [(x, y, z)]
|
/// @param[in] amin Minimum bounds of box A. [(x, y, z)]
|
||||||
/// @param[in] amax Maximum bounds of box A. [(x, y, z)]
|
/// @param[in] amax Maximum bounds of box A. [(x, y, z)]
|
||||||
|
@ -64,12 +43,12 @@ namespace DotRecast.Detour
|
||||||
/// @param[in] bmax Maximum bounds of box B. [(x, y, z)]
|
/// @param[in] bmax Maximum bounds of box B. [(x, y, z)]
|
||||||
/// @return True if the two AABB's overlap.
|
/// @return True if the two AABB's overlap.
|
||||||
/// @see dtOverlapBounds
|
/// @see dtOverlapBounds
|
||||||
public static bool OverlapQuantBounds(Span<int> amin, Span<int> amax, Span<int> bmin, Span<int> bmax)
|
public static bool OverlapQuantBounds(ref RcVec3i amin, ref RcVec3i amax, ref RcVec3i bmin, ref RcVec3i bmax)
|
||||||
{
|
{
|
||||||
bool overlap = true;
|
bool overlap = true;
|
||||||
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
|
overlap = (amin.X > bmax.X || amax.X < bmin.X) ? false : overlap;
|
||||||
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
|
overlap = (amin.Y > bmax.Y || amax.Y < bmin.Y) ? false : overlap;
|
||||||
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
|
overlap = (amin.Z > bmax.Z || amax.Z < bmin.Z) ? false : overlap;
|
||||||
return overlap;
|
return overlap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +76,7 @@ namespace DotRecast.Detour
|
||||||
/// @par
|
/// @par
|
||||||
///
|
///
|
||||||
/// All vertices are projected onto the xz-plane, so the y-values are ignored.
|
/// All vertices are projected onto the xz-plane, so the y-values are ignored.
|
||||||
public static bool OverlapPolyPoly2D(float[] polya, int npolya, float[] polyb, int npolyb)
|
public static bool OverlapPolyPoly2D(Span<float> polya, int npolya, Span<float> polyb, int npolyb)
|
||||||
{
|
{
|
||||||
const float eps = 1e-4f;
|
const float eps = 1e-4f;
|
||||||
for (int i = 0, j = npolya - 1; i < npolya; j = i++)
|
for (int i = 0, j = npolya - 1; i < npolya; j = i++)
|
||||||
|
@ -145,7 +124,7 @@ namespace DotRecast.Detour
|
||||||
/// @param[in] b Vertex B. [(x, y, z)]
|
/// @param[in] b Vertex B. [(x, y, z)]
|
||||||
/// @param[in] c Vertex C. [(x, y, z)]
|
/// @param[in] c Vertex C. [(x, y, z)]
|
||||||
/// @return The signed xz-plane area of the triangle.
|
/// @return The signed xz-plane area of the triangle.
|
||||||
public static float TriArea2D(float[] verts, int a, int b, int c)
|
public static float TriArea2D(Span<float> verts, int a, int b, int c)
|
||||||
{
|
{
|
||||||
float abx = verts[b] - verts[a];
|
float abx = verts[b] - verts[a];
|
||||||
float abz = verts[b + 2] - verts[a + 2];
|
float abz = verts[b + 2] - verts[a + 2];
|
||||||
|
@ -165,7 +144,7 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
// Returns a random point in a convex polygon.
|
// Returns a random point in a convex polygon.
|
||||||
// Adapted from Graphics Gems article.
|
// Adapted from Graphics Gems article.
|
||||||
public static RcVec3f RandomPointInConvexPoly(float[] pts, int npts, float[] areas, float s, float t)
|
public static void RandomPointInConvexPoly(Span<float> pts, int npts, Span<float> areas, float s, float t, out RcVec3f @out)
|
||||||
{
|
{
|
||||||
// Calc triangle araes
|
// Calc triangle araes
|
||||||
float areasum = 0.0f;
|
float areasum = 0.0f;
|
||||||
|
@ -202,7 +181,7 @@ namespace DotRecast.Detour
|
||||||
int pb = (tri - 1) * 3;
|
int pb = (tri - 1) * 3;
|
||||||
int pc = tri * 3;
|
int pc = tri * 3;
|
||||||
|
|
||||||
return new RcVec3f()
|
@out = new RcVec3f()
|
||||||
{
|
{
|
||||||
X = a * pts[pa] + b * pts[pb] + c * pts[pc],
|
X = a * pts[pa] + b * pts[pb] + c * pts[pc],
|
||||||
Y = a * pts[pa + 1] + b * pts[pb + 1] + c * pts[pc + 1],
|
Y = a * pts[pa + 1] + b * pts[pb + 1] + c * pts[pc + 1],
|
||||||
|
@ -246,13 +225,13 @@ namespace DotRecast.Detour
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RcVec2f ProjectPoly(RcVec3f axis, float[] poly, int npoly)
|
public static RcVec2f ProjectPoly(RcVec3f axis, Span<float> poly, int npoly)
|
||||||
{
|
{
|
||||||
float rmin, rmax;
|
float rmin, rmax;
|
||||||
rmin = rmax = axis.Dot2D(poly, 0);
|
rmin = rmax = axis.Dot2D(new RcVec3f(poly));
|
||||||
for (int i = 1; i < npoly; ++i)
|
for (int i = 1; i < npoly; ++i)
|
||||||
{
|
{
|
||||||
float d = axis.Dot2D(poly, i * 3);
|
float d = axis.Dot2D(RcVec.Create(poly, i * 3));
|
||||||
rmin = Math.Min(rmin, d);
|
rmin = Math.Min(rmin, d);
|
||||||
rmax = Math.Max(rmax, d);
|
rmax = Math.Max(rmax, d);
|
||||||
}
|
}
|
||||||
|
@ -267,7 +246,7 @@ namespace DotRecast.Detour
|
||||||
/// @par
|
/// @par
|
||||||
///
|
///
|
||||||
/// All points are projected onto the xz-plane, so the y-values are ignored.
|
/// All points are projected onto the xz-plane, so the y-values are ignored.
|
||||||
public static bool PointInPolygon(RcVec3f pt, float[] verts, int nverts)
|
public static bool PointInPolygon(RcVec3f pt, Span<float> verts, int nverts)
|
||||||
{
|
{
|
||||||
// TODO: Replace pnpoly with triArea2D tests?
|
// TODO: Replace pnpoly with triArea2D tests?
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -286,7 +265,7 @@ namespace DotRecast.Detour
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool DistancePtPolyEdgesSqr(RcVec3f pt, float[] verts, int nverts, float[] ed, float[] et)
|
public static bool DistancePtPolyEdgesSqr(RcVec3f pt, Span<float> verts, int nverts, Span<float> ed, Span<float> et)
|
||||||
{
|
{
|
||||||
// TODO: Replace pnpoly with triArea2D tests?
|
// TODO: Replace pnpoly with triArea2D tests?
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -307,10 +286,10 @@ namespace DotRecast.Detour
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float DistancePtSegSqr2D(RcVec3f pt, float[] verts, int p, int q, out float t)
|
public static float DistancePtSegSqr2D(RcVec3f pt, Span<float> verts, int p, int q, out float t)
|
||||||
{
|
{
|
||||||
var vp = RcVecUtils.Create(verts, p);
|
var vp = RcVec.Create(verts, p);
|
||||||
var vq = RcVecUtils.Create(verts, q);
|
var vq = RcVec.Create(verts, q);
|
||||||
return DistancePtSegSqr2D(pt, vp, vq, out t);
|
return DistancePtSegSqr2D(pt, vp, vq, out t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,7 +321,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IntersectSegmentPoly2D(RcVec3f p0, RcVec3f p1,
|
public static bool IntersectSegmentPoly2D(RcVec3f p0, RcVec3f p1,
|
||||||
RcVec3f[] verts, int nverts,
|
Span<RcVec3f> verts, int nverts,
|
||||||
out float tmin, out float tmax,
|
out float tmin, out float tmax,
|
||||||
out int segMin, out int segMax)
|
out int segMin, out int segMax)
|
||||||
{
|
{
|
||||||
|
@ -362,8 +341,8 @@ namespace DotRecast.Detour
|
||||||
RcVec3f vpi = verts[i];
|
RcVec3f vpi = verts[i];
|
||||||
var edge = RcVec3f.Subtract(vpi, vpj);
|
var edge = RcVec3f.Subtract(vpi, vpj);
|
||||||
var diff = RcVec3f.Subtract(p0v, vpj);
|
var diff = RcVec3f.Subtract(p0v, vpj);
|
||||||
float n = RcVecUtils.Perp2D(edge, diff);
|
float n = RcVec.Perp2D(edge, diff);
|
||||||
float d = RcVecUtils.Perp2D(dir, edge);
|
float d = RcVec.Perp2D(dir, edge);
|
||||||
if (MathF.Abs(d) < EPS)
|
if (MathF.Abs(d) < EPS)
|
||||||
{
|
{
|
||||||
// S is nearly parallel to this edge
|
// S is nearly parallel to this edge
|
||||||
|
@ -425,14 +404,14 @@ namespace DotRecast.Detour
|
||||||
RcVec3f u = RcVec3f.Subtract(aq, ap);
|
RcVec3f u = RcVec3f.Subtract(aq, ap);
|
||||||
RcVec3f v = RcVec3f.Subtract(bq, bp);
|
RcVec3f v = RcVec3f.Subtract(bq, bp);
|
||||||
RcVec3f w = RcVec3f.Subtract(ap, bp);
|
RcVec3f w = RcVec3f.Subtract(ap, bp);
|
||||||
float d = RcVecUtils.PerpXZ(u, v);
|
float d = RcVec.PerpXZ(u, v);
|
||||||
if (MathF.Abs(d) < 1e-6f)
|
if (MathF.Abs(d) < 1e-6f)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = RcVecUtils.PerpXZ(v, w) / d;
|
s = RcVec.PerpXZ(v, w) / d;
|
||||||
t = RcVecUtils.PerpXZ(u, w) / d;
|
t = RcVec.PerpXZ(u, w) / d;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
/// Provides custom polygon query behavior.
|
||||||
|
/// Used by dtNavMeshQuery::queryPolygons.
|
||||||
|
/// @ingroup detour
|
||||||
public interface IDtPolyQuery
|
public interface IDtPolyQuery
|
||||||
{
|
{
|
||||||
void Process(DtMeshTile tile, DtPoly poly, long refs);
|
/// Called for each batch of unique polygons touched by the search area in dtNavMeshQuery::queryPolygons.
|
||||||
|
/// This can be called multiple times for a single query.
|
||||||
|
void Process(DtMeshTile tile, DtPoly[] poly, Span<long> refs, int count);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
|
|
@ -21,13 +21,17 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Io
|
namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
|
using static DtDetour;
|
||||||
|
|
||||||
public class DtMeshDataReader
|
public class DtMeshDataReader
|
||||||
{
|
{
|
||||||
public const int DT_POLY_DETAIL_SIZE = 10;
|
public const int DT_POLY_DETAIL_SIZE = 10;
|
||||||
|
public const int LINK_SIZEOF = 16;
|
||||||
|
public const int LINK_SIZEOF32BIT = 12;
|
||||||
|
|
||||||
public DtMeshData Read(BinaryReader stream, int maxVertPerPoly)
|
public DtMeshData Read(BinaryReader stream, int maxVertPerPoly)
|
||||||
{
|
{
|
||||||
RcByteBuffer buf = IOUtils.ToByteBuffer(stream);
|
RcByteBuffer buf = RcIO.ToByteBuffer(stream);
|
||||||
return Read(buf, maxVertPerPoly, false);
|
return Read(buf, maxVertPerPoly, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +42,7 @@ namespace DotRecast.Detour.Io
|
||||||
|
|
||||||
public DtMeshData Read32Bit(BinaryReader stream, int maxVertPerPoly)
|
public DtMeshData Read32Bit(BinaryReader stream, int maxVertPerPoly)
|
||||||
{
|
{
|
||||||
RcByteBuffer buf = IOUtils.ToByteBuffer(stream);
|
RcByteBuffer buf = RcIO.ToByteBuffer(stream);
|
||||||
return Read(buf, maxVertPerPoly, true);
|
return Read(buf, maxVertPerPoly, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,10 +57,10 @@ namespace DotRecast.Detour.Io
|
||||||
DtMeshHeader header = new DtMeshHeader();
|
DtMeshHeader header = new DtMeshHeader();
|
||||||
data.header = header;
|
data.header = header;
|
||||||
header.magic = buf.GetInt();
|
header.magic = buf.GetInt();
|
||||||
if (header.magic != DtNavMesh.DT_NAVMESH_MAGIC)
|
if (header.magic != DT_NAVMESH_MAGIC)
|
||||||
{
|
{
|
||||||
header.magic = IOUtils.SwapEndianness(header.magic);
|
header.magic = RcIO.SwapEndianness(header.magic);
|
||||||
if (header.magic != DtNavMesh.DT_NAVMESH_MAGIC)
|
if (header.magic != DT_NAVMESH_MAGIC)
|
||||||
{
|
{
|
||||||
throw new IOException("Invalid magic");
|
throw new IOException("Invalid magic");
|
||||||
}
|
}
|
||||||
|
@ -65,16 +69,16 @@ namespace DotRecast.Detour.Io
|
||||||
}
|
}
|
||||||
|
|
||||||
header.version = buf.GetInt();
|
header.version = buf.GetInt();
|
||||||
if (header.version != DtNavMesh.DT_NAVMESH_VERSION)
|
if (header.version != DT_NAVMESH_VERSION)
|
||||||
{
|
{
|
||||||
if (header.version < DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_FIRST
|
if (header.version < DT_NAVMESH_VERSION_RECAST4J_FIRST
|
||||||
|| header.version > DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_LAST)
|
|| header.version > DT_NAVMESH_VERSION_RECAST4J_LAST)
|
||||||
{
|
{
|
||||||
throw new IOException("Invalid version " + header.version);
|
throw new IOException("Invalid version " + header.version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cCompatibility = header.version == DtNavMesh.DT_NAVMESH_VERSION;
|
bool cCompatibility = header.version == DT_NAVMESH_VERSION;
|
||||||
header.x = buf.GetInt();
|
header.x = buf.GetInt();
|
||||||
header.y = buf.GetInt();
|
header.y = buf.GetInt();
|
||||||
header.layer = buf.GetInt();
|
header.layer = buf.GetInt();
|
||||||
|
@ -116,8 +120,6 @@ namespace DotRecast.Detour.Io
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public const int LINK_SIZEOF = 16;
|
|
||||||
public const int LINK_SIZEOF32BIT = 12;
|
|
||||||
|
|
||||||
public static int GetSizeofLink(bool is32Bit)
|
public static int GetSizeofLink(bool is32Bit)
|
||||||
{
|
{
|
||||||
|
@ -141,7 +143,7 @@ namespace DotRecast.Detour.Io
|
||||||
for (int i = 0; i < polys.Length; i++)
|
for (int i = 0; i < polys.Length; i++)
|
||||||
{
|
{
|
||||||
polys[i] = new DtPoly(i, maxVertPerPoly);
|
polys[i] = new DtPoly(i, maxVertPerPoly);
|
||||||
if (header.version < DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_NO_POLY_FIRSTLINK)
|
if (header.version < DT_NAVMESH_VERSION_RECAST4J_NO_POLY_FIRSTLINK)
|
||||||
{
|
{
|
||||||
buf.GetInt(); // polys[i].firstLink
|
buf.GetInt(); // polys[i].firstLink
|
||||||
}
|
}
|
||||||
|
@ -171,8 +173,8 @@ namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
int vertBase = buf.GetInt();
|
int vertBase = buf.GetInt();
|
||||||
int triBase = buf.GetInt();
|
int triBase = buf.GetInt();
|
||||||
int vertCount = buf.Get() & 0xFF;
|
byte vertCount = (byte)(buf.Get() & 0xFF);
|
||||||
int triCount = buf.Get() & 0xFF;
|
byte triCount = (byte)(buf.Get() & 0xFF);
|
||||||
polys[i] = new DtPolyDetail(vertBase, triBase, vertCount, triCount);
|
polys[i] = new DtPolyDetail(vertBase, triBase, vertCount, triCount);
|
||||||
if (cCompatibility)
|
if (cCompatibility)
|
||||||
{
|
{
|
||||||
|
@ -200,29 +202,25 @@ namespace DotRecast.Detour.Io
|
||||||
for (int i = 0; i < nodes.Length; i++)
|
for (int i = 0; i < nodes.Length; i++)
|
||||||
{
|
{
|
||||||
nodes[i] = new DtBVNode();
|
nodes[i] = new DtBVNode();
|
||||||
if (header.version < DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_32BIT_BVTREE)
|
if (header.version < DT_NAVMESH_VERSION_RECAST4J_32BIT_BVTREE)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < 3; j++)
|
nodes[i].bmin.X = buf.GetShort() & 0xFFFF;
|
||||||
{
|
nodes[i].bmin.Y = buf.GetShort() & 0xFFFF;
|
||||||
nodes[i].bmin[j] = buf.GetShort() & 0xFFFF;
|
nodes[i].bmin.Z = buf.GetShort() & 0xFFFF;
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < 3; j++)
|
nodes[i].bmax.X = buf.GetShort() & 0xFFFF;
|
||||||
{
|
nodes[i].bmax.Y = buf.GetShort() & 0xFFFF;
|
||||||
nodes[i].bmax[j] = buf.GetShort() & 0xFFFF;
|
nodes[i].bmax.Z = buf.GetShort() & 0xFFFF;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int j = 0; j < 3; j++)
|
nodes[i].bmin.X = buf.GetInt();
|
||||||
{
|
nodes[i].bmin.Y = buf.GetInt();
|
||||||
nodes[i].bmin[j] = buf.GetInt();
|
nodes[i].bmin.Z = buf.GetInt();
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < 3; j++)
|
nodes[i].bmax.X = buf.GetInt();
|
||||||
{
|
nodes[i].bmax.Y = buf.GetInt();
|
||||||
nodes[i].bmax[j] = buf.GetInt();
|
nodes[i].bmax.Z = buf.GetInt();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes[i].i = buf.GetInt();
|
nodes[i].i = buf.GetInt();
|
||||||
|
|
|
@ -21,36 +21,38 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Io
|
namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
public class DtMeshDataWriter : DtWriter
|
using static DtDetour;
|
||||||
|
|
||||||
|
public class DtMeshDataWriter
|
||||||
{
|
{
|
||||||
public void Write(BinaryWriter stream, DtMeshData data, RcByteOrder order, bool cCompatibility)
|
public void Write(BinaryWriter stream, DtMeshData data, RcByteOrder order, bool cCompatibility)
|
||||||
{
|
{
|
||||||
DtMeshHeader header = data.header;
|
DtMeshHeader header = data.header;
|
||||||
Write(stream, header.magic, order);
|
RcIO.Write(stream, header.magic, order);
|
||||||
Write(stream, cCompatibility ? DtNavMesh.DT_NAVMESH_VERSION : DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_LAST, order);
|
RcIO.Write(stream, cCompatibility ? DT_NAVMESH_VERSION : DT_NAVMESH_VERSION_RECAST4J_LAST, order);
|
||||||
Write(stream, header.x, order);
|
RcIO.Write(stream, header.x, order);
|
||||||
Write(stream, header.y, order);
|
RcIO.Write(stream, header.y, order);
|
||||||
Write(stream, header.layer, order);
|
RcIO.Write(stream, header.layer, order);
|
||||||
Write(stream, header.userId, order);
|
RcIO.Write(stream, header.userId, order);
|
||||||
Write(stream, header.polyCount, order);
|
RcIO.Write(stream, header.polyCount, order);
|
||||||
Write(stream, header.vertCount, order);
|
RcIO.Write(stream, header.vertCount, order);
|
||||||
Write(stream, header.maxLinkCount, order);
|
RcIO.Write(stream, header.maxLinkCount, order);
|
||||||
Write(stream, header.detailMeshCount, order);
|
RcIO.Write(stream, header.detailMeshCount, order);
|
||||||
Write(stream, header.detailVertCount, order);
|
RcIO.Write(stream, header.detailVertCount, order);
|
||||||
Write(stream, header.detailTriCount, order);
|
RcIO.Write(stream, header.detailTriCount, order);
|
||||||
Write(stream, header.bvNodeCount, order);
|
RcIO.Write(stream, header.bvNodeCount, order);
|
||||||
Write(stream, header.offMeshConCount, order);
|
RcIO.Write(stream, header.offMeshConCount, order);
|
||||||
Write(stream, header.offMeshBase, order);
|
RcIO.Write(stream, header.offMeshBase, order);
|
||||||
Write(stream, header.walkableHeight, order);
|
RcIO.Write(stream, header.walkableHeight, order);
|
||||||
Write(stream, header.walkableRadius, order);
|
RcIO.Write(stream, header.walkableRadius, order);
|
||||||
Write(stream, header.walkableClimb, order);
|
RcIO.Write(stream, header.walkableClimb, order);
|
||||||
Write(stream, header.bmin.X, order);
|
RcIO.Write(stream, header.bmin.X, order);
|
||||||
Write(stream, header.bmin.Y, order);
|
RcIO.Write(stream, header.bmin.Y, order);
|
||||||
Write(stream, header.bmin.Z, order);
|
RcIO.Write(stream, header.bmin.Z, order);
|
||||||
Write(stream, header.bmax.X, order);
|
RcIO.Write(stream, header.bmax.X, order);
|
||||||
Write(stream, header.bmax.Y, order);
|
RcIO.Write(stream, header.bmax.Y, order);
|
||||||
Write(stream, header.bmax.Z, order);
|
RcIO.Write(stream, header.bmax.Z, order);
|
||||||
Write(stream, header.bvQuantFactor, order);
|
RcIO.Write(stream, header.bvQuantFactor, order);
|
||||||
WriteVerts(stream, data.verts, header.vertCount, order);
|
WriteVerts(stream, data.verts, header.vertCount, order);
|
||||||
WritePolys(stream, data, order, cCompatibility);
|
WritePolys(stream, data, order, cCompatibility);
|
||||||
if (cCompatibility)
|
if (cCompatibility)
|
||||||
|
@ -70,7 +72,7 @@ namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count * 3; i++)
|
for (int i = 0; i < count * 3; i++)
|
||||||
{
|
{
|
||||||
Write(stream, verts[i], order);
|
RcIO.Write(stream, verts[i], order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,22 +82,22 @@ namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
if (cCompatibility)
|
if (cCompatibility)
|
||||||
{
|
{
|
||||||
Write(stream, 0xFFFF, order);
|
RcIO.Write(stream, 0xFFFF, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < data.polys[i].verts.Length; j++)
|
for (int j = 0; j < data.polys[i].verts.Length; j++)
|
||||||
{
|
{
|
||||||
Write(stream, (short)data.polys[i].verts[j], order);
|
RcIO.Write(stream, (short)data.polys[i].verts[j], order);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < data.polys[i].neis.Length; j++)
|
for (int j = 0; j < data.polys[i].neis.Length; j++)
|
||||||
{
|
{
|
||||||
Write(stream, (short)data.polys[i].neis[j], order);
|
RcIO.Write(stream, (short)data.polys[i].neis[j], order);
|
||||||
}
|
}
|
||||||
|
|
||||||
Write(stream, (short)data.polys[i].flags, order);
|
RcIO.Write(stream, (short)data.polys[i].flags, order);
|
||||||
Write(stream, (byte)data.polys[i].vertCount);
|
RcIO.Write(stream, (byte)data.polys[i].vertCount);
|
||||||
Write(stream, (byte)data.polys[i].areaAndtype);
|
RcIO.Write(stream, (byte)data.polys[i].areaAndtype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,13 +105,13 @@ namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
for (int i = 0; i < data.header.detailMeshCount; i++)
|
for (int i = 0; i < data.header.detailMeshCount; i++)
|
||||||
{
|
{
|
||||||
Write(stream, data.detailMeshes[i].vertBase, order);
|
RcIO.Write(stream, data.detailMeshes[i].vertBase, order);
|
||||||
Write(stream, data.detailMeshes[i].triBase, order);
|
RcIO.Write(stream, data.detailMeshes[i].triBase, order);
|
||||||
Write(stream, (byte)data.detailMeshes[i].vertCount);
|
RcIO.Write(stream, (byte)data.detailMeshes[i].vertCount);
|
||||||
Write(stream, (byte)data.detailMeshes[i].triCount);
|
RcIO.Write(stream, (byte)data.detailMeshes[i].triCount);
|
||||||
if (cCompatibility)
|
if (cCompatibility)
|
||||||
{
|
{
|
||||||
Write(stream, (short)0, order);
|
RcIO.Write(stream, (short)0, order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,7 +120,7 @@ namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
for (int i = 0; i < data.header.detailTriCount * 4; i++)
|
for (int i = 0; i < data.header.detailTriCount * 4; i++)
|
||||||
{
|
{
|
||||||
Write(stream, (byte)data.detailTris[i]);
|
RcIO.Write(stream, (byte)data.detailTris[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,30 +130,26 @@ namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
if (cCompatibility)
|
if (cCompatibility)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < 3; j++)
|
RcIO.Write(stream, (short)data.bvTree[i].bmin.X, order);
|
||||||
{
|
RcIO.Write(stream, (short)data.bvTree[i].bmin.Y, order);
|
||||||
Write(stream, (short)data.bvTree[i].bmin[j], order);
|
RcIO.Write(stream, (short)data.bvTree[i].bmin.Z, order);
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < 3; j++)
|
RcIO.Write(stream, (short)data.bvTree[i].bmax.X, order);
|
||||||
{
|
RcIO.Write(stream, (short)data.bvTree[i].bmax.Y, order);
|
||||||
Write(stream, (short)data.bvTree[i].bmax[j], order);
|
RcIO.Write(stream, (short)data.bvTree[i].bmax.Z, order);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int j = 0; j < 3; j++)
|
RcIO.Write(stream, data.bvTree[i].bmin.X, order);
|
||||||
{
|
RcIO.Write(stream, data.bvTree[i].bmin.Y, order);
|
||||||
Write(stream, data.bvTree[i].bmin[j], order);
|
RcIO.Write(stream, data.bvTree[i].bmin.Z, order);
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < 3; j++)
|
RcIO.Write(stream, data.bvTree[i].bmax.X, order);
|
||||||
{
|
RcIO.Write(stream, data.bvTree[i].bmax.Y, order);
|
||||||
Write(stream, data.bvTree[i].bmax[j], order);
|
RcIO.Write(stream, data.bvTree[i].bmax.Z, order);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Write(stream, data.bvTree[i].i, order);
|
RcIO.Write(stream, data.bvTree[i].i, order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,16 +159,16 @@ namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
for (int j = 0; j < 2; j++)
|
for (int j = 0; j < 2; j++)
|
||||||
{
|
{
|
||||||
Write(stream, data.offMeshCons[i].pos[j].X, order);
|
RcIO.Write(stream, data.offMeshCons[i].pos[j].X, order);
|
||||||
Write(stream, data.offMeshCons[i].pos[j].Y, order);
|
RcIO.Write(stream, data.offMeshCons[i].pos[j].Y, order);
|
||||||
Write(stream, data.offMeshCons[i].pos[j].Z, order);
|
RcIO.Write(stream, data.offMeshCons[i].pos[j].Z, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
Write(stream, data.offMeshCons[i].rad, order);
|
RcIO.Write(stream, data.offMeshCons[i].rad, order);
|
||||||
Write(stream, (short)data.offMeshCons[i].poly, order);
|
RcIO.Write(stream, (short)data.offMeshCons[i].poly, order);
|
||||||
Write(stream, (byte)data.offMeshCons[i].flags);
|
RcIO.Write(stream, (byte)data.offMeshCons[i].flags);
|
||||||
Write(stream, (byte)data.offMeshCons[i].side);
|
RcIO.Write(stream, (byte)data.offMeshCons[i].side);
|
||||||
Write(stream, data.offMeshCons[i].userId, order);
|
RcIO.Write(stream, data.offMeshCons[i].userId, order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Io
|
namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
|
using static DtDetour;
|
||||||
|
|
||||||
public class DtMeshSetReader
|
public class DtMeshSetReader
|
||||||
{
|
{
|
||||||
private readonly DtMeshDataReader meshReader = new DtMeshDataReader();
|
private readonly DtMeshDataReader meshReader = new DtMeshDataReader();
|
||||||
|
@ -29,7 +31,7 @@ namespace DotRecast.Detour.Io
|
||||||
|
|
||||||
public DtNavMesh Read(BinaryReader @is, int maxVertPerPoly)
|
public DtNavMesh Read(BinaryReader @is, int maxVertPerPoly)
|
||||||
{
|
{
|
||||||
return Read(IOUtils.ToByteBuffer(@is), maxVertPerPoly, false);
|
return Read(RcIO.ToByteBuffer(@is), maxVertPerPoly, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtNavMesh Read(RcByteBuffer bb, int maxVertPerPoly)
|
public DtNavMesh Read(RcByteBuffer bb, int maxVertPerPoly)
|
||||||
|
@ -39,7 +41,7 @@ namespace DotRecast.Detour.Io
|
||||||
|
|
||||||
public DtNavMesh Read32Bit(BinaryReader @is, int maxVertPerPoly)
|
public DtNavMesh Read32Bit(BinaryReader @is, int maxVertPerPoly)
|
||||||
{
|
{
|
||||||
return Read(IOUtils.ToByteBuffer(@is), maxVertPerPoly, true);
|
return Read(RcIO.ToByteBuffer(@is), maxVertPerPoly, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtNavMesh Read32Bit(RcByteBuffer bb, int maxVertPerPoly)
|
public DtNavMesh Read32Bit(RcByteBuffer bb, int maxVertPerPoly)
|
||||||
|
@ -49,7 +51,7 @@ namespace DotRecast.Detour.Io
|
||||||
|
|
||||||
public DtNavMesh Read(BinaryReader @is)
|
public DtNavMesh Read(BinaryReader @is)
|
||||||
{
|
{
|
||||||
return Read(IOUtils.ToByteBuffer(@is));
|
return Read(RcIO.ToByteBuffer(@is));
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtNavMesh Read(RcByteBuffer bb)
|
public DtNavMesh Read(RcByteBuffer bb)
|
||||||
|
@ -66,7 +68,8 @@ namespace DotRecast.Detour.Io
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cCompatibility = header.version == NavMeshSetHeader.NAVMESHSET_VERSION;
|
bool cCompatibility = header.version == NavMeshSetHeader.NAVMESHSET_VERSION;
|
||||||
DtNavMesh mesh = new DtNavMesh(header.option, header.maxVertsPerPoly);
|
DtNavMesh mesh = new DtNavMesh();
|
||||||
|
mesh.Init(header.option, header.maxVertsPerPoly);
|
||||||
ReadTiles(bb, is32Bit, ref header, cCompatibility, mesh);
|
ReadTiles(bb, is32Bit, ref header, cCompatibility, mesh);
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +80,7 @@ namespace DotRecast.Detour.Io
|
||||||
header.magic = bb.GetInt();
|
header.magic = bb.GetInt();
|
||||||
if (header.magic != NavMeshSetHeader.NAVMESHSET_MAGIC)
|
if (header.magic != NavMeshSetHeader.NAVMESHSET_MAGIC)
|
||||||
{
|
{
|
||||||
header.magic = IOUtils.SwapEndianness(header.magic);
|
header.magic = RcIO.SwapEndianness(header.magic);
|
||||||
if (header.magic != NavMeshSetHeader.NAVMESHSET_MAGIC)
|
if (header.magic != NavMeshSetHeader.NAVMESHSET_MAGIC)
|
||||||
{
|
{
|
||||||
throw new IOException("Invalid magic " + header.magic);
|
throw new IOException("Invalid magic " + header.magic);
|
||||||
|
@ -131,7 +134,7 @@ namespace DotRecast.Detour.Io
|
||||||
}
|
}
|
||||||
|
|
||||||
DtMeshData data = meshReader.Read(bb, mesh.GetMaxVertsPerPoly(), is32Bit);
|
DtMeshData data = meshReader.Read(bb, mesh.GetMaxVertsPerPoly(), is32Bit);
|
||||||
mesh.AddTile(data, i, tileHeader.tileRef);
|
mesh.AddTile(data, i, tileHeader.tileRef, out _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +150,7 @@ namespace DotRecast.Detour.Io
|
||||||
int salt = ((refs >> (m_polyBits + m_tileBits)) & saltMask);
|
int salt = ((refs >> (m_polyBits + m_tileBits)) & saltMask);
|
||||||
int it = ((refs >> m_polyBits) & tileMask);
|
int it = ((refs >> m_polyBits) & tileMask);
|
||||||
int ip = refs & polyMask;
|
int ip = refs & polyMask;
|
||||||
return DtNavMesh.EncodePolyId(salt, it, ip);
|
return EncodePolyId(salt, it, ip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Io
|
namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
public class DtMeshSetWriter : DtWriter
|
public class DtMeshSetWriter
|
||||||
{
|
{
|
||||||
private readonly DtMeshDataWriter writer = new DtMeshDataWriter();
|
private readonly DtMeshDataWriter writer = new DtMeshDataWriter();
|
||||||
private readonly DtNavMeshParamWriter paramWriter = new DtNavMeshParamWriter();
|
private readonly DtNavMeshParamWriter paramWriter = new DtNavMeshParamWriter();
|
||||||
|
@ -35,8 +35,8 @@ namespace DotRecast.Detour.Io
|
||||||
|
|
||||||
private void WriteHeader(BinaryWriter stream, DtNavMesh mesh, RcByteOrder order, bool cCompatibility)
|
private void WriteHeader(BinaryWriter stream, DtNavMesh mesh, RcByteOrder order, bool cCompatibility)
|
||||||
{
|
{
|
||||||
Write(stream, NavMeshSetHeader.NAVMESHSET_MAGIC, order);
|
RcIO.Write(stream, NavMeshSetHeader.NAVMESHSET_MAGIC, order);
|
||||||
Write(stream, cCompatibility ? NavMeshSetHeader.NAVMESHSET_VERSION : NavMeshSetHeader.NAVMESHSET_VERSION_RECAST4J, order);
|
RcIO.Write(stream, cCompatibility ? NavMeshSetHeader.NAVMESHSET_VERSION : NavMeshSetHeader.NAVMESHSET_VERSION_RECAST4J, order);
|
||||||
int numTiles = 0;
|
int numTiles = 0;
|
||||||
for (int i = 0; i < mesh.GetMaxTiles(); ++i)
|
for (int i = 0; i < mesh.GetMaxTiles(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -49,11 +49,11 @@ namespace DotRecast.Detour.Io
|
||||||
numTiles++;
|
numTiles++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Write(stream, numTiles, order);
|
RcIO.Write(stream, numTiles, order);
|
||||||
paramWriter.Write(stream, mesh.GetParams(), order);
|
paramWriter.Write(stream, mesh.GetParams(), order);
|
||||||
if (!cCompatibility)
|
if (!cCompatibility)
|
||||||
{
|
{
|
||||||
Write(stream, mesh.GetMaxVertsPerPoly(), order);
|
RcIO.Write(stream, mesh.GetMaxVertsPerPoly(), order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,11 +77,11 @@ namespace DotRecast.Detour.Io
|
||||||
|
|
||||||
byte[] ba = msw.ToArray();
|
byte[] ba = msw.ToArray();
|
||||||
tileHeader.dataSize = ba.Length;
|
tileHeader.dataSize = ba.Length;
|
||||||
Write(stream, tileHeader.tileRef, order);
|
RcIO.Write(stream, tileHeader.tileRef, order);
|
||||||
Write(stream, tileHeader.dataSize, order);
|
RcIO.Write(stream, tileHeader.dataSize, order);
|
||||||
if (cCompatibility)
|
if (cCompatibility)
|
||||||
{
|
{
|
||||||
Write(stream, 0, order); // C struct padding
|
RcIO.Write(stream, 0, order); // C struct padding
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.Write(ba);
|
stream.Write(ba);
|
||||||
|
|
|
@ -4,17 +4,17 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Io
|
namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
public class DtNavMeshParamWriter : DtWriter
|
public class DtNavMeshParamWriter
|
||||||
{
|
{
|
||||||
public void Write(BinaryWriter stream, DtNavMeshParams option, RcByteOrder order)
|
public void Write(BinaryWriter stream, DtNavMeshParams option, RcByteOrder order)
|
||||||
{
|
{
|
||||||
Write(stream, option.orig.X, order);
|
RcIO.Write(stream, option.orig.X, order);
|
||||||
Write(stream, option.orig.Y, order);
|
RcIO.Write(stream, option.orig.Y, order);
|
||||||
Write(stream, option.orig.Z, order);
|
RcIO.Write(stream, option.orig.Z, order);
|
||||||
Write(stream, option.tileWidth, order);
|
RcIO.Write(stream, option.tileWidth, order);
|
||||||
Write(stream, option.tileHeight, order);
|
RcIO.Write(stream, option.tileHeight, order);
|
||||||
Write(stream, option.maxTiles, order);
|
RcIO.Write(stream, option.maxTiles, order);
|
||||||
Write(stream, option.maxPolys, order);
|
RcIO.Write(stream, option.maxPolys, order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,98 +0,0 @@
|
||||||
/*
|
|
||||||
Recast4J Copyright (c) 2015 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.IO;
|
|
||||||
using DotRecast.Core;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour.Io
|
|
||||||
{
|
|
||||||
public abstract class DtWriter
|
|
||||||
{
|
|
||||||
protected void Write(BinaryWriter stream, float value, RcByteOrder order)
|
|
||||||
{
|
|
||||||
byte[] bytes = BitConverter.GetBytes(value);
|
|
||||||
int i = BitConverter.ToInt32(bytes, 0);
|
|
||||||
Write(stream, i, order);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Write(BinaryWriter stream, short value, RcByteOrder order)
|
|
||||||
{
|
|
||||||
if (order == RcByteOrder.BIG_ENDIAN)
|
|
||||||
{
|
|
||||||
stream.Write((byte)((value >> 8) & 0xFF));
|
|
||||||
stream.Write((byte)(value & 0xFF));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stream.Write((byte)(value & 0xFF));
|
|
||||||
stream.Write((byte)((value >> 8) & 0xFF));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Write(BinaryWriter stream, long value, RcByteOrder order)
|
|
||||||
{
|
|
||||||
if (order == RcByteOrder.BIG_ENDIAN)
|
|
||||||
{
|
|
||||||
Write(stream, (int)((ulong)value >> 32), order);
|
|
||||||
Write(stream, (int)(value & 0xFFFFFFFF), order);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Write(stream, (int)(value & 0xFFFFFFFF), order);
|
|
||||||
Write(stream, (int)((ulong)value >> 32), order);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Write(BinaryWriter stream, int value, RcByteOrder order)
|
|
||||||
{
|
|
||||||
if (order == RcByteOrder.BIG_ENDIAN)
|
|
||||||
{
|
|
||||||
stream.Write((byte)((value >> 24) & 0xFF));
|
|
||||||
stream.Write((byte)((value >> 16) & 0xFF));
|
|
||||||
stream.Write((byte)((value >> 8) & 0xFF));
|
|
||||||
stream.Write((byte)(value & 0xFF));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stream.Write((byte)(value & 0xFF));
|
|
||||||
stream.Write((byte)((value >> 8) & 0xFF));
|
|
||||||
stream.Write((byte)((value >> 16) & 0xFF));
|
|
||||||
stream.Write((byte)((value >> 24) & 0xFF));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Write(BinaryWriter stream, bool @bool)
|
|
||||||
{
|
|
||||||
Write(stream, (byte)(@bool ? 1 : 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Write(BinaryWriter stream, byte value)
|
|
||||||
{
|
|
||||||
stream.Write(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Write(BinaryWriter stream, MemoryStream data)
|
|
||||||
{
|
|
||||||
data.Position = 0;
|
|
||||||
byte[] buffer = new byte[data.Length];
|
|
||||||
data.Read(buffer, 0, buffer.Length);
|
|
||||||
stream.Write(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
/*
|
|
||||||
Recast4J Copyright (c) 2015 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.IO;
|
|
||||||
using DotRecast.Core;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour.Io
|
|
||||||
{
|
|
||||||
public static class IOUtils
|
|
||||||
{
|
|
||||||
public static RcByteBuffer ToByteBuffer(BinaryReader @is, bool direct)
|
|
||||||
{
|
|
||||||
byte[] data = ToByteArray(@is);
|
|
||||||
if (direct)
|
|
||||||
{
|
|
||||||
Array.Reverse(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new RcByteBuffer(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] ToByteArray(BinaryReader inputStream)
|
|
||||||
{
|
|
||||||
using var msw = new MemoryStream();
|
|
||||||
byte[] buffer = new byte[4096];
|
|
||||||
int l;
|
|
||||||
while ((l = inputStream.Read(buffer)) > 0)
|
|
||||||
{
|
|
||||||
msw.Write(buffer, 0, l);
|
|
||||||
}
|
|
||||||
|
|
||||||
return msw.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static RcByteBuffer ToByteBuffer(BinaryReader inputStream)
|
|
||||||
{
|
|
||||||
var bytes = ToByteArray(inputStream);
|
|
||||||
return new RcByteBuffer(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int SwapEndianness(int i)
|
|
||||||
{
|
|
||||||
var s = (((uint)i >> 24) & 0xFF) | (((uint)i >> 8) & 0xFF00) | (((uint)i << 8) & 0xFF0000) | ((i << 24) & 0xFF000000);
|
|
||||||
return (int)s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -32,6 +32,7 @@ namespace DotRecast.Recast.Demo
|
||||||
private DtNavMesh _navMesh;
|
private DtNavMesh _navMesh;
|
||||||
private DtNavMeshQuery _navMeshQuery;
|
private DtNavMeshQuery _navMeshQuery;
|
||||||
private readonly RcNavMeshBuildSettings _settings;
|
private readonly RcNavMeshBuildSettings _settings;
|
||||||
|
private RcConfig _cfg;
|
||||||
private IList<RcBuilderResult> _recastResults;
|
private IList<RcBuilderResult> _recastResults;
|
||||||
private bool _changed;
|
private bool _changed;
|
||||||
|
|
||||||
|
@ -56,6 +57,11 @@ namespace DotRecast.Recast.Demo
|
||||||
return _geom;
|
return _geom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RcConfig GetRecastConfig()
|
||||||
|
{
|
||||||
|
return _cfg;
|
||||||
|
}
|
||||||
|
|
||||||
public IList<RcBuilderResult> GetRecastResults()
|
public IList<RcBuilderResult> GetRecastResults()
|
||||||
{
|
{
|
||||||
return _recastResults;
|
return _recastResults;
|
||||||
|
@ -86,9 +92,10 @@ namespace DotRecast.Recast.Demo
|
||||||
_changed = changed;
|
_changed = changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(DemoInputGeomProvider geom, IList<RcBuilderResult> recastResults, DtNavMesh navMesh)
|
public void Update(DemoInputGeomProvider geom, RcConfig cfg, IList<RcBuilderResult> recastResults, DtNavMesh navMesh)
|
||||||
{
|
{
|
||||||
_geom = geom;
|
_geom = geom;
|
||||||
|
_cfg = cfg;
|
||||||
_recastResults = recastResults;
|
_recastResults = recastResults;
|
||||||
_navMesh = navMesh;
|
_navMesh = navMesh;
|
||||||
SetQuery(navMesh);
|
SetQuery(navMesh);
|
||||||
|
|
|
@ -20,15 +20,15 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Serilog" Version="3.1.1" />
|
<PackageReference Include="Serilog" Version="4.1.0" />
|
||||||
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.0" />
|
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.4" />
|
||||||
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0"/>
|
<PackageReference Include="Serilog.Enrichers.Thread" Version="4.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0"/>
|
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0"/>
|
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.8" />
|
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.8" />
|
||||||
<PackageReference Include="Silk.NET" Version="2.21.0" />
|
<PackageReference Include="Silk.NET" Version="2.22.0" />
|
||||||
<PackageReference Include="Silk.NET.OpenGL.Extensions.ImGui" Version="2.21.0" />
|
<PackageReference Include="Silk.NET.OpenGL.Extensions.ImGui" Version="2.22.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Draw;
|
namespace DotRecast.Recast.Demo.Draw;
|
||||||
|
@ -9,19 +9,19 @@ public class ArrayBuffer<T>
|
||||||
private T[] _items;
|
private T[] _items;
|
||||||
public int Count => _size;
|
public int Count => _size;
|
||||||
|
|
||||||
public ArrayBuffer()
|
public ArrayBuffer() : this(512) { }
|
||||||
|
|
||||||
|
public ArrayBuffer(int capacity)
|
||||||
{
|
{
|
||||||
|
if (capacity <= 0)
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
|
||||||
_size = 0;
|
_size = 0;
|
||||||
_items = Array.Empty<T>();
|
_items = new T[capacity];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(T item)
|
public void Add(T item)
|
||||||
{
|
{
|
||||||
if (0 >= _items.Length)
|
|
||||||
{
|
|
||||||
_items = new T[256];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_items.Length <= _size)
|
if (_items.Length <= _size)
|
||||||
{
|
{
|
||||||
var temp = new T[(int)(_size * 1.5)];
|
var temp = new T[(int)(_size * 1.5)];
|
||||||
|
@ -37,8 +37,8 @@ public class ArrayBuffer<T>
|
||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T[] AsArray()
|
public Span<T> AsArray()
|
||||||
{
|
{
|
||||||
return _items;
|
return _items.AsSpan(0, _size);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -326,9 +326,9 @@ public class DebugDraw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly int NUM_ARC_PTS = 8;
|
private const int NUM_ARC_PTS = 8;
|
||||||
private static readonly float PAD = 0.05f;
|
private const float PAD = 0.05f;
|
||||||
private static readonly float ARC_PTS_SCALE = (1.0f - PAD * 2) / NUM_ARC_PTS;
|
private const float ARC_PTS_SCALE = (1.0f - PAD * 2) / NUM_ARC_PTS;
|
||||||
|
|
||||||
public void AppendArc(float x0, float y0, float z0, float x1, float y1, float z1, float h, float as0, float as1, int col)
|
public void AppendArc(float x0, float y0, float z0, float x1, float y1, float z1, float h, float as0, float as1, int col)
|
||||||
{
|
{
|
||||||
|
@ -694,7 +694,7 @@ public class DebugDraw
|
||||||
plane[3] = pw;
|
plane[3] = pw;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool FrustumTest(float[] bounds)
|
public bool FrustumTest(Span<float> bounds)
|
||||||
{
|
{
|
||||||
foreach (float[] plane in frustumPlanes)
|
foreach (float[] plane in frustumPlanes)
|
||||||
{
|
{
|
||||||
|
@ -748,6 +748,6 @@ public class DebugDraw
|
||||||
|
|
||||||
public bool FrustumTest(RcVec3f bmin, RcVec3f bmax)
|
public bool FrustumTest(RcVec3f bmin, RcVec3f bmax)
|
||||||
{
|
{
|
||||||
return FrustumTest(new float[] { bmin.X, bmin.Y, bmin.Z, bmax.X, bmax.Y, bmax.Z });
|
return FrustumTest(stackalloc float[] { bmin.X, bmin.Y, bmin.Z, bmax.X, bmax.Y, bmax.Z });
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -68,8 +69,8 @@ public static class GLU
|
||||||
public static int GlhUnProjectf(float winx, float winy, float winz, float[] modelview, float[] projection, int[] viewport, ref RcVec3f objectCoordinate)
|
public static int GlhUnProjectf(float winx, float winy, float winz, float[] modelview, float[] projection, int[] viewport, ref RcVec3f objectCoordinate)
|
||||||
{
|
{
|
||||||
// Transformation matrices
|
// Transformation matrices
|
||||||
float[] m = new float[16], A = new float[16];
|
Span<float> m = stackalloc float[16], A = stackalloc float[16];
|
||||||
float[] @in = new float[4], @out = new float[4];
|
Span<float> @in = stackalloc float[4], @out = stackalloc float[4];
|
||||||
// Calculation for inverting a matrix, compute projection x modelview
|
// Calculation for inverting a matrix, compute projection x modelview
|
||||||
// and store in A[16]
|
// and store in A[16]
|
||||||
MultiplyMatrices4by4OpenGL_FLOAT(A, projection, modelview);
|
MultiplyMatrices4by4OpenGL_FLOAT(A, projection, modelview);
|
||||||
|
@ -92,7 +93,7 @@ public static class GLU
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MultiplyMatrices4by4OpenGL_FLOAT(float[] result, float[] matrix1, float[] matrix2)
|
static void MultiplyMatrices4by4OpenGL_FLOAT(Span<float> result, float[] matrix1, float[] matrix2)
|
||||||
{
|
{
|
||||||
result[0] = matrix1[0] * matrix2[0] + matrix1[4] * matrix2[1] + matrix1[8] * matrix2[2] + matrix1[12] * matrix2[3];
|
result[0] = matrix1[0] * matrix2[0] + matrix1[4] * matrix2[1] + matrix1[8] * matrix2[2] + matrix1[12] * matrix2[3];
|
||||||
result[4] = matrix1[0] * matrix2[4] + matrix1[4] * matrix2[5] + matrix1[8] * matrix2[6] + matrix1[12] * matrix2[7];
|
result[4] = matrix1[0] * matrix2[4] + matrix1[4] * matrix2[5] + matrix1[8] * matrix2[6] + matrix1[12] * matrix2[7];
|
||||||
|
@ -115,7 +116,7 @@ public static class GLU
|
||||||
result[15] = matrix1[3] * matrix2[12] + matrix1[7] * matrix2[13] + matrix1[11] * matrix2[14] + matrix1[15] * matrix2[15];
|
result[15] = matrix1[3] * matrix2[12] + matrix1[7] * matrix2[13] + matrix1[11] * matrix2[14] + matrix1[15] * matrix2[15];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MultiplyMatrixByVector4by4OpenGL_FLOAT(float[] resultvector, float[] matrix, float[] pvector)
|
static void MultiplyMatrixByVector4by4OpenGL_FLOAT(Span<float> resultvector, Span<float> matrix, Span<float> pvector)
|
||||||
{
|
{
|
||||||
resultvector[0] = matrix[0] * pvector[0] + matrix[4] * pvector[1] + matrix[8] * pvector[2] + matrix[12] * pvector[3];
|
resultvector[0] = matrix[0] * pvector[0] + matrix[4] * pvector[1] + matrix[8] * pvector[2] + matrix[12] * pvector[3];
|
||||||
resultvector[1] = matrix[1] * pvector[0] + matrix[5] * pvector[1] + matrix[9] * pvector[2] + matrix[13] * pvector[3];
|
resultvector[1] = matrix[1] * pvector[0] + matrix[5] * pvector[1] + matrix[9] * pvector[2] + matrix[13] * pvector[3];
|
||||||
|
@ -124,15 +125,13 @@ public static class GLU
|
||||||
}
|
}
|
||||||
|
|
||||||
// This code comes directly from GLU except that it is for float
|
// This code comes directly from GLU except that it is for float
|
||||||
static int GlhInvertMatrixf2(float[] m, float[] @out)
|
static int GlhInvertMatrixf2(Span<float> m, Span<float> @out)
|
||||||
{
|
{
|
||||||
float[][] wtmp = RcArrays.Of<float>(4, 8);
|
|
||||||
float m0, m1, m2, m3, s;
|
float m0, m1, m2, m3, s;
|
||||||
float[] r0, r1, r2, r3;
|
Span<float> r0 = stackalloc float[8];
|
||||||
r0 = wtmp[0];
|
Span<float> r1 = stackalloc float[8];
|
||||||
r1 = wtmp[1];
|
Span<float> r2 = stackalloc float[8];
|
||||||
r2 = wtmp[2];
|
Span<float> r3 = stackalloc float[8];
|
||||||
r3 = wtmp[3];
|
|
||||||
r0[0] = MAT(m, 0, 0);
|
r0[0] = MAT(m, 0, 0);
|
||||||
r0[1] = MAT(m, 0, 1);
|
r0[1] = MAT(m, 0, 1);
|
||||||
r0[2] = MAT(m, 0, 2);
|
r0[2] = MAT(m, 0, 2);
|
||||||
|
@ -160,27 +159,28 @@ public static class GLU
|
||||||
/* choose pivot - or die */
|
/* choose pivot - or die */
|
||||||
if (MathF.Abs(r3[0]) > MathF.Abs(r2[0]))
|
if (MathF.Abs(r3[0]) > MathF.Abs(r2[0]))
|
||||||
{
|
{
|
||||||
float[] r = r2;
|
Span<float> r = r2;
|
||||||
r2 = r3;
|
r2 = r3;
|
||||||
r3 = r;
|
r3 = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MathF.Abs(r2[0]) > MathF.Abs(r1[0]))
|
if (MathF.Abs(r2[0]) > MathF.Abs(r1[0]))
|
||||||
{
|
{
|
||||||
float[] r = r2;
|
Span<float> r = r2;
|
||||||
r2 = r1;
|
r2 = r1;
|
||||||
r1 = r;
|
r1 = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MathF.Abs(r1[0]) > MathF.Abs(r0[0]))
|
if (MathF.Abs(r1[0]) > MathF.Abs(r0[0]))
|
||||||
{
|
{
|
||||||
float[] r = r1;
|
Span<float> r = r1;
|
||||||
r1 = r0;
|
r1 = r0;
|
||||||
r0 = r;
|
r0 = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0.0 == r0[0])
|
if (0.0 == r0[0])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* eliminate first variable */
|
/* eliminate first variable */
|
||||||
m1 = r1[0] / r0[0];
|
m1 = r1[0] / r0[0];
|
||||||
m2 = r2[0] / r0[0];
|
m2 = r2[0] / r0[0];
|
||||||
|
@ -232,14 +232,14 @@ public static class GLU
|
||||||
/* choose pivot - or die */
|
/* choose pivot - or die */
|
||||||
if (MathF.Abs(r3[1]) > MathF.Abs(r2[1]))
|
if (MathF.Abs(r3[1]) > MathF.Abs(r2[1]))
|
||||||
{
|
{
|
||||||
float[] r = r2;
|
Span<float> r = r2;
|
||||||
r2 = r3;
|
r2 = r3;
|
||||||
r3 = r;
|
r3 = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MathF.Abs(r2[1]) > MathF.Abs(r1[1]))
|
if (MathF.Abs(r2[1]) > MathF.Abs(r1[1]))
|
||||||
{
|
{
|
||||||
float[] r = r2;
|
Span<float> r = r2;
|
||||||
r2 = r1;
|
r2 = r1;
|
||||||
r1 = r;
|
r1 = r;
|
||||||
}
|
}
|
||||||
|
@ -284,7 +284,7 @@ public static class GLU
|
||||||
/* choose pivot - or die */
|
/* choose pivot - or die */
|
||||||
if (MathF.Abs(r3[2]) > MathF.Abs(r2[2]))
|
if (MathF.Abs(r3[2]) > MathF.Abs(r2[2]))
|
||||||
{
|
{
|
||||||
float[] r = r2;
|
Span<float> r = r2;
|
||||||
r2 = r3;
|
r2 = r3;
|
||||||
r3 = r;
|
r3 = r;
|
||||||
}
|
}
|
||||||
|
@ -358,12 +358,12 @@ public static class GLU
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static float MAT(float[] m, int r, int c)
|
static float MAT(Span<float> m, int r, int c)
|
||||||
{
|
{
|
||||||
return m[(c) * 4 + (r)];
|
return m[(c) * 4 + (r)];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MAT(float[] m, int r, int c, float v)
|
static void MAT(Span<float> m, int r, int c, float v)
|
||||||
{
|
{
|
||||||
m[(c) * 4 + (r)] = v;
|
m[(c) * 4 + (r)] = v;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Numerics;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Draw;
|
namespace DotRecast.Recast.Demo.Draw;
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using Silk.NET.OpenGL;
|
using Silk.NET.OpenGL;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Draw;
|
namespace DotRecast.Recast.Demo.Draw;
|
||||||
|
|
||||||
|
// TODO use a lot of Memory, 2GB+
|
||||||
|
|
||||||
public class ModernOpenGLDraw : IOpenGLDraw
|
public class ModernOpenGLDraw : IOpenGLDraw
|
||||||
{
|
{
|
||||||
private GL _gl;
|
private GL _gl;
|
||||||
|
@ -19,8 +20,8 @@ public class ModernOpenGLDraw : IOpenGLDraw
|
||||||
private float fogEnd;
|
private float fogEnd;
|
||||||
private bool fogEnabled;
|
private bool fogEnabled;
|
||||||
private int uniformViewMatrix;
|
private int uniformViewMatrix;
|
||||||
private readonly ArrayBuffer<OpenGLVertex> vertices = new();
|
private readonly ArrayBuffer<OpenGLVertex> vertices = new(512);
|
||||||
private readonly ArrayBuffer<int> elements = new();
|
private readonly ArrayBuffer<int> elements = new(512);
|
||||||
private GLCheckerTexture _texture;
|
private GLCheckerTexture _texture;
|
||||||
private readonly float[] _viewMatrix = new float[16];
|
private readonly float[] _viewMatrix = new float[16];
|
||||||
private readonly float[] _projectionMatrix = new float[16];
|
private readonly float[] _projectionMatrix = new float[16];
|
||||||
|
@ -36,36 +37,42 @@ public class ModernOpenGLDraw : IOpenGLDraw
|
||||||
|
|
||||||
public unsafe void Init()
|
public unsafe void Init()
|
||||||
{
|
{
|
||||||
string SHADER_VERSION = "#version 400\n";
|
const string SHADER_VERSION = "#version 400\n";
|
||||||
string vertex_shader = SHADER_VERSION + "uniform mat4 ProjMtx;\n" //
|
const string vertex_shader = $@"
|
||||||
+ "uniform mat4 ViewMtx;\n" //
|
{SHADER_VERSION}
|
||||||
+ "in vec3 Position;\n" //
|
uniform mat4 ProjMtx;
|
||||||
+ "in vec2 TexCoord;\n" //
|
uniform mat4 ViewMtx;
|
||||||
+ "in vec4 Color;\n" //
|
in vec3 Position;
|
||||||
+ "out vec2 Frag_UV;\n" //
|
in vec2 TexCoord;
|
||||||
+ "out vec4 Frag_Color;\n" //
|
in vec4 Color;
|
||||||
+ "out float Frag_Depth;\n" //
|
out vec2 Frag_UV;
|
||||||
+ "void main() {\n" //
|
out vec4 Frag_Color;
|
||||||
+ " Frag_UV = TexCoord;\n" //
|
out float Frag_Depth;
|
||||||
+ " Frag_Color = Color;\n" //
|
void main() {{
|
||||||
+ " vec4 VSPosition = ViewMtx * vec4(Position, 1);\n" //
|
Frag_UV = TexCoord;
|
||||||
+ " Frag_Depth = -VSPosition.z;\n" //
|
Frag_Color = Color;
|
||||||
+ " gl_Position = ProjMtx * VSPosition;\n" //
|
vec4 VSPosition = ViewMtx * vec4(Position, 1);
|
||||||
+ "}\n";
|
Frag_Depth = -VSPosition.z;
|
||||||
string fragment_shader = SHADER_VERSION + "precision mediump float;\n" //
|
gl_Position = ProjMtx * VSPosition;
|
||||||
+ "uniform sampler2D Texture;\n" //
|
}}
|
||||||
+ "uniform float UseTexture;\n" //
|
";
|
||||||
+ "uniform float EnableFog;\n" //
|
const string fragment_shader = $@"
|
||||||
+ "uniform float FogStart;\n" //
|
{SHADER_VERSION}
|
||||||
+ "uniform float FogEnd;\n" //
|
precision mediump float;
|
||||||
+ "const vec4 FogColor = vec4(0.3f, 0.3f, 0.32f, 1.0f);\n" //
|
uniform sampler2D Texture;
|
||||||
+ "in vec2 Frag_UV;\n" //
|
uniform float UseTexture;
|
||||||
+ "in vec4 Frag_Color;\n" //
|
uniform float EnableFog;
|
||||||
+ "in float Frag_Depth;\n" //
|
uniform float FogStart;
|
||||||
+ "out vec4 Out_Color;\n" //
|
uniform float FogEnd;
|
||||||
+ "void main(){\n" //
|
const vec4 FogColor = vec4(0.3f, 0.3f, 0.32f, 1.0f);
|
||||||
+ " Out_Color = mix(FogColor, Frag_Color * mix(vec4(1), texture(Texture, Frag_UV.st), UseTexture), 1.0 - EnableFog * clamp( (Frag_Depth - FogStart) / (FogEnd - FogStart), 0.0, 1.0) );\n" //
|
in vec2 Frag_UV;
|
||||||
+ "}\n";
|
in vec4 Frag_Color;
|
||||||
|
in float Frag_Depth;
|
||||||
|
out vec4 Out_Color;
|
||||||
|
void main(){{
|
||||||
|
Out_Color = mix(FogColor, Frag_Color * mix(vec4(1), texture(Texture, Frag_UV.st), UseTexture), 1.0 - EnableFog * clamp( (Frag_Depth - FogStart) / (FogEnd - FogStart), 0.0, 1.0) );
|
||||||
|
}}
|
||||||
|
";
|
||||||
|
|
||||||
program = _gl.CreateProgram();
|
program = _gl.CreateProgram();
|
||||||
uint vert_shdr = _gl.CreateShader(GLEnum.VertexShader);
|
uint vert_shdr = _gl.CreateShader(GLEnum.VertexShader);
|
||||||
|
@ -150,6 +157,10 @@ public class ModernOpenGLDraw : IOpenGLDraw
|
||||||
_gl.BindVertexArray(0);
|
_gl.BindVertexArray(0);
|
||||||
_gl.BindBuffer(GLEnum.ArrayBuffer, 0);
|
_gl.BindBuffer(GLEnum.ArrayBuffer, 0);
|
||||||
_gl.BindBuffer(GLEnum.ElementArrayBuffer, 0);
|
_gl.BindBuffer(GLEnum.ElementArrayBuffer, 0);
|
||||||
|
|
||||||
|
//int* range = stackalloc int[2];
|
||||||
|
//_gl.GetInteger(GetPName.LineWidthRange, range);
|
||||||
|
//Console.WriteLine($"\nLineWidthRange: {range[0]} {range[1]}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
|
@ -191,53 +202,30 @@ public class ModernOpenGLDraw : IOpenGLDraw
|
||||||
// GlBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_BUFFER, GL_STREAM_DRAW);
|
// GlBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_BUFFER, GL_STREAM_DRAW);
|
||||||
// GlBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_BUFFER, GL_STREAM_DRAW);
|
// GlBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_BUFFER, GL_STREAM_DRAW);
|
||||||
|
|
||||||
uint vboSize = (uint)vertices.Count * 24;
|
_gl.BufferData<OpenGLVertex>(GLEnum.ArrayBuffer, vertices.AsArray(), GLEnum.DynamicDraw);
|
||||||
uint eboSize = currentPrim == DebugDrawPrimitives.QUADS ? (uint)vertices.Count * 6 : (uint)vertices.Count * 4;
|
|
||||||
|
|
||||||
_gl.BufferData(GLEnum.ArrayBuffer, vboSize, null, GLEnum.StreamDraw);
|
|
||||||
_gl.BufferData(GLEnum.ElementArrayBuffer, eboSize, null, GLEnum.StreamDraw);
|
|
||||||
// load draw vertices & elements directly into vertex + element buffer
|
|
||||||
|
|
||||||
|
if (currentPrim == DebugDrawPrimitives.QUADS)
|
||||||
{
|
{
|
||||||
byte* pVerts = (byte*)_gl.MapBuffer(GLEnum.ArrayBuffer, GLEnum.WriteOnly);
|
for (int i = 0; i < vertices.Count; i += 4)
|
||||||
byte* pElems = (byte*)_gl.MapBuffer(GLEnum.ElementArrayBuffer, GLEnum.WriteOnly);
|
|
||||||
|
|
||||||
//vertices.ForEach(v => v.Store(verts));
|
|
||||||
fixed (void* v = vertices.AsArray())
|
|
||||||
{
|
{
|
||||||
System.Buffer.MemoryCopy(v, pVerts, vboSize, vboSize);
|
elements.Add(i);
|
||||||
|
elements.Add(i + 1);
|
||||||
|
elements.Add(i + 2);
|
||||||
|
elements.Add(i);
|
||||||
|
elements.Add(i + 2);
|
||||||
|
elements.Add(i + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentPrim == DebugDrawPrimitives.QUADS)
|
|
||||||
{
|
|
||||||
using var unmanagedElems = new UnmanagedMemoryStream(pElems, eboSize, eboSize, FileAccess.Write);
|
|
||||||
using var bw = new BinaryWriter(unmanagedElems);
|
|
||||||
for (int i = 0; i < vertices.Count; i += 4)
|
|
||||||
{
|
|
||||||
bw.Write(i);
|
|
||||||
bw.Write(i + 1);
|
|
||||||
bw.Write(i + 2);
|
|
||||||
bw.Write(i);
|
|
||||||
bw.Write(i + 2);
|
|
||||||
bw.Write(i + 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = elements.Count; i < vertices.Count; i++)
|
|
||||||
{
|
|
||||||
elements.Add(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
fixed (void* e = elements.AsArray())
|
|
||||||
{
|
|
||||||
System.Buffer.MemoryCopy(e, pElems, eboSize, eboSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_gl.UnmapBuffer(GLEnum.ElementArrayBuffer);
|
|
||||||
_gl.UnmapBuffer(GLEnum.ArrayBuffer);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = elements.Count; i < vertices.Count; i++)
|
||||||
|
{
|
||||||
|
elements.Add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_gl.BufferData<int>(GLEnum.ElementArrayBuffer, elements.AsArray(), GLEnum.DynamicDraw);
|
||||||
|
|
||||||
if (_texture != null)
|
if (_texture != null)
|
||||||
{
|
{
|
||||||
_texture.Bind();
|
_texture.Bind();
|
||||||
|
@ -271,15 +259,22 @@ public class ModernOpenGLDraw : IOpenGLDraw
|
||||||
_gl.BindBuffer(GLEnum.ArrayBuffer, 0);
|
_gl.BindBuffer(GLEnum.ArrayBuffer, 0);
|
||||||
_gl.BindBuffer(GLEnum.ElementArrayBuffer, 0);
|
_gl.BindBuffer(GLEnum.ElementArrayBuffer, 0);
|
||||||
vertices.Clear();
|
vertices.Clear();
|
||||||
|
elements.Clear();
|
||||||
_gl.LineWidth(1.0f);
|
_gl.LineWidth(1.0f);
|
||||||
_gl.PointSize(1.0f);
|
_gl.PointSize(1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Vertex(float x, float y, float z, int color)
|
public void Vertex(float x, float y, float z, int color)
|
||||||
{
|
{
|
||||||
vertices.Add(new OpenGLVertex(x, y, z, color));
|
vertices.Add(new OpenGLVertex(x, y, z, color));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public unsafe void Vertex(float* pos, int color)
|
||||||
|
{
|
||||||
|
vertices.Add(new OpenGLVertex(pos[0], pos[1], pos[2], color));
|
||||||
|
}
|
||||||
|
|
||||||
public void Vertex(float[] pos, int color)
|
public void Vertex(float[] pos, int color)
|
||||||
{
|
{
|
||||||
vertices.Add(new OpenGLVertex(pos, color));
|
vertices.Add(new OpenGLVertex(pos, color));
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -23,14 +23,14 @@ using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Detour;
|
using DotRecast.Detour;
|
||||||
using DotRecast.Recast.Toolset.Builder;
|
using DotRecast.Recast.Toolset.Builder;
|
||||||
using DotRecast.Recast.Toolset.Geom;
|
using DotRecast.Recast.Toolset.Geom;
|
||||||
using static DotRecast.Recast.RcCommons;
|
using static DotRecast.Recast.RcRecast;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Draw;
|
namespace DotRecast.Recast.Demo.Draw;
|
||||||
|
|
||||||
public class NavMeshRenderer
|
public class NavMeshRenderer
|
||||||
{
|
{
|
||||||
private readonly RecastDebugDraw _debugDraw;
|
private readonly RecastDebugDraw _debugDraw;
|
||||||
private readonly int _navMeshDrawFlags = RecastDebugDraw.DRAWNAVMESH_OFFMESHCONS | RecastDebugDraw.DRAWNAVMESH_CLOSEDLIST;
|
private readonly int _navMeshDrawFlags = RecastDebugDraw.DU_DRAWNAVMESH_OFFMESHCONS | RecastDebugDraw.DU_DRAWNAVMESH_CLOSEDLIST;
|
||||||
|
|
||||||
public NavMeshRenderer(RecastDebugDraw debugDraw)
|
public NavMeshRenderer(RecastDebugDraw debugDraw)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -19,7 +19,6 @@ freely, subject to the following restrictions:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Detour;
|
using DotRecast.Detour;
|
||||||
using DotRecast.Recast.Toolset.Builder;
|
using DotRecast.Recast.Toolset.Builder;
|
||||||
|
@ -27,11 +26,13 @@ using Silk.NET.OpenGL;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Draw;
|
namespace DotRecast.Recast.Demo.Draw;
|
||||||
|
|
||||||
|
using static DtDetour;
|
||||||
|
|
||||||
public class RecastDebugDraw : DebugDraw
|
public class RecastDebugDraw : DebugDraw
|
||||||
{
|
{
|
||||||
public static readonly int DRAWNAVMESH_OFFMESHCONS = 0x01;
|
public const int DU_DRAWNAVMESH_OFFMESHCONS = 0x01;
|
||||||
public static readonly int DRAWNAVMESH_CLOSEDLIST = 0x02;
|
public const int DU_DRAWNAVMESH_CLOSEDLIST = 0x02;
|
||||||
public static readonly int DRAWNAVMESH_COLOR_TILES = 0x04;
|
public const int DU_DRAWNAVMESH_COLOR_TILES = 0x04;
|
||||||
|
|
||||||
public RecastDebugDraw(GL gl) : base(gl)
|
public RecastDebugDraw(GL gl) : base(gl)
|
||||||
{
|
{
|
||||||
|
@ -101,7 +102,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
|
|
||||||
public void DebugDrawNavMeshWithClosedList(DtNavMesh mesh, DtNavMeshQuery query, int flags)
|
public void DebugDrawNavMeshWithClosedList(DtNavMesh mesh, DtNavMeshQuery query, int flags)
|
||||||
{
|
{
|
||||||
DtNavMeshQuery q = (flags & DRAWNAVMESH_CLOSEDLIST) != 0 ? query : null;
|
DtNavMeshQuery q = (flags & DU_DRAWNAVMESH_CLOSEDLIST) != 0 ? query : null;
|
||||||
for (int i = 0; i < mesh.GetMaxTiles(); ++i)
|
for (int i = 0; i < mesh.GetMaxTiles(); ++i)
|
||||||
{
|
{
|
||||||
DtMeshTile tile = mesh.GetTile(i);
|
DtMeshTile tile = mesh.GetTile(i);
|
||||||
|
@ -116,7 +117,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
{
|
{
|
||||||
long @base = mesh.GetPolyRefBase(tile);
|
long @base = mesh.GetPolyRefBase(tile);
|
||||||
|
|
||||||
int tileNum = DtNavMesh.DecodePolyIdTile(@base);
|
int tileNum = DecodePolyIdTile(@base);
|
||||||
int tileColor = DuIntToCol(tileNum, 128);
|
int tileColor = DuIntToCol(tileNum, 128);
|
||||||
DepthMask(false);
|
DepthMask(false);
|
||||||
Begin(DebugDrawPrimitives.TRIS);
|
Begin(DebugDrawPrimitives.TRIS);
|
||||||
|
@ -135,7 +136,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((flags & DRAWNAVMESH_COLOR_TILES) != 0)
|
if ((flags & DU_DRAWNAVMESH_COLOR_TILES) != 0)
|
||||||
{
|
{
|
||||||
col = tileColor;
|
col = tileColor;
|
||||||
}
|
}
|
||||||
|
@ -163,7 +164,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
// Draw outer poly boundaries
|
// Draw outer poly boundaries
|
||||||
DrawPolyBoundaries(tile, DuRGBA(0, 48, 64, 220), 2.5f, false);
|
DrawPolyBoundaries(tile, DuRGBA(0, 48, 64, 220), 2.5f, false);
|
||||||
|
|
||||||
if ((flags & DRAWNAVMESH_OFFMESHCONS) != 0)
|
if ((flags & DU_DRAWNAVMESH_OFFMESHCONS) != 0)
|
||||||
{
|
{
|
||||||
Begin(DebugDrawPrimitives.LINES, 2.0f);
|
Begin(DebugDrawPrimitives.LINES, 2.0f);
|
||||||
for (int i = 0; i < tile.data.header.polyCount; ++i)
|
for (int i = 0; i < tile.data.header.polyCount; ++i)
|
||||||
|
@ -198,7 +199,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
// Check to see if start and end end-points have links.
|
// Check to see if start and end end-points have links.
|
||||||
bool startSet = false;
|
bool startSet = false;
|
||||||
bool endSet = false;
|
bool endSet = false;
|
||||||
for (int k = tile.polyLinks[p.index]; k != DtNavMesh.DT_NULL_LINK; k = tile.links[k].next)
|
for (int k = p.firstLink; k != DT_NULL_LINK; k = tile.links[k].next)
|
||||||
{
|
{
|
||||||
if (tile.links[k].edge == 0)
|
if (tile.links[k].edge == 0)
|
||||||
{
|
{
|
||||||
|
@ -299,6 +300,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
|
|
||||||
Begin(DebugDrawPrimitives.LINES, linew);
|
Begin(DebugDrawPrimitives.LINES, linew);
|
||||||
|
|
||||||
|
Span<RcVec3f> tv = stackalloc RcVec3f[3];
|
||||||
for (int i = 0; i < tile.data.header.polyCount; ++i)
|
for (int i = 0; i < tile.data.header.polyCount; ++i)
|
||||||
{
|
{
|
||||||
DtPoly p = tile.data.polys[i];
|
DtPoly p = tile.data.polys[i];
|
||||||
|
@ -318,10 +320,10 @@ public class RecastDebugDraw : DebugDraw
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((p.neis[j] & DtNavMesh.DT_EXT_LINK) != 0)
|
if ((p.neis[j] & DT_EXT_LINK) != 0)
|
||||||
{
|
{
|
||||||
bool con = false;
|
bool con = false;
|
||||||
for (int k = tile.polyLinks[p.index]; k != DtNavMesh.DT_NULL_LINK; k = tile.links[k].next)
|
for (int k = p.firstLink; k != DT_NULL_LINK; k = tile.links[k].next)
|
||||||
{
|
{
|
||||||
if (tile.links[k].edge == j)
|
if (tile.links[k].edge == j)
|
||||||
{
|
{
|
||||||
|
@ -370,14 +372,14 @@ public class RecastDebugDraw : DebugDraw
|
||||||
for (int k = 0; k < pd.triCount; ++k)
|
for (int k = 0; k < pd.triCount; ++k)
|
||||||
{
|
{
|
||||||
int t = (pd.triBase + k) * 4;
|
int t = (pd.triBase + k) * 4;
|
||||||
RcVec3f[] tv = new RcVec3f[3];
|
|
||||||
for (int m = 0; m < 3; ++m)
|
for (int m = 0; m < 3; ++m)
|
||||||
{
|
{
|
||||||
int v = tile.data.detailTris[t + m];
|
int v = tile.data.detailTris[t + m];
|
||||||
if (v < p.vertCount)
|
if (v < p.vertCount)
|
||||||
{
|
{
|
||||||
tv[m] = new RcVec3f(
|
tv[m] = new RcVec3f(
|
||||||
tile.data.verts[p.verts[v] * 3], tile.data.verts[p.verts[v] * 3 + 1],
|
tile.data.verts[p.verts[v] * 3],
|
||||||
|
tile.data.verts[p.verts[v] * 3 + 1],
|
||||||
tile.data.verts[p.verts[v] * 3 + 2]
|
tile.data.verts[p.verts[v] * 3 + 2]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -393,7 +395,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
|
|
||||||
for (int m = 0, n = 2; m < 3; n = m++)
|
for (int m = 0, n = 2; m < 3; n = m++)
|
||||||
{
|
{
|
||||||
if ((DtNavMesh.GetDetailTriEdgeFlags(tile.data.detailTris[t + 3], n) & DtDetailTriEdgeFlags.DT_DETAIL_EDGE_BOUNDARY) == 0)
|
if ((GetDetailTriEdgeFlags(tile.data.detailTris[t + 3], n) & DtDetailTriEdgeFlags.DT_DETAIL_EDGE_BOUNDARY) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (((tile.data.detailTris[t + 3] >> (n * 2)) & 0x3) == 0)
|
if (((tile.data.detailTris[t + 3] >> (n * 2)) & 0x3) == 0)
|
||||||
|
@ -463,9 +465,13 @@ public class RecastDebugDraw : DebugDraw
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
AppendBoxWire(tile.data.header.bmin.X + n.bmin[0] * cs, tile.data.header.bmin.Y + n.bmin[1] * cs,
|
AppendBoxWire(
|
||||||
tile.data.header.bmin.Z + n.bmin[2] * cs, tile.data.header.bmin.X + n.bmax[0] * cs,
|
tile.data.header.bmin.X + n.bmin.X * cs,
|
||||||
tile.data.header.bmin.Y + n.bmax[1] * cs, tile.data.header.bmin.Z + n.bmax[2] * cs,
|
tile.data.header.bmin.Y + n.bmin.Y * cs,
|
||||||
|
tile.data.header.bmin.Z + n.bmin.Z * cs,
|
||||||
|
tile.data.header.bmin.X + n.bmax.X * cs,
|
||||||
|
tile.data.header.bmin.Y + n.bmax.Y * cs,
|
||||||
|
tile.data.header.bmin.Z + n.bmax.Z * cs,
|
||||||
DuRGBA(255, 255, 255, 128));
|
DuRGBA(255, 255, 255, 128));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,7 +503,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
{
|
{
|
||||||
color = DuRGBA(0, 192, 255, 64);
|
color = DuRGBA(0, 192, 255, 64);
|
||||||
}
|
}
|
||||||
else if (area == RcConstants.RC_NULL_AREA)
|
else if (area == RcRecast.RC_NULL_AREA)
|
||||||
{
|
{
|
||||||
color = DuRGBA(0, 0, 0, 64);
|
color = DuRGBA(0, 0, 0, 64);
|
||||||
}
|
}
|
||||||
|
@ -669,7 +675,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
int v3 = c.rverts[j * 4 + 3];
|
int v3 = c.rverts[j * 4 + 3];
|
||||||
float off = 0;
|
float off = 0;
|
||||||
int colv = color;
|
int colv = color;
|
||||||
if ((v3 & RcConstants.RC_BORDER_VERTEX) != 0)
|
if ((v3 & RcRecast.RC_BORDER_VERTEX) != 0)
|
||||||
{
|
{
|
||||||
colv = DuRGBA(255, 255, 255, a);
|
colv = DuRGBA(255, 255, 255, a);
|
||||||
off = ch * 2;
|
off = ch * 2;
|
||||||
|
@ -716,7 +722,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
int vb0 = c.verts[j * 4];
|
int vb0 = c.verts[j * 4];
|
||||||
int vb1 = c.verts[j * 4 + 1];
|
int vb1 = c.verts[j * 4 + 1];
|
||||||
int vb2 = c.verts[j * 4 + 2];
|
int vb2 = c.verts[j * 4 + 2];
|
||||||
int col = (va3 & RcConstants.RC_AREA_BORDER) != 0 ? bcolor : color;
|
int col = (va3 & RcRecast.RC_AREA_BORDER) != 0 ? bcolor : color;
|
||||||
|
|
||||||
float fx = orig.X + va0 * cs;
|
float fx = orig.X + va0 * cs;
|
||||||
float fy = orig.Y + (va1 + 1 + (i & 1)) * ch;
|
float fy = orig.Y + (va1 + 1 + (i & 1)) * ch;
|
||||||
|
@ -747,7 +753,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
int v3 = c.verts[j * 4 + 3];
|
int v3 = c.verts[j * 4 + 3];
|
||||||
float off = 0;
|
float off = 0;
|
||||||
int colv = color;
|
int colv = color;
|
||||||
if ((v3 & RcConstants.RC_BORDER_VERTEX) != 0)
|
if ((v3 & RcRecast.RC_BORDER_VERTEX) != 0)
|
||||||
{
|
{
|
||||||
colv = DuRGBA(255, 255, 255, a);
|
colv = DuRGBA(255, 255, 255, a);
|
||||||
off = ch * 2;
|
off = ch * 2;
|
||||||
|
@ -827,7 +833,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
{
|
{
|
||||||
fcol[0] = DuRGBA(64, 128, 160, 255);
|
fcol[0] = DuRGBA(64, 128, 160, 255);
|
||||||
}
|
}
|
||||||
else if (s.area == RcConstants.RC_NULL_AREA)
|
else if (s.area == RcRecast.RC_NULL_AREA)
|
||||||
{
|
{
|
||||||
fcol[0] = DuRGBA(64, 64, 64, 255);
|
fcol[0] = DuRGBA(64, 64, 64, 255);
|
||||||
}
|
}
|
||||||
|
@ -949,7 +955,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
{
|
{
|
||||||
color = DuRGBA(0, 192, 255, 64);
|
color = DuRGBA(0, 192, 255, 64);
|
||||||
}
|
}
|
||||||
else if (area == RcConstants.RC_NULL_AREA)
|
else if (area == RcRecast.RC_NULL_AREA)
|
||||||
{
|
{
|
||||||
color = DuRGBA(0, 0, 0, 64);
|
color = DuRGBA(0, 0, 0, 64);
|
||||||
}
|
}
|
||||||
|
@ -961,7 +967,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
int[] vi = new int[3];
|
int[] vi = new int[3];
|
||||||
for (int j = 2; j < nvp; ++j)
|
for (int j = 2; j < nvp; ++j)
|
||||||
{
|
{
|
||||||
if (mesh.polys[p + j] == RcConstants.RC_MESH_NULL_IDX)
|
if (mesh.polys[p + j] == RcRecast.RC_MESH_NULL_IDX)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -992,7 +998,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
int p = i * nvp * 2;
|
int p = i * nvp * 2;
|
||||||
for (int j = 0; j < nvp; ++j)
|
for (int j = 0; j < nvp; ++j)
|
||||||
{
|
{
|
||||||
if (mesh.polys[p + j] == RcConstants.RC_MESH_NULL_IDX)
|
if (mesh.polys[p + j] == RcRecast.RC_MESH_NULL_IDX)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1002,7 +1008,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nj = (j + 1 >= nvp || mesh.polys[p + j + 1] == RcConstants.RC_MESH_NULL_IDX) ? 0 : j + 1;
|
int nj = (j + 1 >= nvp || mesh.polys[p + j + 1] == RcRecast.RC_MESH_NULL_IDX) ? 0 : j + 1;
|
||||||
int[] vi = { mesh.polys[p + j], mesh.polys[p + nj] };
|
int[] vi = { mesh.polys[p + j], mesh.polys[p + nj] };
|
||||||
|
|
||||||
for (int k = 0; k < 2; ++k)
|
for (int k = 0; k < 2; ++k)
|
||||||
|
@ -1026,7 +1032,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
int p = i * nvp * 2;
|
int p = i * nvp * 2;
|
||||||
for (int j = 0; j < nvp; ++j)
|
for (int j = 0; j < nvp; ++j)
|
||||||
{
|
{
|
||||||
if (mesh.polys[p + j] == RcConstants.RC_MESH_NULL_IDX)
|
if (mesh.polys[p + j] == RcRecast.RC_MESH_NULL_IDX)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1036,7 +1042,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nj = (j + 1 >= nvp || mesh.polys[p + j + 1] == RcConstants.RC_MESH_NULL_IDX) ? 0 : j + 1;
|
int nj = (j + 1 >= nvp || mesh.polys[p + j + 1] == RcRecast.RC_MESH_NULL_IDX) ? 0 : j + 1;
|
||||||
int[] vi = { mesh.polys[p + j], mesh.polys[p + nj] };
|
int[] vi = { mesh.polys[p + j], mesh.polys[p + nj] };
|
||||||
|
|
||||||
int col = colb;
|
int col = colb;
|
||||||
|
@ -1327,7 +1333,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
|
|
||||||
for (int side = 0; side < 8; ++side)
|
for (int side = 0; side < 8; ++side)
|
||||||
{
|
{
|
||||||
int m = DtNavMesh.DT_EXT_LINK | (short)side;
|
int m = DT_EXT_LINK | (short)side;
|
||||||
|
|
||||||
for (int i = 0; i < tile.data.header.polyCount; ++i)
|
for (int i = 0; i < tile.data.header.polyCount; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using K4os.Compression.LZ4;
|
using K4os.Compression.LZ4;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Demo;
|
namespace DotRecast.Recast.Demo;
|
||||||
|
|
||||||
public static class KeyModState
|
public static class KeyModState
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Demo.Messages;
|
namespace DotRecast.Recast.Demo.Messages;
|
||||||
|
|
||||||
public class GeomLoadBeganEvent : IRecastDemoMessage
|
public class GeomLoadBeganEvent : IRecastDemoMessage
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Demo.Messages;
|
namespace DotRecast.Recast.Demo.Messages;
|
||||||
|
|
||||||
public interface IRecastDemoChannel
|
public interface IRecastDemoChannel
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Demo.Messages;
|
namespace DotRecast.Recast.Demo.Messages;
|
||||||
|
|
||||||
public class IRecastDemoMessage
|
public class IRecastDemoMessage
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Demo.Messages;
|
namespace DotRecast.Recast.Demo.Messages;
|
||||||
|
|
||||||
public class NavMeshBuildBeganEvent : IRecastDemoMessage
|
public class NavMeshBuildBeganEvent : IRecastDemoMessage
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Demo.Messages;
|
namespace DotRecast.Recast.Demo.Messages;
|
||||||
|
|
||||||
public class NavMeshLoadBeganEvent : IRecastDemoMessage
|
public class NavMeshLoadBeganEvent : IRecastDemoMessage
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Demo.Messages;
|
namespace DotRecast.Recast.Demo.Messages;
|
||||||
|
|
||||||
public class NavMeshSaveBeganEvent : IRecastDemoMessage
|
public class NavMeshSaveBeganEvent : IRecastDemoMessage
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Messages;
|
namespace DotRecast.Recast.Demo.Messages;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Recast.Demo.Logging.Sinks;
|
using DotRecast.Recast.Demo.Logging.Sinks;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Enrichers;
|
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo;
|
namespace DotRecast.Recast.Demo;
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ public static class Program
|
||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
Thread.CurrentThread.Name ??= "main";
|
||||||
|
|
||||||
InitializeWorkingDirectory();
|
InitializeWorkingDirectory();
|
||||||
InitializeLogger();
|
InitializeLogger();
|
||||||
StartDemo();
|
StartDemo();
|
||||||
|
@ -22,7 +24,6 @@ public static class Program
|
||||||
.MinimumLevel.Verbose()
|
.MinimumLevel.Verbose()
|
||||||
.Enrich.WithThreadId()
|
.Enrich.WithThreadId()
|
||||||
.Enrich.WithThreadName()
|
.Enrich.WithThreadName()
|
||||||
.Enrich.WithProperty(ThreadNameEnricher.ThreadNamePropertyName, "main")
|
|
||||||
.WriteTo.Async(c => c.LogMessageBroker(outputTemplate: format))
|
.WriteTo.Async(c => c.LogMessageBroker(outputTemplate: format))
|
||||||
.WriteTo.Async(c => c.Console(outputTemplate: format))
|
.WriteTo.Async(c => c.Console(outputTemplate: format))
|
||||||
.WriteTo.Async(c => c.File(
|
.WriteTo.Async(c => c.File(
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -25,6 +25,8 @@ using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using System.Runtime;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Silk.NET.Input;
|
using Silk.NET.Input;
|
||||||
|
@ -318,7 +320,7 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
|
|
||||||
if (null != mesh)
|
if (null != mesh)
|
||||||
{
|
{
|
||||||
_sample.Update(_sample.GetInputGeom(), ImmutableArray<RcBuilderResult>.Empty, mesh);
|
_sample.Update(_sample.GetInputGeom(), _sample.GetRecastConfig(), ImmutableArray<RcBuilderResult>.Empty, mesh);
|
||||||
_toolsetView.SetEnabled(true);
|
_toolsetView.SetEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,9 +411,17 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
|
|
||||||
var workingDirectory = Directory.GetCurrentDirectory();
|
var workingDirectory = Directory.GetCurrentDirectory();
|
||||||
Logger.Information($"Working directory - {workingDirectory}");
|
Logger.Information($"Working directory - {workingDirectory}");
|
||||||
Logger.Information($"ImGui.Net - version({ImGui.GetVersion()}) UI scale({scale}) fontSize({fontSize})");
|
|
||||||
Logger.Information($"Dotnet - {Environment.Version.ToString()} culture({currentCulture.Name})");
|
|
||||||
Logger.Information($"OS Version - {Environment.OSVersion} {bitness}");
|
Logger.Information($"OS Version - {Environment.OSVersion} {bitness}");
|
||||||
|
Logger.Information($"{RuntimeInformation.OSArchitecture} {RuntimeInformation.OSDescription}");
|
||||||
|
Logger.Information($"{RuntimeInformation.ProcessArchitecture} {RuntimeInformation.FrameworkDescription}");
|
||||||
|
Logger.Information($"Dotnet - {Environment.Version.ToString()} culture({currentCulture.Name})");
|
||||||
|
Logger.Information($"Processor Count : {Environment.ProcessorCount}");
|
||||||
|
|
||||||
|
Logger.Information($"Server garbage collection : {(GCSettings.IsServerGC ? "Enabled" : "Disabled")}");
|
||||||
|
Logger.Information($"Current latency mode for garbage collection: {GCSettings.LatencyMode}");
|
||||||
|
Logger.Information("");
|
||||||
|
|
||||||
|
Logger.Information($"ImGui.Net - version({ImGui.GetVersion()}) UI scale({scale}) fontSize({fontSize})");
|
||||||
Logger.Information($"{vendor} {rendererGl}");
|
Logger.Information($"{vendor} {rendererGl}");
|
||||||
Logger.Information($"gl version({version}) lang version({glslString})");
|
Logger.Information($"gl version({version}) lang version({glslString})");
|
||||||
}
|
}
|
||||||
|
@ -462,7 +472,7 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
var settings = _sample.GetSettings();
|
var settings = _sample.GetSettings();
|
||||||
RcVec3f bmin = _sample.GetInputGeom().GetMeshBoundsMin();
|
RcVec3f bmin = _sample.GetInputGeom().GetMeshBoundsMin();
|
||||||
RcVec3f bmax = _sample.GetInputGeom().GetMeshBoundsMax();
|
RcVec3f bmax = _sample.GetInputGeom().GetMeshBoundsMax();
|
||||||
RcCommons.CalcGridSize(bmin, bmax, settings.cellSize, out var gw, out var gh);
|
RcRecast.CalcGridSize(bmin, bmax, settings.cellSize, out var gw, out var gh);
|
||||||
settingsView.SetVoxels(gw, gh);
|
settingsView.SetVoxels(gw, gh);
|
||||||
settingsView.SetTiles(tileNavMeshBuilder.GetTiles(_sample.GetInputGeom(), settings.cellSize, settings.tileSize));
|
settingsView.SetTiles(tileNavMeshBuilder.GetTiles(_sample.GetInputGeom(), settings.cellSize, settings.tileSize));
|
||||||
settingsView.SetMaxTiles(tileNavMeshBuilder.GetMaxTiles(_sample.GetInputGeom(), settings.cellSize, settings.tileSize));
|
settingsView.SetMaxTiles(tileNavMeshBuilder.GetMaxTiles(_sample.GetInputGeom(), settings.cellSize, settings.tileSize));
|
||||||
|
@ -674,7 +684,7 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
{
|
{
|
||||||
var geom = LoadInputMesh(args.FilePath);
|
var geom = LoadInputMesh(args.FilePath);
|
||||||
|
|
||||||
_sample.Update(geom, ImmutableArray<RcBuilderResult>.Empty, null);
|
_sample.Update(geom, null, ImmutableArray<RcBuilderResult>.Empty, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnNavMeshBuildBegan(NavMeshBuildBeganEvent args)
|
private void OnNavMeshBuildBegan(NavMeshBuildBeganEvent args)
|
||||||
|
@ -709,7 +719,7 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_sample.Update(_sample.GetInputGeom(), buildResult.RecastBuilderResults, buildResult.NavMesh);
|
_sample.Update(_sample.GetInputGeom(), buildResult.Cfg, buildResult.RecastBuilderResults, buildResult.NavMesh);
|
||||||
_sample.SetChanged(false);
|
_sample.SetChanged(false);
|
||||||
settingsView.SetBuildTime((RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond);
|
settingsView.SetBuildTime((RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond);
|
||||||
//settingsUI.SetBuildTelemetry(buildResult.Item1.Select(x => x.GetTelemetry()).ToList());
|
//settingsUI.SetBuildTelemetry(buildResult.Item1.Select(x => x.GetTelemetry()).ToList());
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -18,12 +18,9 @@ freely, subject to the following restrictions:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Detour;
|
using DotRecast.Detour;
|
||||||
using DotRecast.Detour.Crowd;
|
using DotRecast.Detour.Crowd;
|
||||||
using DotRecast.Recast.Toolset.Builder;
|
|
||||||
using DotRecast.Recast.Demo.Draw;
|
using DotRecast.Recast.Demo.Draw;
|
||||||
using DotRecast.Recast.Toolset;
|
using DotRecast.Recast.Toolset;
|
||||||
using DotRecast.Recast.Toolset.Tools;
|
using DotRecast.Recast.Toolset.Tools;
|
||||||
|
@ -98,6 +95,11 @@ public class CrowdAgentProfilingSampleTool : ISampleTool
|
||||||
ImGui.SliderInt("Max Iterations", ref toolCfg.maxIterations, 0, 4000);
|
ImGui.SliderInt("Max Iterations", ref toolCfg.maxIterations, 0, 4000);
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
|
|
||||||
|
ImGui.Text("Debug Draw");
|
||||||
|
ImGui.Separator();
|
||||||
|
ImGui.Checkbox("Show Agents", ref toolCfg.showAgents);
|
||||||
|
ImGui.NewLine();
|
||||||
|
|
||||||
if (ImGui.Button("Start Crowd Profiling"))
|
if (ImGui.Button("Start Crowd Profiling"))
|
||||||
{
|
{
|
||||||
var settings = _sample.GetSettings();
|
var settings = _sample.GetSettings();
|
||||||
|
@ -118,11 +120,11 @@ public class CrowdAgentProfilingSampleTool : ISampleTool
|
||||||
ImGui.Text($"{rtt.Key}: {rtt.Micros} us");
|
ImGui.Text($"{rtt.Key}: {rtt.Micros} us");
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.Text($"Sampling Time: {_tool.GetCrowdUpdateSamplingTime()} ms");
|
ImGui.Text($"Sampling Time: {_tool.GetCrowdUpdateSamplingTime():0.00} ms");
|
||||||
ImGui.Text($"Current Update Time: {_tool.GetCrowdUpdateTime()} ms");
|
ImGui.Text($"Current Update Time: {_tool.GetCrowdUpdateTime():0.00} ms");
|
||||||
ImGui.Text($"Avg Update Time: {_tool.GetCrowdUpdateAvgTime()} ms");
|
ImGui.Text($"Avg Update Time: {_tool.GetCrowdUpdateAvgTime():0.00} ms");
|
||||||
ImGui.Text($"Max Update Time: {_tool.GetCrowdUpdateMaxTime()} ms");
|
ImGui.Text($"Max Update Time: {_tool.GetCrowdUpdateMaxTime():0.00} ms");
|
||||||
ImGui.Text($"Min Update Time: {_tool.GetCrowdUpdateMinTime()} ms");
|
ImGui.Text($"Min Update Time: {_tool.GetCrowdUpdateMinTime():0.00} ms");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +134,7 @@ public class CrowdAgentProfilingSampleTool : ISampleTool
|
||||||
dd.DepthMask(false);
|
dd.DepthMask(false);
|
||||||
|
|
||||||
var crowd = _tool.GetCrowd();
|
var crowd = _tool.GetCrowd();
|
||||||
if (crowd != null)
|
if (crowd != null && _tool.GetToolConfig().showAgents)
|
||||||
{
|
{
|
||||||
foreach (DtCrowdAgent ag in crowd.GetActiveAgents())
|
foreach (DtCrowdAgent ag in crowd.GetActiveAgents())
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -234,7 +234,7 @@ public class CrowdSampleTool : ISampleTool
|
||||||
dd.Vertex(prev.X, prev.Y + 0.1f, prev.Z, DuRGBA(0, 0, 0, (int)(128 * preva)));
|
dd.Vertex(prev.X, prev.Y + 0.1f, prev.Z, DuRGBA(0, 0, 0, (int)(128 * preva)));
|
||||||
dd.Vertex(trail.trail[v], trail.trail[v + 1] + 0.1f, trail.trail[v + 2], DuRGBA(0, 0, 0, (int)(128 * a)));
|
dd.Vertex(trail.trail[v], trail.trail[v + 1] + 0.1f, trail.trail[v + 2], DuRGBA(0, 0, 0, (int)(128 * a)));
|
||||||
preva = a;
|
preva = a;
|
||||||
prev = RcVecUtils.Create(trail.trail, v);
|
prev = RcVec.Create(trail.trail, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
dd.End();
|
dd.End();
|
||||||
|
@ -251,10 +251,10 @@ public class CrowdSampleTool : ISampleTool
|
||||||
|
|
||||||
if (_showCorners)
|
if (_showCorners)
|
||||||
{
|
{
|
||||||
if (0 < ag.corners.Count)
|
if (0 < ag.ncorners)
|
||||||
{
|
{
|
||||||
dd.Begin(LINES, 2.0f);
|
dd.Begin(LINES, 2.0f);
|
||||||
for (int j = 0; j < ag.corners.Count; ++j)
|
for (int j = 0; j < ag.ncorners; ++j)
|
||||||
{
|
{
|
||||||
RcVec3f va = j == 0 ? pos : ag.corners[j - 1].pos;
|
RcVec3f va = j == 0 ? pos : ag.corners[j - 1].pos;
|
||||||
RcVec3f vb = ag.corners[j].pos;
|
RcVec3f vb = ag.corners[j].pos;
|
||||||
|
@ -262,10 +262,10 @@ public class CrowdSampleTool : ISampleTool
|
||||||
dd.Vertex(vb.X, vb.Y + radius, vb.Z, DuRGBA(128, 0, 0, 192));
|
dd.Vertex(vb.X, vb.Y + radius, vb.Z, DuRGBA(128, 0, 0, 192));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ag.corners[ag.corners.Count - 1].flags
|
if ((ag.corners[ag.ncorners - 1].flags
|
||||||
& DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
& DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
||||||
{
|
{
|
||||||
RcVec3f v = ag.corners[ag.corners.Count - 1].pos;
|
RcVec3f v = ag.corners[ag.ncorners - 1].pos;
|
||||||
dd.Vertex(v.X, v.Y, v.Z, DuRGBA(192, 0, 0, 192));
|
dd.Vertex(v.X, v.Y, v.Z, DuRGBA(192, 0, 0, 192));
|
||||||
dd.Vertex(v.X, v.Y + radius * 2, v.Z, DuRGBA(192, 0, 0, 192));
|
dd.Vertex(v.X, v.Y + radius * 2, v.Z, DuRGBA(192, 0, 0, 192));
|
||||||
}
|
}
|
||||||
|
@ -325,7 +325,7 @@ public class CrowdSampleTool : ISampleTool
|
||||||
2.0f);
|
2.0f);
|
||||||
|
|
||||||
dd.Begin(LINES, 2.0f);
|
dd.Begin(LINES, 2.0f);
|
||||||
for (int j = 0; j < ag.neis.Count; ++j)
|
for (int j = 0; j < ag.nneis; ++j)
|
||||||
{
|
{
|
||||||
DtCrowdAgent nei = ag.neis[j].agent;
|
DtCrowdAgent nei = ag.neis[j].agent;
|
||||||
if (nei != null)
|
if (nei != null)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -25,6 +25,7 @@ using DotRecast.Core;
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Detour.Dynamic;
|
using DotRecast.Detour.Dynamic;
|
||||||
|
using DotRecast.Detour.Dynamic.Io;
|
||||||
using DotRecast.Recast.Toolset;
|
using DotRecast.Recast.Toolset;
|
||||||
using DotRecast.Recast.Toolset.Tools;
|
using DotRecast.Recast.Toolset.Tools;
|
||||||
using DotRecast.Recast.Demo.Draw;
|
using DotRecast.Recast.Demo.Draw;
|
||||||
|
@ -116,8 +117,17 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
|
|
||||||
if (mode == RcDynamicUpdateToolMode.BUILD)
|
if (mode == RcDynamicUpdateToolMode.BUILD)
|
||||||
{
|
{
|
||||||
var loadVoxelPopupStrId = "Load Voxels Popup";
|
const string loadVoxelPopupStrId = "Load Voxels Popup";
|
||||||
|
|
||||||
bool isLoadVoxelPopup = true;
|
bool isLoadVoxelPopup = true;
|
||||||
|
if (_sample.GetRecastResults() != null && _sample.GetRecastConfig() != null)
|
||||||
|
{
|
||||||
|
if (ImGui.Button("Import Voxels"))
|
||||||
|
{
|
||||||
|
Copy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ImGui.Button("Load Voxels..."))
|
if (ImGui.Button("Load Voxels..."))
|
||||||
{
|
{
|
||||||
ImGui.OpenPopup(loadVoxelPopupStrId);
|
ImGui.OpenPopup(loadVoxelPopupStrId);
|
||||||
|
@ -135,7 +145,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
ImGui.EndPopup();
|
ImGui.EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
var saveVoxelPopupStrId = "Save Voxels Popup";
|
const string saveVoxelPopupStrId = "Save Voxels Popup";
|
||||||
bool isSaveVoxelPopup = true;
|
bool isSaveVoxelPopup = true;
|
||||||
|
|
||||||
var dynaMesh = _tool.GetDynamicNavMesh();
|
var dynaMesh = _tool.GetDynamicNavMesh();
|
||||||
|
@ -144,7 +154,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
ImGui.Checkbox("Compression", ref compression);
|
ImGui.Checkbox("Compression", ref compression);
|
||||||
if (ImGui.Button("Save Voxels..."))
|
if (ImGui.Button("Save Voxels..."))
|
||||||
{
|
{
|
||||||
ImGui.BeginPopup(saveVoxelPopupStrId);
|
ImGui.OpenPopup(saveVoxelPopupStrId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui.BeginPopupModal(saveVoxelPopupStrId, ref isSaveVoxelPopup, ImGuiWindowFlags.NoTitleBar))
|
if (ImGui.BeginPopupModal(saveVoxelPopupStrId, ref isSaveVoxelPopup, ImGuiWindowFlags.NoTitleBar))
|
||||||
|
@ -152,9 +162,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
var picker = ImFilePicker.GetFilePicker(saveVoxelPopupStrId, Path.Combine(Environment.CurrentDirectory), ".voxels");
|
var picker = ImFilePicker.GetFilePicker(saveVoxelPopupStrId, Path.Combine(Environment.CurrentDirectory), ".voxels");
|
||||||
if (picker.Draw())
|
if (picker.Draw())
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(picker.SelectedFile))
|
Save(picker.SelectedFile);
|
||||||
Save(picker.SelectedFile);
|
|
||||||
|
|
||||||
ImFilePicker.RemoveFilePicker(saveVoxelPopupStrId);
|
ImFilePicker.RemoveFilePicker(saveVoxelPopupStrId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +419,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
{
|
{
|
||||||
buildTime = (RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond;
|
buildTime = (RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond;
|
||||||
var dynaMesh = _tool.GetDynamicNavMesh();
|
var dynaMesh = _tool.GetDynamicNavMesh();
|
||||||
_sample.Update(null, dynaMesh.RecastResults(), dynaMesh.NavMesh());
|
_sample.Update(null, null, dynaMesh.RecastResults(), dynaMesh.NavMesh());
|
||||||
_sample.SetChanged(false);
|
_sample.SetChanged(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -421,6 +429,15 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Copy()
|
||||||
|
{
|
||||||
|
if (_sample.GetRecastResults() != null && _sample.GetRecastConfig() != null)
|
||||||
|
{
|
||||||
|
var dynaMesh = _tool.Copy(_sample.GetRecastConfig(), _sample.GetRecastResults());
|
||||||
|
UpdateFrom(dynaMesh.config);
|
||||||
|
BuildDynaMesh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void Load(string filename)
|
private void Load(string filename)
|
||||||
{
|
{
|
||||||
|
@ -458,7 +475,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTime = (RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond;
|
buildTime = (RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond;
|
||||||
_sample.Update(null, dynaMesh.RecastResults(), dynaMesh.NavMesh());
|
_sample.Update(null, null, dynaMesh.RecastResults(), dynaMesh.NavMesh());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateTo(DtDynamicNavMeshConfig config)
|
private void UpdateTo(DtDynamicNavMeshConfig config)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Recast.Demo.Draw;
|
using DotRecast.Recast.Demo.Draw;
|
||||||
|
@ -36,16 +36,11 @@ public static class GizmoRenderer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetColorByNormal(float[] vertices, int v0, int v1, int v2)
|
public static int GetColorByNormal(RcVec3f v0, RcVec3f v1, RcVec3f v2)
|
||||||
{
|
{
|
||||||
RcVec3f e0 = new RcVec3f();
|
|
||||||
RcVec3f e1 = new RcVec3f();
|
|
||||||
RcVec3f normal = new RcVec3f();
|
RcVec3f normal = new RcVec3f();
|
||||||
for (int j = 0; j < 3; ++j)
|
RcVec3f e0 = v1 - v0;
|
||||||
{
|
RcVec3f e1 = v2 - v0;
|
||||||
e0 = RcVecUtils.Subtract(vertices, v1, v0);
|
|
||||||
e1 = RcVecUtils.Subtract(vertices, v2, v0);
|
|
||||||
}
|
|
||||||
|
|
||||||
normal.X = e0.Y * e1.Z - e0.Z * e1.Y;
|
normal.X = e0.Y * e1.Z - e0.Z * e1.Y;
|
||||||
normal.Y = e0.Z * e1.X - e0.X * e1.Z;
|
normal.Y = e0.Z * e1.X - e0.X * e1.Z;
|
||||||
|
@ -65,7 +60,7 @@ public static class GizmoRenderer
|
||||||
var trX = new RcVec3f(box.halfEdges[0].X, box.halfEdges[1].X, box.halfEdges[2].X);
|
var trX = new RcVec3f(box.halfEdges[0].X, box.halfEdges[1].X, box.halfEdges[2].X);
|
||||||
var trY = new RcVec3f(box.halfEdges[0].Y, box.halfEdges[1].Y, box.halfEdges[2].Y);
|
var trY = new RcVec3f(box.halfEdges[0].Y, box.halfEdges[1].Y, box.halfEdges[2].Y);
|
||||||
var trZ = new RcVec3f(box.halfEdges[0].Z, box.halfEdges[1].Z, box.halfEdges[2].Z);
|
var trZ = new RcVec3f(box.halfEdges[0].Z, box.halfEdges[1].Z, box.halfEdges[2].Z);
|
||||||
float[] vertices = new float[8 * 3];
|
Span<float> vertices = stackalloc float[8 * 3];
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
vertices[i * 3 + 0] = RcVec3f.Dot(RcBoxGizmo.VERTS[i], trX) + box.center.X;
|
vertices[i * 3 + 0] = RcVec3f.Dot(RcBoxGizmo.VERTS[i], trX) + box.center.X;
|
||||||
|
@ -160,13 +155,13 @@ public static class GizmoRenderer
|
||||||
debugDraw.Begin(DebugDrawPrimitives.TRIS);
|
debugDraw.Begin(DebugDrawPrimitives.TRIS);
|
||||||
for (int i = 0; i < trimesh.triangles.Length; i += 3)
|
for (int i = 0; i < trimesh.triangles.Length; i += 3)
|
||||||
{
|
{
|
||||||
int v0 = 3 * trimesh.triangles[i];
|
RcVec3f v0 = RcVec.Create(trimesh.vertices, 3 * trimesh.triangles[i]);
|
||||||
int v1 = 3 * trimesh.triangles[i + 1];
|
RcVec3f v1 = RcVec.Create(trimesh.vertices, 3 * trimesh.triangles[i + 1]);
|
||||||
int v2 = 3 * trimesh.triangles[i + 2];
|
RcVec3f v2 = RcVec.Create(trimesh.vertices, 3 * trimesh.triangles[i + 2]);
|
||||||
int col = GetColorByNormal(trimesh.vertices, v0, v1, v2);
|
int col = GetColorByNormal(v0, v1, v2);
|
||||||
debugDraw.Vertex(trimesh.vertices[v0], trimesh.vertices[v0 + 1], trimesh.vertices[v0 + 2], col);
|
debugDraw.Vertex(v0.X, v0.Y, v0.Z, col);
|
||||||
debugDraw.Vertex(trimesh.vertices[v1], trimesh.vertices[v1 + 1], trimesh.vertices[v1 + 2], col);
|
debugDraw.Vertex(v1.X, v1.Y, v1.Z, col);
|
||||||
debugDraw.Vertex(trimesh.vertices[v2], trimesh.vertices[v2 + 1], trimesh.vertices[v2 + 2], col);
|
debugDraw.Vertex(v2.X, v2.Y, v2.Z, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
debugDraw.End();
|
debugDraw.End();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
|
|
@ -417,7 +417,7 @@ public class JumpLinkBuilderSampleTool : ISampleTool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void DrawTrajectory(RecastDebugDraw dd, JumpLink link, RcVec3f pa, RcVec3f pb, Trajectory tra, int cola)
|
private void DrawTrajectory(RecastDebugDraw dd, JumpLink link, RcVec3f pa, RcVec3f pb, ITrajectory tra, int cola)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Detour.TileCache;
|
using DotRecast.Detour.TileCache;
|
||||||
using DotRecast.Detour.TileCache.Io.Compress;
|
using DotRecast.Detour.TileCache.Io.Compress;
|
||||||
|
@ -32,7 +32,7 @@ public class ObstacleSampleTool : ISampleTool
|
||||||
var buildResult = _tool.Build(geom, settings, RcByteOrder.LITTLE_ENDIAN, true);
|
var buildResult = _tool.Build(geom, settings, RcByteOrder.LITTLE_ENDIAN, true);
|
||||||
if (buildResult.Success)
|
if (buildResult.Success)
|
||||||
{
|
{
|
||||||
_sample.Update(_sample.GetInputGeom(), buildResult.RecastBuilderResults, buildResult.NavMesh);
|
_sample.Update(_sample.GetInputGeom(), buildResult.Cfg, buildResult.RecastBuilderResults, buildResult.NavMesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
|
|
@ -57,7 +57,8 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
private bool m_hitResult;
|
private bool m_hitResult;
|
||||||
|
|
||||||
private float m_distanceToWall;
|
private float m_distanceToWall;
|
||||||
private List<DtStraightPath> m_straightPath;
|
private DtStraightPath[] m_straightPath;
|
||||||
|
private int m_straightPathCount;
|
||||||
private List<long> m_polys;
|
private List<long> m_polys;
|
||||||
private List<long> m_parent;
|
private List<long> m_parent;
|
||||||
private float m_neighbourhoodRadius;
|
private float m_neighbourhoodRadius;
|
||||||
|
@ -77,6 +78,8 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
SampleAreaModifications.SAMPLE_POLYFLAGS_DISABLED,
|
SampleAreaModifications.SAMPLE_POLYFLAGS_DISABLED,
|
||||||
new float[] { 1f, 1f, 1f, 1f, 2f, 1.5f }
|
new float[] { 1f, 1f, 1f, 1f, 2f, 1.5f }
|
||||||
);
|
);
|
||||||
|
m_straightPath = new DtStraightPath[MAX_POLYS];
|
||||||
|
m_straightPathCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Layout()
|
public void Layout()
|
||||||
|
@ -137,22 +140,22 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
ImGui.Text("Common");
|
ImGui.Text("Common");
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
ImGui.Text("Include Flags");
|
ImGui.Text("+ Include Flags");
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
ImGui.CheckboxFlags("Walk", ref _includeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_WALK);
|
ImGui.CheckboxFlags("+ Walk", ref _includeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_WALK);
|
||||||
ImGui.CheckboxFlags("Swim", ref _includeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_SWIM);
|
ImGui.CheckboxFlags("+ Swim", ref _includeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_SWIM);
|
||||||
ImGui.CheckboxFlags("Door", ref _includeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_DOOR);
|
ImGui.CheckboxFlags("+ Door", ref _includeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_DOOR);
|
||||||
ImGui.CheckboxFlags("Jump", ref _includeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_JUMP);
|
ImGui.CheckboxFlags("+ Jump", ref _includeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_JUMP);
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
|
|
||||||
m_filter.SetIncludeFlags(_includeFlags);
|
m_filter.SetIncludeFlags(_includeFlags);
|
||||||
|
|
||||||
ImGui.Text("Exclude Flags");
|
ImGui.Text("- Exclude Flags");
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
ImGui.CheckboxFlags("Walk", ref _excludeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_WALK);
|
ImGui.CheckboxFlags("- Walk", ref _excludeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_WALK);
|
||||||
ImGui.CheckboxFlags("Swim", ref _excludeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_SWIM);
|
ImGui.CheckboxFlags("- Swim", ref _excludeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_SWIM);
|
||||||
ImGui.CheckboxFlags("Door", ref _excludeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_DOOR);
|
ImGui.CheckboxFlags("- Door", ref _excludeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_DOOR);
|
||||||
ImGui.CheckboxFlags("Jump", ref _excludeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_JUMP);
|
ImGui.CheckboxFlags("- Jump", ref _excludeFlags, SampleAreaModifications.SAMPLE_POLYFLAGS_JUMP);
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
|
|
||||||
m_filter.SetExcludeFlags(_excludeFlags);
|
m_filter.SetExcludeFlags(_excludeFlags);
|
||||||
|
@ -284,7 +287,7 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
int spathCol = DuRGBA(64, 16, 0, 220);
|
int spathCol = DuRGBA(64, 16, 0, 220);
|
||||||
int offMeshCol = DuRGBA(128, 96, 0, 220);
|
int offMeshCol = DuRGBA(128, 96, 0, 220);
|
||||||
dd.Begin(LINES, 2.0f);
|
dd.Begin(LINES, 2.0f);
|
||||||
for (int i = 0; i < m_straightPath.Count - 1; ++i)
|
for (int i = 0; i < m_straightPathCount - 1; ++i)
|
||||||
{
|
{
|
||||||
DtStraightPath straightPathItem = m_straightPath[i];
|
DtStraightPath straightPathItem = m_straightPath[i];
|
||||||
DtStraightPath straightPathItem2 = m_straightPath[i + 1];
|
DtStraightPath straightPathItem2 = m_straightPath[i + 1];
|
||||||
|
@ -304,7 +307,7 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
|
|
||||||
dd.End();
|
dd.End();
|
||||||
dd.Begin(POINTS, 6.0f);
|
dd.Begin(POINTS, 6.0f);
|
||||||
for (int i = 0; i < m_straightPath.Count; ++i)
|
for (int i = 0; i < m_straightPathCount; ++i)
|
||||||
{
|
{
|
||||||
DtStraightPath straightPathItem = m_straightPath[i];
|
DtStraightPath straightPathItem = m_straightPath[i];
|
||||||
int col;
|
int col;
|
||||||
|
@ -349,7 +352,7 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
dd.DepthMask(false);
|
dd.DepthMask(false);
|
||||||
int spathCol = m_hitResult ? DuRGBA(64, 16, 0, 220) : DuRGBA(240, 240, 240, 220);
|
int spathCol = m_hitResult ? DuRGBA(64, 16, 0, 220) : DuRGBA(240, 240, 240, 220);
|
||||||
dd.Begin(LINES, 2.0f);
|
dd.Begin(LINES, 2.0f);
|
||||||
for (int i = 0; i < m_straightPath.Count - 1; ++i)
|
for (int i = 0; i < m_straightPathCount - 1; ++i)
|
||||||
{
|
{
|
||||||
DtStraightPath straightPathItem = m_straightPath[i];
|
DtStraightPath straightPathItem = m_straightPath[i];
|
||||||
DtStraightPath straightPathItem2 = m_straightPath[i + 1];
|
DtStraightPath straightPathItem2 = m_straightPath[i + 1];
|
||||||
|
@ -359,7 +362,7 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
|
|
||||||
dd.End();
|
dd.End();
|
||||||
dd.Begin(POINTS, 4.0f);
|
dd.Begin(POINTS, 4.0f);
|
||||||
for (int i = 0; i < m_straightPath.Count; ++i)
|
for (int i = 0; i < m_straightPathCount; ++i)
|
||||||
{
|
{
|
||||||
DtStraightPath straightPathItem = m_straightPath[i];
|
DtStraightPath straightPathItem = m_straightPath[i];
|
||||||
dd.Vertex(straightPathItem.pos.X, straightPathItem.pos.Y + 0.4f, straightPathItem.pos.Z, spathCol);
|
dd.Vertex(straightPathItem.pos.X, straightPathItem.pos.Y + 0.4f, straightPathItem.pos.Z, spathCol);
|
||||||
|
@ -469,8 +472,9 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
{
|
{
|
||||||
if (m_polys != null)
|
if (m_polys != null)
|
||||||
{
|
{
|
||||||
var segmentVerts = new List<RcSegmentVert>();
|
const int MAX_SEGS = DtDetour.DT_VERTS_PER_POLYGON * 4;
|
||||||
var segmentRefs = new List<long>();
|
Span<RcSegmentVert> segs = stackalloc RcSegmentVert[MAX_SEGS];
|
||||||
|
Span<long> refs = stackalloc long[MAX_SEGS];
|
||||||
|
|
||||||
for (int i = 0; i < m_polys.Count; i++)
|
for (int i = 0; i < m_polys.Count; i++)
|
||||||
{
|
{
|
||||||
|
@ -488,18 +492,20 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
dd.DepthMask(true);
|
dd.DepthMask(true);
|
||||||
if (_sample.GetNavMeshQuery() != null)
|
if (_sample.GetNavMeshQuery() != null)
|
||||||
{
|
{
|
||||||
|
int nsegs = 0;
|
||||||
var result = _sample
|
var result = _sample
|
||||||
.GetNavMeshQuery()
|
.GetNavMeshQuery()
|
||||||
.GetPolyWallSegments(m_polys[i], false, m_filter, ref segmentVerts, ref segmentRefs);
|
.GetPolyWallSegments(m_polys[i], m_filter, segs, refs, ref nsegs, MAX_SEGS);
|
||||||
|
|
||||||
if (result.Succeeded())
|
if (result.Succeeded())
|
||||||
{
|
{
|
||||||
dd.Begin(LINES, 2.0f);
|
dd.Begin(LINES, 2.0f);
|
||||||
for (int j = 0; j < segmentVerts.Count; ++j)
|
for (int j = 0; j < nsegs; ++j)
|
||||||
{
|
{
|
||||||
RcSegmentVert s = segmentVerts[j];
|
ref RcSegmentVert s = ref segs[j];
|
||||||
var v0 = s.vmin;
|
var v0 = s.vmin;
|
||||||
var s3 = s.vmax;
|
var s3 = s.vmax;
|
||||||
|
|
||||||
// Skip too distant segments.
|
// Skip too distant segments.
|
||||||
var distSqr = DtUtils.DistancePtSegSqr2D(m_spos, v0, s3, out var tseg);
|
var distSqr = DtUtils.DistancePtSegSqr2D(m_spos, v0, s3, out var tseg);
|
||||||
if (distSqr > RcMath.Sqr(m_neighbourhoodRadius))
|
if (distSqr > RcMath.Sqr(m_neighbourhoodRadius))
|
||||||
|
@ -508,12 +514,13 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
}
|
}
|
||||||
|
|
||||||
RcVec3f delta = RcVec3f.Subtract(s3, s.vmin);
|
RcVec3f delta = RcVec3f.Subtract(s3, s.vmin);
|
||||||
RcVec3f p0 = RcVecUtils.Mad(s.vmin, delta, 0.5f);
|
RcVec3f p0 = RcVec.Mad(s.vmin, delta, 0.5f);
|
||||||
RcVec3f norm = new RcVec3f(delta.Z, 0, -delta.X);
|
RcVec3f norm = new RcVec3f(delta.Z, 0, -delta.X);
|
||||||
norm = RcVec3f.Normalize(norm);
|
norm = RcVec3f.Normalize(norm);
|
||||||
RcVec3f p1 = RcVecUtils.Mad(p0, norm, agentRadius * 0.5f);
|
RcVec3f p1 = RcVec.Mad(p0, norm, agentRadius * 0.5f);
|
||||||
|
|
||||||
// Skip backfacing segments.
|
// Skip backfacing segments.
|
||||||
if (segmentRefs[j] != 0)
|
if (refs[j] != 0)
|
||||||
{
|
{
|
||||||
int col = DuRGBA(255, 255, 255, 32);
|
int col = DuRGBA(255, 255, 255, 32);
|
||||||
dd.Vertex(s.vmin.X, s.vmin.Y + agentClimb, s.vmin.Z, col);
|
dd.Vertex(s.vmin.X, s.vmin.Y + agentClimb, s.vmin.Z, col);
|
||||||
|
@ -661,23 +668,23 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
if (_mode == RcTestNavmeshToolMode.PATHFIND_FOLLOW)
|
if (_mode == RcTestNavmeshToolMode.PATHFIND_FOLLOW)
|
||||||
{
|
{
|
||||||
_tool.FindFollowPath(navMesh, navQuery, m_startRef, m_endRef, m_spos, m_epos, m_filter, _enableRaycast,
|
_tool.FindFollowPath(navMesh, navQuery, m_startRef, m_endRef, m_spos, m_epos, m_filter, _enableRaycast,
|
||||||
ref m_polys, ref m_smoothPath);
|
ref m_polys, m_polys?.Count ?? 0, ref m_smoothPath);
|
||||||
}
|
}
|
||||||
else if (_mode == RcTestNavmeshToolMode.PATHFIND_STRAIGHT)
|
else if (_mode == RcTestNavmeshToolMode.PATHFIND_STRAIGHT)
|
||||||
{
|
{
|
||||||
_tool.FindStraightPath(navQuery, m_startRef, m_endRef, m_spos, m_epos, m_filter, _enableRaycast,
|
_tool.FindStraightPath(navQuery, m_startRef, m_endRef, m_spos, m_epos, m_filter, _enableRaycast,
|
||||||
ref m_polys, ref m_straightPath, _straightPathOption);
|
ref m_polys, m_straightPath, out m_straightPathCount, MAX_POLYS, _straightPathOption);
|
||||||
}
|
}
|
||||||
else if (_mode == RcTestNavmeshToolMode.PATHFIND_SLICED)
|
else if (_mode == RcTestNavmeshToolMode.PATHFIND_SLICED)
|
||||||
{
|
{
|
||||||
m_polys?.Clear();
|
m_polys?.Clear();
|
||||||
m_straightPath?.Clear();
|
m_straightPathCount = 0;
|
||||||
m_pathFindStatus = _tool.InitSlicedFindPath(navQuery, m_startRef, m_endRef, m_spos, m_epos, m_filter, _enableRaycast);
|
m_pathFindStatus = _tool.InitSlicedFindPath(navQuery, m_startRef, m_endRef, m_spos, m_epos, m_filter, _enableRaycast);
|
||||||
}
|
}
|
||||||
else if (_mode == RcTestNavmeshToolMode.RAYCAST)
|
else if (_mode == RcTestNavmeshToolMode.RAYCAST)
|
||||||
{
|
{
|
||||||
_tool.Raycast(navQuery, m_startRef, m_endRef, m_spos, m_epos, m_filter,
|
_tool.Raycast(navQuery, m_startRef, m_endRef, m_spos, m_epos, m_filter,
|
||||||
ref m_polys, ref m_straightPath, ref m_hitPos, ref m_hitNormal, ref m_hitResult);
|
ref m_polys, m_straightPath, out m_straightPathCount, MAX_POLYS, ref m_hitPos, ref m_hitNormal, ref m_hitResult);
|
||||||
}
|
}
|
||||||
else if (_mode == RcTestNavmeshToolMode.DISTANCE_TO_WALL)
|
else if (_mode == RcTestNavmeshToolMode.DISTANCE_TO_WALL)
|
||||||
{
|
{
|
||||||
|
@ -712,7 +719,7 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
|
|
||||||
if (m_pathFindStatus.InProgress())
|
if (m_pathFindStatus.InProgress())
|
||||||
{
|
{
|
||||||
m_pathFindStatus = _tool.UpdateSlicedFindPath(navQuery, 1, m_endRef, m_spos, m_epos, ref m_polys, ref m_straightPath);
|
m_pathFindStatus = _tool.UpdateSlicedFindPath(navQuery, 1, m_endRef, m_spos, m_epos, ref m_polys, m_straightPath, out m_straightPathCount, MAX_POLYS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Recast.Demo.Draw;
|
using DotRecast.Recast.Demo.Draw;
|
||||||
using DotRecast.Recast.Toolset;
|
using DotRecast.Recast.Toolset;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
@ -69,7 +69,7 @@ public class ImFilePicker
|
||||||
ImGui.Text("Current Folder: " + CurrentFolder);
|
ImGui.Text("Current Folder: " + CurrentFolder);
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
if (ImGui.BeginChildFrame(1, new Vector2(1024, 400)))
|
if (ImGui.BeginChild(1, new Vector2(1024, 400)))
|
||||||
{
|
{
|
||||||
var di = new DirectoryInfo(CurrentFolder);
|
var di = new DirectoryInfo(CurrentFolder);
|
||||||
if (di.Exists)
|
if (di.Exists)
|
||||||
|
@ -111,7 +111,7 @@ public class ImFilePicker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.EndChildFrame();
|
ImGui.EndChild();
|
||||||
|
|
||||||
|
|
||||||
if (ImGui.Button("Cancel"))
|
if (ImGui.Button("Cancel"))
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -80,7 +80,7 @@ public class RcLogView : IRcView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (ImGui.BeginChild("scrolling", Vector2.Zero, false, ImGuiWindowFlags.HorizontalScrollbar))
|
if (ImGui.BeginChild("scrolling", Vector2.Zero, ImGuiChildFlags.None, ImGuiWindowFlags.HorizontalScrollbar))
|
||||||
{
|
{
|
||||||
_isHovered = ImGui.IsWindowHovered(ImGuiHoveredFlags.RectOnly | ImGuiHoveredFlags.RootAndChildWindows);
|
_isHovered = ImGui.IsWindowHovered(ImGuiHoveredFlags.RectOnly | ImGuiHoveredFlags.RootAndChildWindows);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.UI;
|
namespace DotRecast.Recast.Demo.UI;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,7 +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
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Demo.UI.ViewModels;
|
namespace DotRecast.Recast.Demo.UI.ViewModels;
|
||||||
|
|
||||||
public class LogMessageItem
|
public class LogMessageItem
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Detour;
|
using DotRecast.Detour;
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
public class NavMeshBuildResult
|
public class NavMeshBuildResult
|
||||||
{
|
{
|
||||||
public readonly bool Success;
|
public readonly bool Success;
|
||||||
|
public readonly RcConfig Cfg;
|
||||||
public readonly IList<RcBuilderResult> RecastBuilderResults;
|
public readonly IList<RcBuilderResult> RecastBuilderResults;
|
||||||
public readonly DtNavMesh NavMesh;
|
public readonly DtNavMesh NavMesh;
|
||||||
|
|
||||||
|
@ -17,11 +18,22 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
NavMesh = null;
|
NavMesh = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NavMeshBuildResult(IList<RcBuilderResult> recastBuilderResults, DtNavMesh navMesh)
|
// for solo
|
||||||
|
public NavMeshBuildResult(RcConfig cfg, IList<RcBuilderResult> recastBuilderResults, DtNavMesh navMesh)
|
||||||
{
|
{
|
||||||
Success = true;
|
Success = true;
|
||||||
|
Cfg = cfg;
|
||||||
RecastBuilderResults = recastBuilderResults;
|
RecastBuilderResults = recastBuilderResults;
|
||||||
NavMesh = navMesh;
|
NavMesh = navMesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for tiles
|
||||||
|
public NavMeshBuildResult(RcConfig cfg, IList<RcBuilderResult> recastBuilderResults)
|
||||||
|
{
|
||||||
|
Success = true;
|
||||||
|
Cfg = cfg;
|
||||||
|
RecastBuilderResults = recastBuilderResults;
|
||||||
|
NavMesh = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -34,12 +34,12 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
public const int SAMPLE_POLYAREA_TYPE_JUMP_AUTO = 0x6;
|
public const int SAMPLE_POLYAREA_TYPE_JUMP_AUTO = 0x6;
|
||||||
public const int SAMPLE_POLYAREA_TYPE_WALKABLE = 0x3f;
|
public const int SAMPLE_POLYAREA_TYPE_WALKABLE = 0x3f;
|
||||||
|
|
||||||
public static readonly int SAMPLE_POLYFLAGS_WALK = 0x01; // Ability to walk (ground, grass, road)
|
public const int SAMPLE_POLYFLAGS_WALK = 0x01; // Ability to walk (ground, grass, road)
|
||||||
public static readonly int SAMPLE_POLYFLAGS_SWIM = 0x02; // Ability to swim (water).
|
public const int SAMPLE_POLYFLAGS_SWIM = 0x02; // Ability to swim (water).
|
||||||
public static readonly int SAMPLE_POLYFLAGS_DOOR = 0x04; // Ability to move through doors.
|
public const int SAMPLE_POLYFLAGS_DOOR = 0x04; // Ability to move through doors.
|
||||||
public static readonly int SAMPLE_POLYFLAGS_JUMP = 0x08; // Ability to jump.
|
public const int SAMPLE_POLYFLAGS_JUMP = 0x08; // Ability to jump.
|
||||||
public static readonly int SAMPLE_POLYFLAGS_DISABLED = 0x10; // Disabled polygon
|
public const int SAMPLE_POLYFLAGS_DISABLED = 0x10; // Disabled polygon
|
||||||
public static readonly int SAMPLE_POLYFLAGS_ALL = 0xffff; // All abilities.
|
public const int SAMPLE_POLYFLAGS_ALL = 0xffff; // All abilities.
|
||||||
|
|
||||||
public static readonly RcAreaModification SAMPLE_AREAMOD_WALKABLE = new RcAreaModification(SAMPLE_POLYAREA_TYPE_WALKABLE);
|
public static readonly RcAreaModification SAMPLE_AREAMOD_WALKABLE = new RcAreaModification(SAMPLE_POLYAREA_TYPE_WALKABLE);
|
||||||
public static readonly RcAreaModification SAMPLE_AREAMOD_GROUND = new RcAreaModification(SAMPLE_POLYAREA_TYPE_GROUND);
|
public static readonly RcAreaModification SAMPLE_AREAMOD_GROUND = new RcAreaModification(SAMPLE_POLYAREA_TYPE_GROUND);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -68,12 +69,19 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
}
|
}
|
||||||
|
|
||||||
var navMesh = BuildNavMesh(meshData, vertsPerPoly);
|
var navMesh = BuildNavMesh(meshData, vertsPerPoly);
|
||||||
return new NavMeshBuildResult(RcImmutableArray.Create(rcResult), navMesh);
|
return new NavMeshBuildResult(cfg, RcImmutableArray.Create(rcResult), navMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DtNavMesh BuildNavMesh(DtMeshData meshData, int vertsPerPoly)
|
private DtNavMesh BuildNavMesh(DtMeshData meshData, int vertsPerPoly)
|
||||||
{
|
{
|
||||||
return new DtNavMesh(meshData, vertsPerPoly, 0);
|
var mesh = new DtNavMesh();
|
||||||
|
var status = mesh.Init(meshData, vertsPerPoly, 0);
|
||||||
|
if (status.Failed())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
private RcBuilderResult BuildRecastResult(DemoInputGeomProvider geom, RcConfig cfg, bool keepInterResults)
|
private RcBuilderResult BuildRecastResult(DemoInputGeomProvider geom, RcConfig cfg, bool keepInterResults)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -57,7 +58,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans,
|
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans,
|
||||||
bool keepInterResults, bool buildAll)
|
bool keepInterResults, bool buildAll)
|
||||||
{
|
{
|
||||||
List<RcBuilderResult> results = BuildRecastResult(
|
NavMeshBuildResult result = BuildRecastResult(
|
||||||
geom,
|
geom,
|
||||||
tileSize,
|
tileSize,
|
||||||
partitionType,
|
partitionType,
|
||||||
|
@ -71,12 +72,12 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
keepInterResults, buildAll
|
keepInterResults, buildAll
|
||||||
);
|
);
|
||||||
|
|
||||||
var tileMeshData = BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, results);
|
var tileMeshData = BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, result.RecastBuilderResults);
|
||||||
var tileNavMesh = BuildNavMesh(geom, tileMeshData, cellSize, tileSize, vertsPerPoly);
|
var tileNavMesh = BuildNavMesh(geom, tileMeshData, cellSize, tileSize, vertsPerPoly);
|
||||||
return new NavMeshBuildResult(results, tileNavMesh);
|
return new NavMeshBuildResult(result.Cfg, result.RecastBuilderResults, tileNavMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RcBuilderResult> BuildRecastResult(IInputGeomProvider geom,
|
public NavMeshBuildResult BuildRecastResult(IInputGeomProvider geom,
|
||||||
int tileSize,
|
int tileSize,
|
||||||
RcPartition partitionType,
|
RcPartition partitionType,
|
||||||
float cellSize, float cellHeight,
|
float cellSize, float cellHeight,
|
||||||
|
@ -101,7 +102,8 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
|
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true);
|
SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true);
|
||||||
RcBuilder rcBuilder = new RcBuilder();
|
RcBuilder rcBuilder = new RcBuilder();
|
||||||
return rcBuilder.BuildTiles(geom, cfg, keepInterResults, buildAll, Environment.ProcessorCount + 1, Task.Factory);
|
var results = rcBuilder.BuildTiles(geom, cfg, keepInterResults, buildAll, Environment.ProcessorCount + 1, Task.Factory);
|
||||||
|
return new NavMeshBuildResult(cfg, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtNavMesh BuildNavMesh(IInputGeomProvider geom, List<DtMeshData> meshData, float cellSize, int tileSize, int vertsPerPoly)
|
public DtNavMesh BuildNavMesh(IInputGeomProvider geom, List<DtMeshData> meshData, float cellSize, int tileSize, int vertsPerPoly)
|
||||||
|
@ -115,8 +117,9 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
|
|
||||||
navMeshParams.maxTiles = GetMaxTiles(geom, cellSize, tileSize);
|
navMeshParams.maxTiles = GetMaxTiles(geom, cellSize, tileSize);
|
||||||
navMeshParams.maxPolys = GetMaxPolysPerTile(geom, cellSize, tileSize);
|
navMeshParams.maxPolys = GetMaxPolysPerTile(geom, cellSize, tileSize);
|
||||||
DtNavMesh navMesh = new DtNavMesh(navMeshParams, vertsPerPoly);
|
DtNavMesh navMesh = new DtNavMesh();
|
||||||
meshData.ForEach(md => navMesh.AddTile(md, 0, 0));
|
navMesh.Init(navMeshParams, vertsPerPoly);
|
||||||
|
meshData.ForEach(md => navMesh.AddTile(md, 0, 0, out _));
|
||||||
return navMesh;
|
return navMesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +161,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
|
|
||||||
private int GetTileBits(IInputGeomProvider geom, float cellSize, int tileSize)
|
private int GetTileBits(IInputGeomProvider geom, float cellSize, int tileSize)
|
||||||
{
|
{
|
||||||
RcCommons.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
|
RcRecast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
|
||||||
int tw = (gw + tileSize - 1) / tileSize;
|
int tw = (gw + tileSize - 1) / tileSize;
|
||||||
int th = (gh + tileSize - 1) / tileSize;
|
int th = (gh + tileSize - 1) / tileSize;
|
||||||
int tileBits = Math.Min(DtUtils.Ilog2(DtUtils.NextPow2(tw * th)), 14);
|
int tileBits = Math.Min(DtUtils.Ilog2(DtUtils.NextPow2(tw * th)), 14);
|
||||||
|
@ -167,7 +170,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
|
|
||||||
public int[] GetTiles(DemoInputGeomProvider geom, float cellSize, int tileSize)
|
public int[] GetTiles(DemoInputGeomProvider geom, float cellSize, int tileSize)
|
||||||
{
|
{
|
||||||
RcCommons.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
|
RcRecast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
|
||||||
int tw = (gw + tileSize - 1) / tileSize;
|
int tw = (gw + tileSize - 1) / tileSize;
|
||||||
int th = (gh + tileSize - 1) / tileSize;
|
int th = (gh + tileSize - 1) / tileSize;
|
||||||
return new int[] { tw, th };
|
return new int[] { tw, th };
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Detour;
|
using DotRecast.Detour;
|
||||||
using DotRecast.Detour.TileCache;
|
using DotRecast.Detour.TileCache;
|
||||||
using DotRecast.Recast.Geom;
|
using DotRecast.Recast.Geom;
|
||||||
using DotRecast.Recast.Toolset.Builder;
|
using DotRecast.Recast.Toolset.Builder;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -41,7 +41,7 @@ namespace DotRecast.Recast.Toolset.Geom
|
||||||
|
|
||||||
public static DemoInputGeomProvider LoadFile(string objFilePath)
|
public static DemoInputGeomProvider LoadFile(string objFilePath)
|
||||||
{
|
{
|
||||||
byte[] chunk = RcResources.Load(objFilePath);
|
byte[] chunk = RcIO.ReadFileIfFound(objFilePath);
|
||||||
var context = RcObjImporter.LoadContext(chunk);
|
var context = RcObjImporter.LoadContext(chunk);
|
||||||
return new DemoInputGeomProvider(context.vertexPositions, context.meshFaces);
|
return new DemoInputGeomProvider(context.vertexPositions, context.meshFaces);
|
||||||
}
|
}
|
||||||
|
@ -57,12 +57,12 @@ namespace DotRecast.Recast.Toolset.Geom
|
||||||
this.faces = faces;
|
this.faces = faces;
|
||||||
normals = new float[faces.Length];
|
normals = new float[faces.Length];
|
||||||
CalculateNormals();
|
CalculateNormals();
|
||||||
bmin = RcVecUtils.Create(vertices);
|
bmin = new RcVec3f(vertices);
|
||||||
bmax = RcVecUtils.Create(vertices);
|
bmax = new RcVec3f(vertices);
|
||||||
for (int i = 1; i < vertices.Length / 3; i++)
|
for (int i = 1; i < vertices.Length / 3; i++)
|
||||||
{
|
{
|
||||||
bmin = RcVecUtils.Min(bmin, vertices, i * 3);
|
bmin = RcVec3f.Min(bmin, RcVec.Create(vertices, i * 3));
|
||||||
bmax = RcVecUtils.Max(bmax, vertices, i * 3);
|
bmax = RcVec3f.Max(bmax, RcVec.Create(vertices, i * 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
_mesh = new RcTriMesh(vertices, faces);
|
_mesh = new RcTriMesh(vertices, faces);
|
||||||
|
@ -87,11 +87,11 @@ namespace DotRecast.Recast.Toolset.Geom
|
||||||
{
|
{
|
||||||
for (int i = 0; i < faces.Length; i += 3)
|
for (int i = 0; i < faces.Length; i += 3)
|
||||||
{
|
{
|
||||||
int v0 = faces[i] * 3;
|
RcVec3f v0 = RcVec.Create(vertices, faces[i] * 3);
|
||||||
int v1 = faces[i + 1] * 3;
|
RcVec3f v1 = RcVec.Create(vertices, faces[i + 1] * 3);
|
||||||
int v2 = faces[i + 2] * 3;
|
RcVec3f v2 = RcVec.Create(vertices, faces[i + 2] * 3);
|
||||||
var e0 = RcVecUtils.Subtract(vertices, v1, v0);
|
RcVec3f e0 = v1 - v0;
|
||||||
var e1 = RcVecUtils.Subtract(vertices, v2, v0);
|
RcVec3f e1 = v2 - v0;
|
||||||
|
|
||||||
normals[i] = e0.Y * e1.Z - e0.Z * e1.Y;
|
normals[i] = e0.Y * e1.Z - e0.Z * e1.Y;
|
||||||
normals[i + 1] = e0.Z * e1.X - e0.X * e1.Z;
|
normals[i + 1] = e0.Z * e1.X - e0.X * e1.Z;
|
||||||
|
@ -150,7 +150,7 @@ namespace DotRecast.Recast.Toolset.Geom
|
||||||
q.X = src.X + (dst.X - src.X) * btmax;
|
q.X = src.X + (dst.X - src.X) * btmax;
|
||||||
q.Y = src.Z + (dst.Z - src.Z) * btmax;
|
q.Y = src.Z + (dst.Z - src.Z) * btmax;
|
||||||
|
|
||||||
List<RcChunkyTriMeshNode> chunks = _mesh.chunkyTriMesh.GetChunksOverlappingSegment(p, q);
|
List<RcChunkyTriMeshNode> chunks = RcChunkyTriMeshs.GetChunksOverlappingSegment(_mesh.chunkyTriMesh, p, q);
|
||||||
if (0 == chunks.Count)
|
if (0 == chunks.Count)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace DotRecast.Recast.Toolset.Gizmos
|
||||||
0.5f * (start.Z + end.Z)
|
0.5f * (start.Z + end.Z)
|
||||||
};
|
};
|
||||||
RcVec3f axis = new RcVec3f(end.X - start.X, end.Y - start.Y, end.Z - start.Z);
|
RcVec3f axis = new RcVec3f(end.X - start.X, end.Y - start.Y, end.Z - start.Z);
|
||||||
RcVec3f[] normals = new RcVec3f[3];
|
Span<RcVec3f> normals = stackalloc RcVec3f[3];
|
||||||
normals[1] = new RcVec3f(end.X - start.X, end.Y - start.Y, end.Z - start.Z);
|
normals[1] = new RcVec3f(end.X - start.X, end.Y - start.Y, end.Z - start.Z);
|
||||||
normals[1] = RcVec3f.Normalize(normals[1]);
|
normals[1] = RcVec3f.Normalize(normals[1]);
|
||||||
normals[0] = GetSideVector(axis);
|
normals[0] = GetSideVector(axis);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Toolset.Gizmos
|
namespace DotRecast.Recast.Toolset.Gizmos
|
||||||
{
|
{
|
||||||
public class RcCompositeGizmo : IRcGizmoMeshFilter
|
public class RcCompositeGizmo : IRcGizmoMeshFilter
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace DotRecast.Recast.Toolset.Gizmos
|
||||||
0.5f * (start.Z + end.Z)
|
0.5f * (start.Z + end.Z)
|
||||||
);
|
);
|
||||||
RcVec3f axis = new RcVec3f(end.X - start.X, end.Y - start.Y, end.Z - start.Z);
|
RcVec3f axis = new RcVec3f(end.X - start.X, end.Y - start.Y, end.Z - start.Z);
|
||||||
RcVec3f[] normals = new RcVec3f[3];
|
Span<RcVec3f> normals = stackalloc RcVec3f[3];
|
||||||
normals[1] = new RcVec3f(end.X - start.X, end.Y - start.Y, end.Z - start.Z);
|
normals[1] = new RcVec3f(end.X - start.X, end.Y - start.Y, end.Z - start.Z);
|
||||||
normals[1] = RcVec3f.Normalize(normals[1]);
|
normals[1] = RcVec3f.Normalize(normals[1]);
|
||||||
normals[0] = GetSideVector(axis);
|
normals[0] = GetSideVector(axis);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Detour.Dynamic.Colliders;
|
using DotRecast.Detour.Dynamic.Colliders;
|
||||||
using DotRecast.Recast.Toolset.Gizmos;
|
using DotRecast.Recast.Toolset.Gizmos;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Toolset.Gizmos
|
namespace DotRecast.Recast.Toolset.Gizmos
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Toolset.Gizmos
|
namespace DotRecast.Recast.Toolset.Gizmos
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,8 +4,8 @@ namespace DotRecast.Recast.Toolset.Gizmos
|
||||||
{
|
{
|
||||||
public static class RcGizmoHelper
|
public static class RcGizmoHelper
|
||||||
{
|
{
|
||||||
private static readonly int SEGMENTS = 16;
|
private const int SEGMENTS = 16;
|
||||||
private static readonly int RINGS = 8;
|
private const int RINGS = 8;
|
||||||
|
|
||||||
private static float[] sphericalVertices;
|
private static float[] sphericalVertices;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using static DotRecast.Recast.Toolset.Gizmos.RcGizmoHelper;
|
using static DotRecast.Recast.Toolset.Gizmos.RcGizmoHelper;
|
||||||
|
|
||||||
|
|
||||||
namespace DotRecast.Recast.Toolset.Gizmos
|
namespace DotRecast.Recast.Toolset.Gizmos
|
||||||
{
|
{
|
||||||
public class RcSphereGizmo : IRcGizmoMeshFilter
|
public class RcSphereGizmo : IRcGizmoMeshFilter
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Toolset.Gizmos
|
namespace DotRecast.Recast.Toolset.Gizmos
|
||||||
{
|
{
|
||||||
public class RcTrimeshGizmo : IRcGizmoMeshFilter
|
public class RcTrimeshGizmo : IRcGizmoMeshFilter
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Toolset
|
namespace DotRecast.Recast.Toolset
|
||||||
{
|
{
|
||||||
public interface IRcToolable
|
public interface IRcToolable
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace DotRecast.Recast.Toolset
|
namespace DotRecast.Recast.Toolset
|
||||||
{
|
{
|
||||||
[Serializable]
|
|
||||||
public class RcNavMeshBuildSettings
|
public class RcNavMeshBuildSettings
|
||||||
{
|
{
|
||||||
public float cellSize = 0.3f;
|
public float cellSize = 0.3f;
|
||||||
|
@ -35,7 +32,7 @@ namespace DotRecast.Recast.Toolset
|
||||||
public bool tiled = false;
|
public bool tiled = false;
|
||||||
public int tileSize = 32;
|
public int tileSize = 32;
|
||||||
|
|
||||||
public bool keepInterResults = false;
|
public bool keepInterResults = true; // full memory
|
||||||
public bool buildAll = true;
|
public bool buildAll = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Toolset.Tools
|
namespace DotRecast.Recast.Toolset.Tools
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
@ -26,12 +26,12 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
private readonly List<DtPolyPoint> _polyPoints;
|
private readonly List<DtPolyPoint> _polyPoints;
|
||||||
|
|
||||||
private const int SamplingCount = 500;
|
private const int SamplingCount = 500;
|
||||||
private long _samplingUpdateTime;
|
private double _samplingUpdateTime;
|
||||||
private readonly RcCyclicBuffer<long> _updateTimes;
|
private readonly RcCyclicBuffer<long> _updateTimes;
|
||||||
private long _curUpdateTime;
|
private double _curUpdateTime;
|
||||||
private long _avgUpdateTime;
|
private double _avgUpdateTime;
|
||||||
private long _minUpdateTime;
|
private double _minUpdateTime;
|
||||||
private long _maxUpdateTime;
|
private double _maxUpdateTime;
|
||||||
|
|
||||||
public RcCrowdAgentProfilingTool()
|
public RcCrowdAgentProfilingTool()
|
||||||
{
|
{
|
||||||
|
@ -269,11 +269,11 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
_updateTimes.PushBack(currentTime);
|
_updateTimes.PushBack(currentTime);
|
||||||
|
|
||||||
// for benchmark
|
// for benchmark
|
||||||
_samplingUpdateTime = _updateTimes.Sum() / TimeSpan.TicksPerMillisecond;
|
_samplingUpdateTime = _updateTimes.Sum() / (double)TimeSpan.TicksPerMillisecond;
|
||||||
_curUpdateTime = currentTime / TimeSpan.TicksPerMillisecond;
|
_curUpdateTime = currentTime / (double)TimeSpan.TicksPerMillisecond;
|
||||||
_avgUpdateTime = (long)(_updateTimes.Average() / TimeSpan.TicksPerMillisecond);
|
_avgUpdateTime = (_updateTimes.Average() / (double)TimeSpan.TicksPerMillisecond);
|
||||||
_minUpdateTime = _updateTimes.Min() / TimeSpan.TicksPerMillisecond;
|
_minUpdateTime = _updateTimes.Min() / (double)TimeSpan.TicksPerMillisecond;
|
||||||
_maxUpdateTime = _updateTimes.Max() / TimeSpan.TicksPerMillisecond;
|
_maxUpdateTime = _updateTimes.Max() / (double)TimeSpan.TicksPerMillisecond;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MoveMob(DtNavMeshQuery navquery, IDtQueryFilter filter, DtCrowdAgent ag, RcCrowdAgentData crowAgentData)
|
private void MoveMob(DtNavMeshQuery navquery, IDtQueryFilter filter, DtCrowdAgent ag, RcCrowdAgentData crowAgentData)
|
||||||
|
@ -374,27 +374,27 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetCrowdUpdateSamplingTime()
|
public double GetCrowdUpdateSamplingTime()
|
||||||
{
|
{
|
||||||
return _samplingUpdateTime;
|
return _samplingUpdateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetCrowdUpdateTime()
|
public double GetCrowdUpdateTime()
|
||||||
{
|
{
|
||||||
return _curUpdateTime;
|
return _curUpdateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetCrowdUpdateAvgTime()
|
public double GetCrowdUpdateAvgTime()
|
||||||
{
|
{
|
||||||
return _avgUpdateTime;
|
return _avgUpdateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetCrowdUpdateMinTime()
|
public double GetCrowdUpdateMinTime()
|
||||||
{
|
{
|
||||||
return _minUpdateTime;
|
return _minUpdateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetCrowdUpdateMaxTime()
|
public double GetCrowdUpdateMaxTime()
|
||||||
{
|
{
|
||||||
return _maxUpdateTime;
|
return _maxUpdateTime;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Toolset.Tools
|
namespace DotRecast.Recast.Toolset.Tools
|
||||||
{
|
{
|
||||||
public class RcCrowdAgentProfilingToolConfig
|
public class RcCrowdAgentProfilingToolConfig
|
||||||
{
|
{
|
||||||
|
@ -12,5 +12,7 @@
|
||||||
public float percentTravellers = 15f;
|
public float percentTravellers = 15f;
|
||||||
public int pathQueueSize = 32;
|
public int pathQueueSize = 32;
|
||||||
public int maxIterations = 300;
|
public int maxIterations = 300;
|
||||||
|
|
||||||
|
public bool showAgents = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Toolset.Tools
|
namespace DotRecast.Recast.Toolset.Tools
|
||||||
{
|
{
|
||||||
public class RcCrowdAgentTrail
|
public class RcCrowdAgentTrail
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Toolset.Tools
|
namespace DotRecast.Recast.Toolset.Tools
|
||||||
{
|
{
|
||||||
public enum RcCrowdAgentType
|
public enum RcCrowdAgentType
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
@ -297,7 +297,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
RcVec3f vel = RcVec3f.Subtract(tgt, pos);
|
RcVec3f vel = RcVec3f.Subtract(tgt, pos);
|
||||||
vel.Y = 0.0f;
|
vel.Y = 0.0f;
|
||||||
vel = RcVec3f.Normalize(vel);
|
vel = RcVec3f.Normalize(vel);
|
||||||
return vel.Scale(speed);
|
return vel * speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetCrowdUpdateTime()
|
public long GetCrowdUpdateTime()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Toolset.Tools
|
namespace DotRecast.Recast.Toolset.Tools
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Toolset.Tools
|
namespace DotRecast.Recast.Toolset.Tools
|
||||||
{
|
{
|
||||||
public enum RcDynamicColliderShape
|
public enum RcDynamicColliderShape
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -141,6 +141,16 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
return colliderWithGizmo;
|
return colliderWithGizmo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DtDynamicNavMesh Copy(RcConfig cfg, IList<RcBuilderResult> results)
|
||||||
|
{
|
||||||
|
var voxelFile = DtVoxelFile.From(cfg, results);
|
||||||
|
dynaMesh = new DtDynamicNavMesh(voxelFile);
|
||||||
|
dynaMesh.config.keepIntermediateResults = true;
|
||||||
|
colliderGizmos.Clear();
|
||||||
|
|
||||||
|
return dynaMesh;
|
||||||
|
}
|
||||||
|
|
||||||
public DtDynamicNavMesh Load(string filename, IRcCompressor compressor)
|
public DtDynamicNavMesh Load(string filename, IRcCompressor compressor)
|
||||||
{
|
{
|
||||||
using var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
|
using var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
@ -159,7 +169,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
public void Save(string filename, bool compression, IRcCompressor compressor)
|
public void Save(string filename, bool compression, IRcCompressor compressor)
|
||||||
{
|
{
|
||||||
DtVoxelFile voxelFile = DtVoxelFile.From(dynaMesh);
|
DtVoxelFile voxelFile = DtVoxelFile.From(dynaMesh);
|
||||||
using var fs = new FileStream(filename, FileMode.CreateNew, FileAccess.Write);
|
using var fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
|
||||||
using var bw = new BinaryWriter(fs);
|
using var bw = new BinaryWriter(fs);
|
||||||
DtVoxelFileWriter writer = new DtVoxelFileWriter(compressor);
|
DtVoxelFileWriter writer = new DtVoxelFileWriter(compressor);
|
||||||
writer.Write(bw, voxelFile, compression);
|
writer.Write(bw, voxelFile, compression);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Toolset.Tools
|
namespace DotRecast.Recast.Toolset.Tools
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Detour.Extras.Jumplink;
|
using DotRecast.Detour.Extras.Jumplink;
|
||||||
using DotRecast.Recast.Geom;
|
using DotRecast.Recast.Geom;
|
||||||
|
@ -116,7 +116,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
{
|
{
|
||||||
RcVec3f p = link.startSamples[i].p;
|
RcVec3f p = link.startSamples[i].p;
|
||||||
RcVec3f q = link.endSamples[i].p;
|
RcVec3f q = link.endSamples[i].p;
|
||||||
if (i == 0 || RcVecUtils.Dist2D(prev, p) > agentRadius)
|
if (i == 0 || RcVec.Dist2D(prev, p) > agentRadius)
|
||||||
{
|
{
|
||||||
geom.AddOffMeshConnection(p, q, agentRadius, false, area, flags);
|
geom.AddOffMeshConnection(p, q, agentRadius, false, area, flags);
|
||||||
prev = p;
|
prev = p;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
|
@ -42,7 +42,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
// Init cache
|
// Init cache
|
||||||
var bmin = geom.GetMeshBoundsMin();
|
var bmin = geom.GetMeshBoundsMin();
|
||||||
var bmax = geom.GetMeshBoundsMax();
|
var bmax = geom.GetMeshBoundsMax();
|
||||||
RcCommons.CalcGridSize(bmin, bmax, setting.cellSize, out var gw, out var gh);
|
RcRecast.CalcGridSize(bmin, bmax, setting.cellSize, out var gw, out var gh);
|
||||||
int ts = setting.tileSize;
|
int ts = setting.tileSize;
|
||||||
int tw = (gw + ts - 1) / ts;
|
int tw = (gw + ts - 1) / ts;
|
||||||
int th = (gh + ts - 1) / ts;
|
int th = (gh + ts - 1) / ts;
|
||||||
|
@ -78,7 +78,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
_tc.BuildNavMeshTile(refs);
|
_tc.BuildNavMeshTile(refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NavMeshBuildResult(RcImmutableArray<RcBuilderResult>.Empty, _tc.GetNavMesh());
|
return new NavMeshBuildResult(cfg, RcImmutableArray<RcBuilderResult>.Empty, _tc.GetNavMesh());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearAllTempObstacles()
|
public void ClearAllTempObstacles()
|
||||||
|
@ -141,7 +141,8 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
navMeshParams.maxTiles = 256; // ..
|
navMeshParams.maxTiles = 256; // ..
|
||||||
navMeshParams.maxPolys = 16384;
|
navMeshParams.maxPolys = 16384;
|
||||||
|
|
||||||
var navMesh = new DtNavMesh(navMeshParams, 6);
|
var navMesh = new DtNavMesh();
|
||||||
|
navMesh.Init(navMeshParams, 6);
|
||||||
var comp = _comp.Create(cCompatibility ? 0 : 1);
|
var comp = _comp.Create(cCompatibility ? 0 : 1);
|
||||||
var storageParams = new DtTileCacheStorageParams(order, cCompatibility);
|
var storageParams = new DtTileCacheStorageParams(order, cCompatibility);
|
||||||
DtTileCache tc = new DtTileCache(option, storageParams, navMesh, comp, _proc);
|
DtTileCache tc = new DtTileCache(option, storageParams, navMesh, comp, _proc);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Recast.Geom;
|
using DotRecast.Recast.Geom;
|
||||||
using DotRecast.Recast.Toolset.Builder;
|
using DotRecast.Recast.Toolset.Builder;
|
||||||
|
@ -34,7 +34,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
RcOffMeshConnection nearestConnection = null;
|
RcOffMeshConnection nearestConnection = null;
|
||||||
foreach (RcOffMeshConnection offMeshCon in geom.GetOffMeshConnections())
|
foreach (RcOffMeshConnection offMeshCon in geom.GetOffMeshConnections())
|
||||||
{
|
{
|
||||||
float d = Math.Min(RcVecUtils.DistanceSquared(p, offMeshCon.verts, 0), RcVecUtils.DistanceSquared(p, offMeshCon.verts, 3));
|
float d = Math.Min(RcVec.DistanceSquared(p, offMeshCon.verts, 0), RcVec.DistanceSquared(p, offMeshCon.verts, 3));
|
||||||
if (d < nearestDist && Math.Sqrt(d) < settings.agentRadius)
|
if (d < nearestDist && Math.Sqrt(d) < settings.agentRadius)
|
||||||
{
|
{
|
||||||
nearestDist = d;
|
nearestDist = d;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
@ -11,7 +11,6 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
public const int MAX_POLYS = 256;
|
public const int MAX_POLYS = 256;
|
||||||
public const int MAX_SMOOTH = 2048;
|
public const int MAX_SMOOTH = 2048;
|
||||||
|
|
||||||
|
|
||||||
public RcTestNavMeshTool()
|
public RcTestNavMeshTool()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -22,7 +21,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtStatus FindFollowPath(DtNavMesh navMesh, DtNavMeshQuery navQuery, long startRef, long endRef, RcVec3f startPt, RcVec3f endPt, IDtQueryFilter filter, bool enableRaycast,
|
public DtStatus FindFollowPath(DtNavMesh navMesh, DtNavMeshQuery navQuery, long startRef, long endRef, RcVec3f startPt, RcVec3f endPt, IDtQueryFilter filter, bool enableRaycast,
|
||||||
ref List<long> pathIterPolys, ref List<RcVec3f> smoothPath)
|
ref List<long> pathIterPolys, int pathIterPolyCount, ref List<RcVec3f> smoothPath)
|
||||||
{
|
{
|
||||||
if (startRef == 0 || endRef == 0)
|
if (startRef == 0 || endRef == 0)
|
||||||
{
|
{
|
||||||
|
@ -36,6 +35,8 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
smoothPath ??= new List<RcVec3f>();
|
smoothPath ??= new List<RcVec3f>();
|
||||||
|
|
||||||
pathIterPolys.Clear();
|
pathIterPolys.Clear();
|
||||||
|
pathIterPolyCount = 0;
|
||||||
|
|
||||||
smoothPath.Clear();
|
smoothPath.Clear();
|
||||||
|
|
||||||
var opt = new DtFindPathOption(enableRaycast ? DtFindPathOptions.DT_FINDPATH_ANY_ANGLE : 0, float.MaxValue);
|
var opt = new DtFindPathOption(enableRaycast ? DtFindPathOptions.DT_FINDPATH_ANY_ANGLE : 0, float.MaxValue);
|
||||||
|
@ -43,24 +44,29 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
if (0 >= pathIterPolys.Count)
|
if (0 >= pathIterPolys.Count)
|
||||||
return DtStatus.DT_FAILURE;
|
return DtStatus.DT_FAILURE;
|
||||||
|
|
||||||
|
pathIterPolyCount = pathIterPolys.Count;
|
||||||
|
|
||||||
// Iterate over the path to find smooth path on the detail mesh surface.
|
// Iterate over the path to find smooth path on the detail mesh surface.
|
||||||
navQuery.ClosestPointOnPoly(startRef, startPt, out var iterPos, out var _);
|
navQuery.ClosestPointOnPoly(startRef, startPt, out var iterPos, out var _);
|
||||||
navQuery.ClosestPointOnPoly(pathIterPolys[pathIterPolys.Count - 1], endPt, out var targetPos, out var _);
|
navQuery.ClosestPointOnPoly(pathIterPolys[pathIterPolys.Count - 1], endPt, out var targetPos, out var _);
|
||||||
|
|
||||||
float STEP_SIZE = 0.5f;
|
const float STEP_SIZE = 0.5f;
|
||||||
float SLOP = 0.01f;
|
const float SLOP = 0.01f;
|
||||||
|
|
||||||
smoothPath.Clear();
|
smoothPath.Clear();
|
||||||
smoothPath.Add(iterPos);
|
smoothPath.Add(iterPos);
|
||||||
var visited = new List<long>();
|
|
||||||
|
Span<long> visited = stackalloc long[16];
|
||||||
|
int nvisited = 0;
|
||||||
|
|
||||||
|
|
||||||
// Move towards target a small advancement at a time until target reached or
|
// Move towards target a small advancement at a time until target reached or
|
||||||
// when ran out of memory to store the path.
|
// when ran out of memory to store the path.
|
||||||
while (0 < pathIterPolys.Count && smoothPath.Count < MAX_SMOOTH)
|
while (0 < pathIterPolyCount && smoothPath.Count < MAX_SMOOTH)
|
||||||
{
|
{
|
||||||
// Find location to steer towards.
|
// Find location to steer towards.
|
||||||
if (!DtPathUtils.GetSteerTarget(navQuery, iterPos, targetPos, SLOP,
|
if (!DtPathUtils.GetSteerTarget(navQuery, iterPos, targetPos, SLOP,
|
||||||
pathIterPolys, out var steerPos, out var steerPosFlag, out var steerPosRef))
|
pathIterPolys, pathIterPolyCount, out var steerPos, out var steerPosFlag, out var steerPosRef))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -85,15 +91,15 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
len = STEP_SIZE / len;
|
len = STEP_SIZE / len;
|
||||||
}
|
}
|
||||||
|
|
||||||
RcVec3f moveTgt = RcVecUtils.Mad(iterPos, delta, len);
|
RcVec3f moveTgt = RcVec.Mad(iterPos, delta, len);
|
||||||
|
|
||||||
// Move
|
// Move
|
||||||
navQuery.MoveAlongSurface(pathIterPolys[0], iterPos, moveTgt, filter, out var result, ref visited);
|
navQuery.MoveAlongSurface(pathIterPolys[0], iterPos, moveTgt, filter, out var result, visited, out nvisited, 16);
|
||||||
|
|
||||||
iterPos = result;
|
iterPos = result;
|
||||||
|
|
||||||
pathIterPolys = DtPathUtils.MergeCorridorStartMoved(pathIterPolys, pathIterPolys.Count, MAX_POLYS, visited);
|
pathIterPolyCount = DtPathUtils.MergeCorridorStartMoved(ref pathIterPolys, pathIterPolyCount, MAX_POLYS, visited, nvisited);
|
||||||
pathIterPolys = DtPathUtils.FixupShortcuts(pathIterPolys, navQuery);
|
pathIterPolyCount = DtPathUtils.FixupShortcuts(ref pathIterPolys, pathIterPolyCount, navQuery);
|
||||||
|
|
||||||
var status = navQuery.GetPolyHeight(pathIterPolys[0], result, out var h);
|
var status = navQuery.GetPolyHeight(pathIterPolys[0], result, out var h);
|
||||||
if (status.Succeeded())
|
if (status.Succeeded())
|
||||||
|
@ -123,7 +129,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
long prevRef = 0;
|
long prevRef = 0;
|
||||||
long polyRef = pathIterPolys[0];
|
long polyRef = pathIterPolys[0];
|
||||||
int npos = 0;
|
int npos = 0;
|
||||||
while (npos < pathIterPolys.Count && polyRef != steerPosRef)
|
while (npos < pathIterPolyCount && polyRef != steerPosRef)
|
||||||
{
|
{
|
||||||
prevRef = polyRef;
|
prevRef = polyRef;
|
||||||
polyRef = pathIterPolys[npos];
|
polyRef = pathIterPolys[npos];
|
||||||
|
@ -131,6 +137,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
}
|
}
|
||||||
|
|
||||||
pathIterPolys = pathIterPolys.GetRange(npos, pathIterPolys.Count - npos);
|
pathIterPolys = pathIterPolys.GetRange(npos, pathIterPolys.Count - npos);
|
||||||
|
pathIterPolyCount -= npos;
|
||||||
|
|
||||||
// Handle the connection.
|
// Handle the connection.
|
||||||
var status2 = navMesh.GetOffMeshConnectionPolyEndPoints(prevRef, polyRef, ref startPos, ref endPos);
|
var status2 = navMesh.GetOffMeshConnectionPolyEndPoints(prevRef, polyRef, ref startPos, ref endPos);
|
||||||
|
@ -164,15 +171,15 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtStatus FindStraightPath(DtNavMeshQuery navQuery, long startRef, long endRef, RcVec3f startPt, RcVec3f endPt, IDtQueryFilter filter, bool enableRaycast,
|
public DtStatus FindStraightPath(DtNavMeshQuery navQuery, long startRef, long endRef, RcVec3f startPt, RcVec3f endPt, IDtQueryFilter filter, bool enableRaycast,
|
||||||
ref List<long> polys, ref List<DtStraightPath> straightPath, int straightPathOptions)
|
ref List<long> polys, Span<DtStraightPath> straightPath, out int straightPathCount, int maxStraightPath, int straightPathOptions)
|
||||||
{
|
{
|
||||||
|
straightPathCount = 0;
|
||||||
if (startRef == 0 || endRef == 0)
|
if (startRef == 0 || endRef == 0)
|
||||||
{
|
{
|
||||||
return DtStatus.DT_FAILURE;
|
return DtStatus.DT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
polys ??= new List<long>();
|
polys ??= new List<long>();
|
||||||
straightPath ??= new List<DtStraightPath>();
|
|
||||||
|
|
||||||
polys.Clear();
|
polys.Clear();
|
||||||
straightPath.Clear();
|
straightPath.Clear();
|
||||||
|
@ -194,7 +201,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
navQuery.FindStraightPath(startPt, epos, polys, ref straightPath, MAX_POLYS, straightPathOptions);
|
navQuery.FindStraightPath(startPt, epos, polys, polys.Count, straightPath, out straightPathCount, maxStraightPath, straightPathOptions);
|
||||||
|
|
||||||
return DtStatus.DT_SUCCESS;
|
return DtStatus.DT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -213,8 +220,9 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtStatus UpdateSlicedFindPath(DtNavMeshQuery navQuery, int maxIter, long endRef, RcVec3f startPos, RcVec3f endPos,
|
public DtStatus UpdateSlicedFindPath(DtNavMeshQuery navQuery, int maxIter, long endRef, RcVec3f startPos, RcVec3f endPos,
|
||||||
ref List<long> path, ref List<DtStraightPath> straightPath)
|
ref List<long> path, Span<DtStraightPath> straightPath, out int straightPathCount, int maxStraightPath)
|
||||||
{
|
{
|
||||||
|
straightPathCount = 0;
|
||||||
var status = navQuery.UpdateSlicedFindPath(maxIter, out _);
|
var status = navQuery.UpdateSlicedFindPath(maxIter, out _);
|
||||||
|
|
||||||
if (!status.Succeeded())
|
if (!status.Succeeded())
|
||||||
|
@ -224,7 +232,6 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
|
|
||||||
navQuery.FinalizeSlicedFindPath(ref path);
|
navQuery.FinalizeSlicedFindPath(ref path);
|
||||||
|
|
||||||
straightPath?.Clear();
|
|
||||||
if (path != null)
|
if (path != null)
|
||||||
{
|
{
|
||||||
// In case of partial path, make sure the end point is clamped to the last polygon.
|
// In case of partial path, make sure the end point is clamped to the last polygon.
|
||||||
|
@ -238,8 +245,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
straightPath = new List<DtStraightPath>(MAX_POLYS);
|
navQuery.FindStraightPath(startPos, epos, path, path.Count, straightPath, out straightPathCount, maxStraightPath, DtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS);
|
||||||
navQuery.FindStraightPath(startPos, epos, path, ref straightPath, MAX_POLYS, DtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return DtStatus.DT_SUCCESS;
|
return DtStatus.DT_SUCCESS;
|
||||||
|
@ -247,13 +253,12 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
|
|
||||||
|
|
||||||
public DtStatus Raycast(DtNavMeshQuery navQuery, long startRef, long endRef, RcVec3f startPos, RcVec3f endPos, IDtQueryFilter filter,
|
public DtStatus Raycast(DtNavMeshQuery navQuery, long startRef, long endRef, RcVec3f startPos, RcVec3f endPos, IDtQueryFilter filter,
|
||||||
ref List<long> polys, ref List<DtStraightPath> straightPath, ref RcVec3f hitPos, ref RcVec3f hitNormal, ref bool hitResult)
|
ref List<long> polys, Span<DtStraightPath> straightPath, out int straightPathCount, int maxStraightPath, ref RcVec3f hitPos, ref RcVec3f hitNormal, ref bool hitResult)
|
||||||
{
|
{
|
||||||
|
straightPathCount = 0;
|
||||||
if (startRef == 0 || endRef == 0)
|
if (startRef == 0 || endRef == 0)
|
||||||
{
|
{
|
||||||
polys?.Clear();
|
polys?.Clear();
|
||||||
straightPath?.Clear();
|
|
||||||
|
|
||||||
return DtStatus.DT_FAILURE;
|
return DtStatus.DT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +272,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
// results ...
|
// results ...
|
||||||
polys = path;
|
polys = path;
|
||||||
|
|
||||||
if (t > 1)
|
if (t >= 1)
|
||||||
{
|
{
|
||||||
// No hit
|
// No hit
|
||||||
hitPos = endPos;
|
hitPos = endPos;
|
||||||
|
@ -291,10 +296,8 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
straightPath ??= new List<DtStraightPath>();
|
straightPath[straightPathCount++] = new DtStraightPath(startPos, 0, 0);
|
||||||
straightPath.Clear();
|
straightPath[straightPathCount++] = new DtStraightPath(hitPos, 0, 0);
|
||||||
straightPath.Add(new DtStraightPath(startPos, 0, 0));
|
|
||||||
straightPath.Add(new DtStraightPath(hitPos, 0, 0));
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -377,7 +380,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
float nx = (epos.Z - spos.Z) * 0.25f;
|
float nx = (epos.Z - spos.Z) * 0.25f;
|
||||||
float nz = -(epos.X - spos.X) * 0.25f;
|
float nz = -(epos.X - spos.X) * 0.25f;
|
||||||
|
|
||||||
var tempQueryPoly = new RcVec3f[4];
|
RcVec3f[] tempQueryPoly = new RcVec3f[4];
|
||||||
tempQueryPoly[0].X = spos.X + nx * 1.2f;
|
tempQueryPoly[0].X = spos.X + nx * 1.2f;
|
||||||
tempQueryPoly[0].Y = spos.Y + agentHeight / 2;
|
tempQueryPoly[0].Y = spos.Y + agentHeight / 2;
|
||||||
tempQueryPoly[0].Z = spos.Z + nz * 1.2f;
|
tempQueryPoly[0].Z = spos.Z + nz * 1.2f;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Toolset.Tools
|
namespace DotRecast.Recast.Toolset.Tools
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
@ -23,7 +23,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
var bmin = geom.GetMeshBoundsMin();
|
var bmin = geom.GetMeshBoundsMin();
|
||||||
var bmax = geom.GetMeshBoundsMax();
|
var bmax = geom.GetMeshBoundsMax();
|
||||||
int gw = 0, gh = 0;
|
int gw = 0, gh = 0;
|
||||||
RcCommons.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh);
|
RcRecast.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh);
|
||||||
|
|
||||||
int ts = settings.tileSize;
|
int ts = settings.tileSize;
|
||||||
int tw = (gw + ts - 1) / ts;
|
int tw = (gw + ts - 1) / ts;
|
||||||
|
@ -47,7 +47,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
var bmin = geom.GetMeshBoundsMin();
|
var bmin = geom.GetMeshBoundsMin();
|
||||||
var bmax = geom.GetMeshBoundsMax();
|
var bmax = geom.GetMeshBoundsMax();
|
||||||
int gw = 0, gh = 0;
|
int gw = 0, gh = 0;
|
||||||
RcCommons.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh);
|
RcRecast.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh);
|
||||||
|
|
||||||
int ts = settings.tileSize;
|
int ts = settings.tileSize;
|
||||||
int tw = (gw + ts - 1) / ts;
|
int tw = (gw + ts - 1) / ts;
|
||||||
|
@ -68,8 +68,8 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
tileTriCount = 0; // ...
|
tileTriCount = 0; // ...
|
||||||
tileMemUsage = 0; // ...
|
tileMemUsage = 0; // ...
|
||||||
|
|
||||||
var availableTileCount = navMesh.GetAvailableTileCount();
|
var availableTile = navMesh.IsAvailableTileCount();
|
||||||
if (0 >= availableTileCount)
|
if (!availableTile)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace DotRecast.Recast
|
||||||
|
{
|
||||||
|
public static class EdgeValues
|
||||||
|
{
|
||||||
|
public const int EV_UNDEF = -1;
|
||||||
|
public const int EV_HULL = -2;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Geom
|
namespace DotRecast.Recast.Geom
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Geom
|
namespace DotRecast.Recast.Geom
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Geom
|
namespace DotRecast.Recast.Geom
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -18,278 +18,14 @@ freely, subject to the following restrictions:
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core.Numerics;
|
|
||||||
|
|
||||||
namespace DotRecast.Recast.Geom
|
namespace DotRecast.Recast.Geom
|
||||||
{
|
{
|
||||||
public class RcChunkyTriMesh
|
public class RcChunkyTriMesh
|
||||||
{
|
{
|
||||||
private List<RcChunkyTriMeshNode> nodes;
|
public List<RcChunkyTriMeshNode> nodes;
|
||||||
private int ntris;
|
public int ntris;
|
||||||
private int maxTrisPerChunk;
|
public int maxTrisPerChunk;
|
||||||
|
|
||||||
private void CalcExtends(BoundsItem[] items, int imin, int imax, ref RcVec2f bmin, ref RcVec2f bmax)
|
|
||||||
{
|
|
||||||
bmin.X = items[imin].bmin.X;
|
|
||||||
bmin.Y = items[imin].bmin.Y;
|
|
||||||
|
|
||||||
bmax.X = items[imin].bmax.X;
|
|
||||||
bmax.Y = items[imin].bmax.Y;
|
|
||||||
|
|
||||||
for (int i = imin + 1; i < imax; ++i)
|
|
||||||
{
|
|
||||||
BoundsItem it = items[i];
|
|
||||||
if (it.bmin.X < bmin.X)
|
|
||||||
{
|
|
||||||
bmin.X = it.bmin.X;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (it.bmin.Y < bmin.Y)
|
|
||||||
{
|
|
||||||
bmin.Y = it.bmin.Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (it.bmax.X > bmax.X)
|
|
||||||
{
|
|
||||||
bmax.X = it.bmax.X;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (it.bmax.Y > bmax.Y)
|
|
||||||
{
|
|
||||||
bmax.Y = it.bmax.Y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int LongestAxis(float x, float y)
|
|
||||||
{
|
|
||||||
return y > x ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Subdivide(BoundsItem[] items, int imin, int imax, int trisPerChunk, List<RcChunkyTriMeshNode> nodes, int[] inTris)
|
|
||||||
{
|
|
||||||
int inum = imax - imin;
|
|
||||||
|
|
||||||
RcChunkyTriMeshNode node = new RcChunkyTriMeshNode();
|
|
||||||
nodes.Add(node);
|
|
||||||
|
|
||||||
if (inum <= trisPerChunk)
|
|
||||||
{
|
|
||||||
// Leaf
|
|
||||||
CalcExtends(items, imin, imax, ref node.bmin, ref node.bmax);
|
|
||||||
|
|
||||||
// Copy triangles.
|
|
||||||
node.i = nodes.Count;
|
|
||||||
node.tris = new int[inum * 3];
|
|
||||||
|
|
||||||
int dst = 0;
|
|
||||||
for (int i = imin; i < imax; ++i)
|
|
||||||
{
|
|
||||||
int src = items[i].i * 3;
|
|
||||||
node.tris[dst++] = inTris[src];
|
|
||||||
node.tris[dst++] = inTris[src + 1];
|
|
||||||
node.tris[dst++] = inTris[src + 2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Split
|
|
||||||
CalcExtends(items, imin, imax, ref node.bmin, ref node.bmax);
|
|
||||||
|
|
||||||
int axis = LongestAxis(node.bmax.X - node.bmin.X, node.bmax.Y - node.bmin.Y);
|
|
||||||
|
|
||||||
if (axis == 0)
|
|
||||||
{
|
|
||||||
Array.Sort(items, imin, imax - imin, BoundsItemXComparer.Shared);
|
|
||||||
// Sort along x-axis
|
|
||||||
}
|
|
||||||
else if (axis == 1)
|
|
||||||
{
|
|
||||||
Array.Sort(items, imin, imax - imin, BoundsItemYComparer.Shared);
|
|
||||||
// Sort along y-axis
|
|
||||||
}
|
|
||||||
|
|
||||||
int isplit = imin + inum / 2;
|
|
||||||
|
|
||||||
// Left
|
|
||||||
Subdivide(items, imin, isplit, trisPerChunk, nodes, inTris);
|
|
||||||
// Right
|
|
||||||
Subdivide(items, isplit, imax, trisPerChunk, nodes, inTris);
|
|
||||||
|
|
||||||
// Negative index means escape.
|
|
||||||
node.i = -nodes.Count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RcChunkyTriMesh(float[] verts, int[] tris, int ntris, int trisPerChunk)
|
|
||||||
{
|
|
||||||
int nchunks = (ntris + trisPerChunk - 1) / trisPerChunk;
|
|
||||||
|
|
||||||
nodes = new List<RcChunkyTriMeshNode>(nchunks);
|
|
||||||
this.ntris = ntris;
|
|
||||||
|
|
||||||
// Build tree
|
|
||||||
BoundsItem[] items = new BoundsItem[ntris];
|
|
||||||
|
|
||||||
for (int i = 0; i < ntris; i++)
|
|
||||||
{
|
|
||||||
int t = i * 3;
|
|
||||||
BoundsItem it = items[i] = new BoundsItem();
|
|
||||||
it.i = i;
|
|
||||||
// Calc triangle XZ bounds.
|
|
||||||
it.bmin.X = it.bmax.X = verts[tris[t] * 3 + 0];
|
|
||||||
it.bmin.Y = it.bmax.Y = verts[tris[t] * 3 + 2];
|
|
||||||
for (int j = 1; j < 3; ++j)
|
|
||||||
{
|
|
||||||
int v = tris[t + j] * 3;
|
|
||||||
if (verts[v] < it.bmin.X)
|
|
||||||
{
|
|
||||||
it.bmin.X = verts[v];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verts[v + 2] < it.bmin.Y)
|
|
||||||
{
|
|
||||||
it.bmin.Y = verts[v + 2];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verts[v] > it.bmax.X)
|
|
||||||
{
|
|
||||||
it.bmax.X = verts[v];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verts[v + 2] > it.bmax.Y)
|
|
||||||
{
|
|
||||||
it.bmax.Y = verts[v + 2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Subdivide(items, 0, ntris, trisPerChunk, nodes, tris);
|
|
||||||
|
|
||||||
// Calc max tris per node.
|
|
||||||
maxTrisPerChunk = 0;
|
|
||||||
foreach (RcChunkyTriMeshNode node in nodes)
|
|
||||||
{
|
|
||||||
bool isLeaf = node.i >= 0;
|
|
||||||
if (!isLeaf)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.tris.Length / 3 > maxTrisPerChunk)
|
|
||||||
{
|
|
||||||
maxTrisPerChunk = node.tris.Length / 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CheckOverlapRect(float[] amin, float[] amax, RcVec2f bmin, RcVec2f bmax)
|
|
||||||
{
|
|
||||||
bool overlap = true;
|
|
||||||
overlap = (amin[0] > bmax.X || amax[0] < bmin.X) ? false : overlap;
|
|
||||||
overlap = (amin[1] > bmax.Y || amax[1] < bmin.Y) ? false : overlap;
|
|
||||||
return overlap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<RcChunkyTriMeshNode> GetChunksOverlappingRect(float[] bmin, float[] bmax)
|
|
||||||
{
|
|
||||||
// Traverse tree
|
|
||||||
List<RcChunkyTriMeshNode> ids = new List<RcChunkyTriMeshNode>();
|
|
||||||
int i = 0;
|
|
||||||
while (i < nodes.Count)
|
|
||||||
{
|
|
||||||
RcChunkyTriMeshNode node = nodes[i];
|
|
||||||
bool overlap = CheckOverlapRect(bmin, bmax, node.bmin, node.bmax);
|
|
||||||
bool isLeafNode = node.i >= 0;
|
|
||||||
|
|
||||||
if (isLeafNode && overlap)
|
|
||||||
{
|
|
||||||
ids.Add(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (overlap || isLeafNode)
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i = -node.i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ids;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<RcChunkyTriMeshNode> GetChunksOverlappingSegment(RcVec2f p, RcVec2f q)
|
|
||||||
{
|
|
||||||
// Traverse tree
|
|
||||||
List<RcChunkyTriMeshNode> ids = new List<RcChunkyTriMeshNode>();
|
|
||||||
int i = 0;
|
|
||||||
while (i < nodes.Count)
|
|
||||||
{
|
|
||||||
RcChunkyTriMeshNode node = nodes[i];
|
|
||||||
bool overlap = CheckOverlapSegment(p, q, node.bmin, node.bmax);
|
|
||||||
bool isLeafNode = node.i >= 0;
|
|
||||||
|
|
||||||
if (isLeafNode && overlap)
|
|
||||||
{
|
|
||||||
ids.Add(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (overlap || isLeafNode)
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i = -node.i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ids;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CheckOverlapSegment(RcVec2f p, RcVec2f q, RcVec2f bmin, RcVec2f bmax)
|
|
||||||
{
|
|
||||||
const float EPSILON = 1e-6f;
|
|
||||||
|
|
||||||
float tmin = 0;
|
|
||||||
float tmax = 1;
|
|
||||||
var d = new RcVec2f();
|
|
||||||
d.X = q.X - p.X;
|
|
||||||
d.Y = q.Y - p.Y;
|
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
|
||||||
{
|
|
||||||
if (MathF.Abs(d.Get(i)) < EPSILON)
|
|
||||||
{
|
|
||||||
// Ray is parallel to slab. No hit if origin not within slab
|
|
||||||
if (p.Get(i) < bmin.Get(i) || p.Get(i) > bmax.Get(i))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Compute intersection t value of ray with near and far plane of slab
|
|
||||||
float ood = 1.0f / d.Get(i);
|
|
||||||
float t1 = (bmin.Get(i) - p.Get(i)) * ood;
|
|
||||||
float t2 = (bmax.Get(i) - p.Get(i)) * ood;
|
|
||||||
if (t1 > t2)
|
|
||||||
{
|
|
||||||
(t1, t2) = (t2, t1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t1 > tmin)
|
|
||||||
tmin = t1;
|
|
||||||
if (t2 < tmax)
|
|
||||||
tmax = t2;
|
|
||||||
if (tmin > tmax)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Geom
|
namespace DotRecast.Recast.Geom
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,305 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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.Numerics;
|
||||||
|
|
||||||
|
namespace DotRecast.Recast.Geom
|
||||||
|
{
|
||||||
|
public static class RcChunkyTriMeshs
|
||||||
|
{
|
||||||
|
/// Creates partitioned triangle mesh (AABB tree),
|
||||||
|
/// where each node contains at max trisPerChunk triangles.
|
||||||
|
public static bool CreateChunkyTriMesh(float[] verts, int[] tris, int ntris, int trisPerChunk, RcChunkyTriMesh cm)
|
||||||
|
{
|
||||||
|
int nchunks = (ntris + trisPerChunk - 1) / trisPerChunk;
|
||||||
|
|
||||||
|
cm.nodes = new List<RcChunkyTriMeshNode>(nchunks);
|
||||||
|
cm.ntris = ntris;
|
||||||
|
|
||||||
|
// Build tree
|
||||||
|
BoundsItem[] items = new BoundsItem[ntris];
|
||||||
|
for (int i = 0; i < ntris; ++i)
|
||||||
|
{
|
||||||
|
items[i] = new BoundsItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < ntris; i++)
|
||||||
|
{
|
||||||
|
int t = i * 3;
|
||||||
|
BoundsItem it = items[i];
|
||||||
|
it.i = i;
|
||||||
|
// Calc triangle XZ bounds.
|
||||||
|
it.bmin.X = it.bmax.X = verts[tris[t] * 3 + 0];
|
||||||
|
it.bmin.Y = it.bmax.Y = verts[tris[t] * 3 + 2];
|
||||||
|
for (int j = 1; j < 3; ++j)
|
||||||
|
{
|
||||||
|
int v = tris[t + j] * 3;
|
||||||
|
if (verts[v] < it.bmin.X)
|
||||||
|
{
|
||||||
|
it.bmin.X = verts[v];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verts[v + 2] < it.bmin.Y)
|
||||||
|
{
|
||||||
|
it.bmin.Y = verts[v + 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verts[v] > it.bmax.X)
|
||||||
|
{
|
||||||
|
it.bmax.X = verts[v];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verts[v + 2] > it.bmax.Y)
|
||||||
|
{
|
||||||
|
it.bmax.Y = verts[v + 2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Subdivide(items, 0, ntris, trisPerChunk, cm.nodes, tris);
|
||||||
|
|
||||||
|
items = null;
|
||||||
|
|
||||||
|
// Calc max tris per node.
|
||||||
|
cm.maxTrisPerChunk = 0;
|
||||||
|
foreach (RcChunkyTriMeshNode node in cm.nodes)
|
||||||
|
{
|
||||||
|
bool isLeaf = node.i >= 0;
|
||||||
|
if (!isLeaf)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.tris.Length / 3 > cm.maxTrisPerChunk)
|
||||||
|
{
|
||||||
|
cm.maxTrisPerChunk = node.tris.Length / 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the chunk indices which overlap the input rectable.
|
||||||
|
public static List<RcChunkyTriMeshNode> GetChunksOverlappingRect(RcChunkyTriMesh cm, RcVec2f bmin, RcVec2f bmax)
|
||||||
|
{
|
||||||
|
// Traverse tree
|
||||||
|
List<RcChunkyTriMeshNode> ids = new List<RcChunkyTriMeshNode>();
|
||||||
|
int i = 0;
|
||||||
|
while (i < cm.nodes.Count)
|
||||||
|
{
|
||||||
|
RcChunkyTriMeshNode node = cm.nodes[i];
|
||||||
|
bool overlap = CheckOverlapRect(bmin, bmax, node.bmin, node.bmax);
|
||||||
|
bool isLeafNode = node.i >= 0;
|
||||||
|
|
||||||
|
if (isLeafNode && overlap)
|
||||||
|
{
|
||||||
|
ids.Add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overlap || isLeafNode)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i = -node.i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the chunk indices which overlap the input segment.
|
||||||
|
public static List<RcChunkyTriMeshNode> GetChunksOverlappingSegment(RcChunkyTriMesh cm, RcVec2f p, RcVec2f q)
|
||||||
|
{
|
||||||
|
// Traverse tree
|
||||||
|
List<RcChunkyTriMeshNode> ids = new List<RcChunkyTriMeshNode>();
|
||||||
|
int i = 0;
|
||||||
|
while (i < cm.nodes.Count)
|
||||||
|
{
|
||||||
|
RcChunkyTriMeshNode node = cm.nodes[i];
|
||||||
|
bool overlap = CheckOverlapSegment(p, q, node.bmin, node.bmax);
|
||||||
|
bool isLeafNode = node.i >= 0;
|
||||||
|
|
||||||
|
if (isLeafNode && overlap)
|
||||||
|
{
|
||||||
|
ids.Add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overlap || isLeafNode)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i = -node.i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void CalcExtends(BoundsItem[] items, int imin, int imax, ref RcVec2f bmin, ref RcVec2f bmax)
|
||||||
|
{
|
||||||
|
bmin.X = items[imin].bmin.X;
|
||||||
|
bmin.Y = items[imin].bmin.Y;
|
||||||
|
|
||||||
|
bmax.X = items[imin].bmax.X;
|
||||||
|
bmax.Y = items[imin].bmax.Y;
|
||||||
|
|
||||||
|
for (int i = imin + 1; i < imax; ++i)
|
||||||
|
{
|
||||||
|
BoundsItem it = items[i];
|
||||||
|
if (it.bmin.X < bmin.X)
|
||||||
|
{
|
||||||
|
bmin.X = it.bmin.X;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it.bmin.Y < bmin.Y)
|
||||||
|
{
|
||||||
|
bmin.Y = it.bmin.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it.bmax.X > bmax.X)
|
||||||
|
{
|
||||||
|
bmax.X = it.bmax.X;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it.bmax.Y > bmax.Y)
|
||||||
|
{
|
||||||
|
bmax.Y = it.bmax.Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int LongestAxis(float x, float y)
|
||||||
|
{
|
||||||
|
return y > x ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Subdivide(BoundsItem[] items, int imin, int imax, int trisPerChunk, List<RcChunkyTriMeshNode> nodes, int[] inTris)
|
||||||
|
{
|
||||||
|
int inum = imax - imin;
|
||||||
|
|
||||||
|
RcChunkyTriMeshNode node = new RcChunkyTriMeshNode();
|
||||||
|
nodes.Add(node);
|
||||||
|
|
||||||
|
if (inum <= trisPerChunk)
|
||||||
|
{
|
||||||
|
// Leaf
|
||||||
|
CalcExtends(items, imin, imax, ref node.bmin, ref node.bmax);
|
||||||
|
|
||||||
|
// Copy triangles.
|
||||||
|
node.i = nodes.Count;
|
||||||
|
node.tris = new int[inum * 3];
|
||||||
|
|
||||||
|
int dst = 0;
|
||||||
|
for (int i = imin; i < imax; ++i)
|
||||||
|
{
|
||||||
|
int src = items[i].i * 3;
|
||||||
|
node.tris[dst++] = inTris[src];
|
||||||
|
node.tris[dst++] = inTris[src + 1];
|
||||||
|
node.tris[dst++] = inTris[src + 2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Split
|
||||||
|
CalcExtends(items, imin, imax, ref node.bmin, ref node.bmax);
|
||||||
|
|
||||||
|
int axis = LongestAxis(node.bmax.X - node.bmin.X, node.bmax.Y - node.bmin.Y);
|
||||||
|
|
||||||
|
if (axis == 0)
|
||||||
|
{
|
||||||
|
Array.Sort(items, imin, imax - imin, BoundsItemXComparer.Shared);
|
||||||
|
// Sort along x-axis
|
||||||
|
}
|
||||||
|
else if (axis == 1)
|
||||||
|
{
|
||||||
|
Array.Sort(items, imin, imax - imin, BoundsItemYComparer.Shared);
|
||||||
|
// Sort along y-axis
|
||||||
|
}
|
||||||
|
|
||||||
|
int isplit = imin + inum / 2;
|
||||||
|
|
||||||
|
// Left
|
||||||
|
Subdivide(items, imin, isplit, trisPerChunk, nodes, inTris);
|
||||||
|
// Right
|
||||||
|
Subdivide(items, isplit, imax, trisPerChunk, nodes, inTris);
|
||||||
|
|
||||||
|
// Negative index means escape.
|
||||||
|
node.i = -nodes.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool CheckOverlapRect(RcVec2f amin, RcVec2f amax, RcVec2f bmin, RcVec2f bmax)
|
||||||
|
{
|
||||||
|
bool overlap = true;
|
||||||
|
overlap = (amin.X > bmax.X || amax.X < bmin.X) ? false : overlap;
|
||||||
|
overlap = (amin.Y > bmax.Y || amax.Y < bmin.Y) ? false : overlap;
|
||||||
|
return overlap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static bool CheckOverlapSegment(RcVec2f p, RcVec2f q, RcVec2f bmin, RcVec2f bmax)
|
||||||
|
{
|
||||||
|
const float EPSILON = 1e-6f;
|
||||||
|
|
||||||
|
float tmin = 0;
|
||||||
|
float tmax = 1;
|
||||||
|
var d = new RcVec2f();
|
||||||
|
d.X = q.X - p.X;
|
||||||
|
d.Y = q.Y - p.Y;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
if (MathF.Abs(d.Get(i)) < EPSILON)
|
||||||
|
{
|
||||||
|
// Ray is parallel to slab. No hit if origin not within slab
|
||||||
|
if (p.Get(i) < bmin.Get(i) || p.Get(i) > bmax.Get(i))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Compute intersection t value of ray with near and far plane of slab
|
||||||
|
float ood = 1.0f / d.Get(i);
|
||||||
|
float t1 = (bmin.Get(i) - p.Get(i)) * ood;
|
||||||
|
float t2 = (bmax.Get(i) - p.Get(i)) * ood;
|
||||||
|
if (t1 > t2)
|
||||||
|
{
|
||||||
|
(t1, t2) = (t2, t1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t1 > tmin)
|
||||||
|
tmin = t1;
|
||||||
|
if (t2 < tmax)
|
||||||
|
tmax = t2;
|
||||||
|
if (tmin > tmax)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -19,6 +19,7 @@ freely, subject to the following restrictions:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Geom
|
namespace DotRecast.Recast.Geom
|
||||||
{
|
{
|
||||||
|
@ -32,7 +33,8 @@ namespace DotRecast.Recast.Geom
|
||||||
{
|
{
|
||||||
this.vertices = vertices;
|
this.vertices = vertices;
|
||||||
this.faces = faces;
|
this.faces = faces;
|
||||||
chunkyTriMesh = new RcChunkyTriMesh(vertices, faces, faces.Length / 3, 32);
|
chunkyTriMesh = new RcChunkyTriMesh();
|
||||||
|
RcChunkyTriMeshs.CreateChunkyTriMesh(vertices, faces, faces.Length / 3, 32, chunkyTriMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int[] GetTris()
|
public int[] GetTris()
|
||||||
|
@ -45,9 +47,9 @@ namespace DotRecast.Recast.Geom
|
||||||
return vertices;
|
return vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RcChunkyTriMeshNode> GetChunksOverlappingRect(float[] bmin, float[] bmax)
|
public List<RcChunkyTriMeshNode> GetChunksOverlappingRect(RcVec2f bmin, RcVec2f bmax)
|
||||||
{
|
{
|
||||||
return chunkyTriMesh.GetChunksOverlappingRect(bmin, bmax);
|
return RcChunkyTriMeshs.GetChunksOverlappingRect(chunkyTriMesh, bmin, bmax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -39,7 +39,7 @@ namespace DotRecast.Recast.Geom
|
||||||
|
|
||||||
public static SimpleInputGeomProvider LoadFile(string objFilePath)
|
public static SimpleInputGeomProvider LoadFile(string objFilePath)
|
||||||
{
|
{
|
||||||
byte[] chunk = RcResources.Load(objFilePath);
|
byte[] chunk = RcIO.ReadFileIfFound(objFilePath);
|
||||||
var context = RcObjImporter.LoadContext(chunk);
|
var context = RcObjImporter.LoadContext(chunk);
|
||||||
return new SimpleInputGeomProvider(context.vertexPositions, context.meshFaces);
|
return new SimpleInputGeomProvider(context.vertexPositions, context.meshFaces);
|
||||||
}
|
}
|
||||||
|
@ -77,12 +77,12 @@ namespace DotRecast.Recast.Geom
|
||||||
this.faces = faces;
|
this.faces = faces;
|
||||||
normals = new float[faces.Length];
|
normals = new float[faces.Length];
|
||||||
CalculateNormals();
|
CalculateNormals();
|
||||||
bmin = RcVecUtils.Create(vertices);
|
bmin = new RcVec3f(vertices);
|
||||||
bmax = RcVecUtils.Create(vertices);
|
bmax = new RcVec3f(vertices);
|
||||||
for (int i = 1; i < vertices.Length / 3; i++)
|
for (int i = 1; i < vertices.Length / 3; i++)
|
||||||
{
|
{
|
||||||
bmin = RcVecUtils.Min(bmin, vertices, i * 3);
|
bmin = RcVec3f.Min(bmin, RcVec.Create(vertices, i * 3));
|
||||||
bmax = RcVecUtils.Max(bmax, vertices, i * 3);
|
bmax = RcVec3f.Max(bmax, RcVec.Create(vertices, i * 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
_mesh = new RcTriMesh(vertices, faces);
|
_mesh = new RcTriMesh(vertices, faces);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public interface IRcBuilderProgressListener
|
public interface IRcBuilderProgressListener
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -25,8 +25,7 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcConstants;
|
using static RcRecast;
|
||||||
using static RcCommons;
|
|
||||||
|
|
||||||
public static class RcAreas
|
public static class RcAreas
|
||||||
{
|
{
|
||||||
|
@ -457,12 +456,12 @@ namespace DotRecast.Recast
|
||||||
int zStride = xSize; // For readability
|
int zStride = xSize; // For readability
|
||||||
|
|
||||||
// Compute the bounding box of the polygon
|
// Compute the bounding box of the polygon
|
||||||
RcVec3f bmin = RcVecUtils.Create(verts);
|
RcVec3f bmin = new RcVec3f(verts);
|
||||||
RcVec3f bmax = RcVecUtils.Create(verts);
|
RcVec3f bmax = new RcVec3f(verts);
|
||||||
for (int i = 3; i < verts.Length; i += 3)
|
for (int i = 3; i < verts.Length; i += 3)
|
||||||
{
|
{
|
||||||
bmin = RcVecUtils.Min(bmin, verts, i);
|
bmin = RcVec3f.Min(bmin, RcVec.Create(verts, i));
|
||||||
bmax = RcVecUtils.Max(bmax, verts, i);
|
bmax = RcVec3f.Max(bmax, RcVec.Create(verts, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
bmin.Y = minY;
|
bmin.Y = minY;
|
||||||
|
@ -753,19 +752,19 @@ namespace DotRecast.Recast
|
||||||
int vertIndexB = vertIndex;
|
int vertIndexB = vertIndex;
|
||||||
int vertIndexC = (vertIndex + 1) % numVerts;
|
int vertIndexC = (vertIndex + 1) % numVerts;
|
||||||
|
|
||||||
RcVec3f vertA = RcVecUtils.Create(verts, vertIndexA * 3);
|
RcVec3f vertA = RcVec.Create(verts, vertIndexA * 3);
|
||||||
RcVec3f vertB = RcVecUtils.Create(verts, vertIndexB * 3);
|
RcVec3f vertB = RcVec.Create(verts, vertIndexB * 3);
|
||||||
RcVec3f vertC = RcVecUtils.Create(verts, vertIndexC * 3);
|
RcVec3f vertC = RcVec.Create(verts, vertIndexC * 3);
|
||||||
|
|
||||||
// From A to B on the x/z plane
|
// From A to B on the x/z plane
|
||||||
RcVec3f prevSegmentDir = RcVec3f.Subtract(vertB, vertA);
|
RcVec3f prevSegmentDir = RcVec3f.Subtract(vertB, vertA);
|
||||||
prevSegmentDir.Y = 0; // Squash onto x/z plane
|
prevSegmentDir.Y = 0; // Squash onto x/z plane
|
||||||
prevSegmentDir = RcVecUtils.SafeNormalize(prevSegmentDir);
|
prevSegmentDir = RcVec.SafeNormalize(prevSegmentDir);
|
||||||
|
|
||||||
// From B to C on the x/z plane
|
// From B to C on the x/z plane
|
||||||
RcVec3f currSegmentDir = RcVec3f.Subtract(vertC, vertB);
|
RcVec3f currSegmentDir = RcVec3f.Subtract(vertC, vertB);
|
||||||
currSegmentDir.Y = 0; // Squash onto x/z plane
|
currSegmentDir.Y = 0; // Squash onto x/z plane
|
||||||
currSegmentDir = RcVecUtils.SafeNormalize(currSegmentDir);
|
currSegmentDir = RcVec.SafeNormalize(currSegmentDir);
|
||||||
|
|
||||||
// The y component of the cross product of the two normalized segment directions.
|
// The y component of the cross product of the two normalized segment directions.
|
||||||
// The X and Z components of the cross product are both zero because the two
|
// The X and Z components of the cross product are both zero because the two
|
||||||
|
@ -792,7 +791,7 @@ namespace DotRecast.Recast
|
||||||
bool bevel = cornerMiterSqMag * MITER_LIMIT * MITER_LIMIT < 1.0f;
|
bool bevel = cornerMiterSqMag * MITER_LIMIT * MITER_LIMIT < 1.0f;
|
||||||
|
|
||||||
// Scale the corner miter so it's proportional to how much the corner should be offset compared to the edges.
|
// Scale the corner miter so it's proportional to how much the corner should be offset compared to the edges.
|
||||||
if (cornerMiterSqMag > RcVecUtils.EPSILON)
|
if (cornerMiterSqMag > RcVec.EPSILON)
|
||||||
{
|
{
|
||||||
float scale = 1.0f / cornerMiterSqMag;
|
float scale = 1.0f / cornerMiterSqMag;
|
||||||
cornerMiterX *= scale;
|
cornerMiterX *= scale;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public static class RcAxis
|
public static class RcAxis
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
/// Contour build flags.
|
/// Contour build flags.
|
||||||
/// @see rcBuildContours
|
/// @see rcBuildContours
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -30,7 +30,7 @@ using DotRecast.Recast.Geom;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcCommons;
|
using static RcRecast;
|
||||||
using static RcAreas;
|
using static RcAreas;
|
||||||
|
|
||||||
public class RcBuilder
|
public class RcBuilder
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -92,7 +92,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RcCommons.CalcGridSize(this.bmin, this.bmax, cfg.Cs, out width, out height);
|
RcRecast.CalcGridSize(this.bmin, this.bmax, cfg.Cs, out width, out height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public class RcCompactSpanBuilder
|
public class RcCompactSpanBuilder
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -20,17 +20,14 @@ freely, subject to the following restrictions:
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using static DotRecast.Recast.RcConstants;
|
|
||||||
|
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcCommons;
|
using static RcRecast;
|
||||||
|
|
||||||
|
|
||||||
public static class RcCompacts
|
public static class RcCompacts
|
||||||
{
|
{
|
||||||
private const int MAX_HEIGHT = RcConstants.RC_SPAN_MAX_HEIGHT;
|
private const int MAX_HEIGHT = RC_SPAN_MAX_HEIGHT;
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
/// @name Compact Heightfield Functions
|
/// @name Compact Heightfield Functions
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,93 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
|
||||||
{
|
|
||||||
public static class RcConstants
|
|
||||||
{
|
|
||||||
/// Represents the null area.
|
|
||||||
/// When a data element is given this value it is considered to no longer be
|
|
||||||
/// assigned to a usable area. (E.g. It is un-walkable.)
|
|
||||||
public const int RC_NULL_AREA = 0;
|
|
||||||
|
|
||||||
/// The default area id used to indicate a walkable polygon.
|
|
||||||
/// This is also the maximum allowed area id, and the only non-null area id
|
|
||||||
/// recognized by some steps in the build process.
|
|
||||||
public const int RC_WALKABLE_AREA = 63;
|
|
||||||
|
|
||||||
/// The value returned by #rcGetCon if the specified direction is not connected
|
|
||||||
/// to another span. (Has no neighbor.)
|
|
||||||
public const int RC_NOT_CONNECTED = 0x3f;
|
|
||||||
|
|
||||||
/// Defines the number of bits allocated to rcSpan::smin and rcSpan::smax.
|
|
||||||
public const int RC_SPAN_HEIGHT_BITS = 20;
|
|
||||||
|
|
||||||
/// Defines the maximum value for rcSpan::smin and rcSpan::smax.
|
|
||||||
public const int RC_SPAN_MAX_HEIGHT = (1 << RC_SPAN_HEIGHT_BITS) - 1;
|
|
||||||
|
|
||||||
/// The number of spans allocated per span spool.
|
|
||||||
/// @see rcSpanPool
|
|
||||||
public const int RC_SPANS_PER_POOL = 2048;
|
|
||||||
|
|
||||||
/// Heighfield border flag.
|
|
||||||
/// If a heightfield region ID has this bit set, then the region is a border
|
|
||||||
/// region and its spans are considered unwalkable.
|
|
||||||
/// (Used during the region and contour build process.)
|
|
||||||
/// @see rcCompactSpan::reg
|
|
||||||
public const int RC_BORDER_REG = 0x8000;
|
|
||||||
|
|
||||||
/// Polygon touches multiple regions.
|
|
||||||
/// If a polygon has this region ID it was merged with or created
|
|
||||||
/// from polygons of different regions during the polymesh
|
|
||||||
/// build step that removes redundant border vertices.
|
|
||||||
/// (Used during the polymesh and detail polymesh build processes)
|
|
||||||
/// @see rcPolyMesh::regs
|
|
||||||
public const int RC_MULTIPLE_REGS = 0;
|
|
||||||
|
|
||||||
// Border vertex flag.
|
|
||||||
/// If a region ID has this bit set, then the associated element lies on
|
|
||||||
/// a tile border. If a contour vertex's region ID has this bit set, the
|
|
||||||
/// vertex will later be removed in order to match the segments and vertices
|
|
||||||
/// at tile boundaries.
|
|
||||||
/// (Used during the build process.)
|
|
||||||
/// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts
|
|
||||||
public const int RC_BORDER_VERTEX = 0x10000;
|
|
||||||
|
|
||||||
/// Area border flag.
|
|
||||||
/// If a region ID has this bit set, then the associated element lies on
|
|
||||||
/// the border of an area.
|
|
||||||
/// (Used during the region and contour build process.)
|
|
||||||
/// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts
|
|
||||||
public const int RC_AREA_BORDER = 0x20000;
|
|
||||||
|
|
||||||
/// Applied to the region id field of contour vertices in order to extract the region id.
|
|
||||||
/// The region id field of a vertex may have several flags applied to it. So the
|
|
||||||
/// fields value can't be used directly.
|
|
||||||
/// @see rcContour::verts, rcContour::rverts
|
|
||||||
public const int RC_CONTOUR_REG_MASK = 0xffff;
|
|
||||||
|
|
||||||
/// A value which indicates an invalid index within a mesh.
|
|
||||||
/// @note This does not necessarily indicate an error.
|
|
||||||
/// @see rcPolyMesh::polys
|
|
||||||
public const int RC_MESH_NULL_IDX = 0xffff;
|
|
||||||
|
|
||||||
public const int RC_LOG_WARNING = 1;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -20,25 +20,14 @@ freely, subject to the following restrictions:
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
/** Represents a simple, non-overlapping contour in field space. */
|
/// Represents a simple, non-overlapping contour in field space.
|
||||||
public class RcContour
|
public class RcContour
|
||||||
{
|
{
|
||||||
/** Simplified contour vertex and connection data. [Size: 4 * #nverts] */
|
public int[] verts; //< Simplified contour vertex and connection data. [Size: 4 * #nverts]
|
||||||
public int[] verts;
|
public int nverts; //< The number of vertices in the simplified contour.
|
||||||
|
public int[] rverts; //< Raw contour vertex and connection data. [Size: 4 * #nrverts]
|
||||||
/** The number of vertices in the simplified contour. */
|
public int nrverts; //< The number of vertices in the raw contour.
|
||||||
public int nverts;
|
public int reg; //< The region id of the contour.
|
||||||
|
public int area; //< The area id of the contour.
|
||||||
/** Raw contour vertex and connection data. [Size: 4 * #nrverts] */
|
|
||||||
public int[] rverts;
|
|
||||||
|
|
||||||
/** The number of vertices in the raw contour. */
|
|
||||||
public int nrverts;
|
|
||||||
|
|
||||||
/** The region id of the contour. */
|
|
||||||
public int area;
|
|
||||||
|
|
||||||
/** The area id of the contour. */
|
|
||||||
public int reg;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public class RcContourHole
|
public class RcContourHole
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public class RcContourRegion
|
public class RcContourRegion
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -24,8 +24,8 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcConstants;
|
|
||||||
using static RcCommons;
|
using static RcRecast;
|
||||||
|
|
||||||
public static class RcContours
|
public static class RcContours
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
// Struct to keep track of entries in the region table that have been changed.
|
// Struct to keep track of entries in the region table that have been changed.
|
||||||
public readonly struct RcDirtyEntry
|
public readonly struct RcDirtyEntry
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -20,11 +20,11 @@ freely, subject to the following restrictions:
|
||||||
using System;
|
using System;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using static DotRecast.Recast.RcConstants;
|
|
||||||
|
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
|
using static RcRecast;
|
||||||
|
|
||||||
public static class RcFilledVolumeRasterization
|
public static class RcFilledVolumeRasterization
|
||||||
{
|
{
|
||||||
private const float EPSILON = 0.00001f;
|
private const float EPSILON = 0.00001f;
|
||||||
|
@ -176,7 +176,7 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
private static void Plane(float[][] planes, int p, float[] v1, float[] v2, float[] vertices, int vert)
|
private static void Plane(float[][] planes, int p, float[] v1, float[] v2, float[] vertices, int vert)
|
||||||
{
|
{
|
||||||
RcVecUtils.Cross(planes[p], v1, v2);
|
RcVec.Cross(planes[p], v1, v2);
|
||||||
planes[p][3] = planes[p][0] * vertices[vert] + planes[p][1] * vertices[vert + 1] + planes[p][2] * vertices[vert + 2];
|
planes[p][3] = planes[p][0] * vertices[vert] + planes[p][1] * vertices[vert + 1] + planes[p][2] * vertices[vert + 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,8 +296,8 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
if (axis.Y * axis.Y > EPSILON)
|
if (axis.Y * axis.Y > EPSILON)
|
||||||
{
|
{
|
||||||
RcVec3f[] rectangleOnStartPlane = new RcVec3f[4];
|
Span<RcVec3f> rectangleOnStartPlane = stackalloc RcVec3f[4];
|
||||||
RcVec3f[] rectangleOnEndPlane = new RcVec3f[4];
|
Span<RcVec3f> rectangleOnEndPlane = stackalloc RcVec3f[4];
|
||||||
float ds = RcVec3f.Dot(axis, start);
|
float ds = RcVec3f.Dot(axis, start);
|
||||||
float de = RcVec3f.Dot(axis, end);
|
float de = RcVec3f.Dot(axis, end);
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
|
@ -326,7 +326,7 @@ namespace DotRecast.Recast
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float[] CylinderCapIntersection(RcVec3f start, float radiusSqr, float[] s, int i, RcVec3f[] rectangleOnPlane)
|
private static float[] CylinderCapIntersection(RcVec3f start, float radiusSqr, float[] s, int i, Span<RcVec3f> rectangleOnPlane)
|
||||||
{
|
{
|
||||||
int j = (i + 1) % 4;
|
int j = (i + 1) % 4;
|
||||||
// Ray against sphere intersection
|
// Ray against sphere intersection
|
||||||
|
@ -507,8 +507,8 @@ namespace DotRecast.Recast
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
int vi = i * 3;
|
int vi = i * 3;
|
||||||
if (vertices[vi] >= rectangle[0] && vertices[vi] < rectangle[2] && vertices[vi + 2] >= rectangle[1]
|
if (vertices[vi] >= rectangle[0] && vertices[vi] < rectangle[2] &&
|
||||||
&& vertices[vi + 2] < rectangle[3])
|
vertices[vi + 2] >= rectangle[1] && vertices[vi + 2] < rectangle[3])
|
||||||
{
|
{
|
||||||
yMin = Math.Min(yMin, vertices[vi + 1]);
|
yMin = Math.Min(yMin, vertices[vi + 1]);
|
||||||
yMax = Math.Max(yMax, vertices[vi + 1]);
|
yMax = Math.Max(yMax, vertices[vi + 1]);
|
||||||
|
@ -525,7 +525,7 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
if (MathF.Abs(planes[j][1]) > EPSILON)
|
if (MathF.Abs(planes[j][1]) > EPSILON)
|
||||||
{
|
{
|
||||||
float dotNormalPoint = RcVecUtils.Dot(planes[j], point);
|
float dotNormalPoint = RcVec3f.Dot(new RcVec3f(planes[j]), point);
|
||||||
float t = (planes[j][3] - dotNormalPoint) / planes[j][1];
|
float t = (planes[j][3] - dotNormalPoint) / planes[j][1];
|
||||||
float y = point.Y + t;
|
float y = point.Y + t;
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
|
@ -729,15 +729,15 @@ namespace DotRecast.Recast
|
||||||
private static bool RayTriangleIntersection(RcVec3f point, int plane, float[][] planes, out float y)
|
private static bool RayTriangleIntersection(RcVec3f point, int plane, float[][] planes, out float y)
|
||||||
{
|
{
|
||||||
y = 0.0f;
|
y = 0.0f;
|
||||||
float t = (planes[plane][3] - RcVecUtils.Dot(planes[plane], point)) / planes[plane][1];
|
float t = (planes[plane][3] - RcVec3f.Dot(new RcVec3f(planes[plane]), point)) / planes[plane][1];
|
||||||
float[] s = { point.X, point.Y + t, point.Z };
|
RcVec3f s = new RcVec3f(point.X, point.Y + t, point.Z);
|
||||||
float u = RcVecUtils.Dot(s, planes[plane + 1]) - planes[plane + 1][3];
|
float u = RcVec3f.Dot(s, new RcVec3f(planes[plane + 1])) - planes[plane + 1][3];
|
||||||
if (u < 0.0f || u > 1.0f)
|
if (u < 0.0f || u > 1.0f)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float v = RcVecUtils.Dot(s, planes[plane + 2]) - planes[plane + 2][3];
|
float v = RcVec3f.Dot(s, new RcVec3f(planes[plane + 2])) - planes[plane + 2][3];
|
||||||
if (v < 0.0f)
|
if (v < 0.0f)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -749,7 +749,7 @@ namespace DotRecast.Recast
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
y = s[1];
|
y = s.Y;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -23,8 +23,8 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcConstants;
|
|
||||||
using static RcCommons;
|
using static RcRecast;
|
||||||
|
|
||||||
public static class RcFilters
|
public static class RcFilters
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public class RcHeightPatch
|
public class RcHeightPatch
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,23 +1,23 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public class RcLayerRegion
|
public class RcLayerRegion
|
||||||
{
|
{
|
||||||
public int id;
|
public readonly int index;
|
||||||
public int layerId; // Layer ID
|
public List<int> layers;
|
||||||
public bool @base; // Flag indicating if the region is the base of merged regions.
|
public List<int> neis;
|
||||||
public int ymin, ymax;
|
public int ymin, ymax;
|
||||||
public List<int> layers; // Layer count
|
public byte layerId; // Layer ID
|
||||||
public List<int> neis; // Neighbour count
|
public bool @base; // Flag indicating if the region is the base of merged regions.
|
||||||
|
|
||||||
public RcLayerRegion(int i)
|
public RcLayerRegion(int i)
|
||||||
{
|
{
|
||||||
id = i;
|
index = i;
|
||||||
ymin = 0xFFFF;
|
|
||||||
layerId = 0xff;
|
|
||||||
layers = new List<int>();
|
layers = new List<int>();
|
||||||
neis = new List<int>();
|
neis = new List<int>();
|
||||||
|
ymin = 0xFFFF;
|
||||||
|
layerId = 0xff;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public class RcLayerSweepSpan
|
public class RcLayerSweepSpan
|
||||||
{
|
{
|
||||||
public int ns; // number samples
|
public int ns; // number samples
|
||||||
public int id; // region id
|
public byte id; // region id
|
||||||
public int nei; // neighbour id
|
public byte nei; // neighbour id
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -25,15 +25,10 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcConstants;
|
using static RcRecast;
|
||||||
using static RcCommons;
|
|
||||||
|
|
||||||
public static class RcLayers
|
public static class RcLayers
|
||||||
{
|
{
|
||||||
const int RC_MAX_LAYERS = RcConstants.RC_NOT_CONNECTED;
|
|
||||||
const int RC_MAX_NEIS = 16;
|
|
||||||
|
|
||||||
|
|
||||||
private static void AddUnique(List<int> a, int v)
|
private static void AddUnique(List<int> a, int v)
|
||||||
{
|
{
|
||||||
if (!a.Contains(v))
|
if (!a.Contains(v))
|
||||||
|
@ -61,7 +56,6 @@ namespace DotRecast.Recast
|
||||||
/// @name Layer, Contour, Polymesh, and Detail Mesh Functions
|
/// @name Layer, Contour, Polymesh, and Detail Mesh Functions
|
||||||
/// @see rcHeightfieldLayer, rcContourSet, rcPolyMesh, rcPolyMeshDetail
|
/// @see rcHeightfieldLayer, rcContourSet, rcPolyMesh, rcPolyMeshDetail
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
/// Builds a layer set from the specified compact heightfield.
|
/// Builds a layer set from the specified compact heightfield.
|
||||||
/// @ingroup recast
|
/// @ingroup recast
|
||||||
/// @param[in,out] ctx The build context to use during the operation.
|
/// @param[in,out] ctx The build context to use during the operation.
|
||||||
|
@ -80,10 +74,10 @@ namespace DotRecast.Recast
|
||||||
int w = chf.width;
|
int w = chf.width;
|
||||||
int h = chf.height;
|
int h = chf.height;
|
||||||
|
|
||||||
int[] srcReg = new int[chf.spanCount];
|
Span<byte> srcReg = stackalloc byte[chf.spanCount];
|
||||||
Array.Fill(srcReg, 0xFF);
|
srcReg.Fill(0xFF);
|
||||||
|
|
||||||
int nsweeps = chf.width; // Math.Max(chf.width, chf.height);
|
int nsweeps = chf.width;
|
||||||
RcLayerSweepSpan[] sweeps = new RcLayerSweepSpan[nsweeps];
|
RcLayerSweepSpan[] sweeps = new RcLayerSweepSpan[nsweeps];
|
||||||
for (int i = 0; i < sweeps.Length; i++)
|
for (int i = 0; i < sweeps.Length; i++)
|
||||||
{
|
{
|
||||||
|
@ -91,15 +85,15 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// Partition walkable area into monotone regions.
|
// Partition walkable area into monotone regions.
|
||||||
int[] prevCount = new int[256];
|
Span<int> prevCount = stackalloc int[256];
|
||||||
int regId = 0;
|
byte regId = 0;
|
||||||
|
|
||||||
// Sweep one line at a time.
|
// Sweep one line at a time.
|
||||||
for (int y = borderSize; y < h - borderSize; ++y)
|
for (int y = borderSize; y < h - borderSize; ++y)
|
||||||
{
|
{
|
||||||
// Collect spans from this row.
|
// Collect spans from this row.
|
||||||
Array.Fill(prevCount, 0);
|
prevCount.Fill(0);
|
||||||
int sweepId = 0;
|
byte sweepId = 0;
|
||||||
|
|
||||||
for (int x = borderSize; x < w - borderSize; ++x)
|
for (int x = borderSize; x < w - borderSize; ++x)
|
||||||
{
|
{
|
||||||
|
@ -111,7 +105,7 @@ namespace DotRecast.Recast
|
||||||
if (chf.areas[i] == RC_NULL_AREA)
|
if (chf.areas[i] == RC_NULL_AREA)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int sid = 0xFF;
|
byte sid = 0xFF;
|
||||||
|
|
||||||
// -x
|
// -x
|
||||||
if (GetCon(ref s, 0) != RC_NOT_CONNECTED)
|
if (GetCon(ref s, 0) != RC_NOT_CONNECTED)
|
||||||
|
@ -136,7 +130,7 @@ namespace DotRecast.Recast
|
||||||
int ax = x + GetDirOffsetX(3);
|
int ax = x + GetDirOffsetX(3);
|
||||||
int ay = y + GetDirOffsetY(3);
|
int ay = y + GetDirOffsetY(3);
|
||||||
int ai = chf.cells[ax + ay * w].index + GetCon(ref s, 3);
|
int ai = chf.cells[ax + ay * w].index + GetCon(ref s, 3);
|
||||||
int nr = srcReg[ai];
|
byte nr = srcReg[ai];
|
||||||
if (nr != 0xff)
|
if (nr != 0xff)
|
||||||
{
|
{
|
||||||
// Set neighbour when first valid neighbour is encoutered.
|
// Set neighbour when first valid neighbour is encoutered.
|
||||||
|
@ -266,9 +260,11 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create 2D layers from regions.
|
// Create 2D layers from regions.
|
||||||
int layerId = 0;
|
byte layerId = 0;
|
||||||
|
|
||||||
List<int> stack = new List<int>();
|
const int MAX_STACK = 64;
|
||||||
|
Span<byte> stack = stackalloc byte[MAX_STACK];
|
||||||
|
int nstack = 0;
|
||||||
|
|
||||||
for (int i = 0; i < nregs; ++i)
|
for (int i = 0; i < nregs; ++i)
|
||||||
{
|
{
|
||||||
|
@ -281,14 +277,16 @@ namespace DotRecast.Recast
|
||||||
root.layerId = layerId;
|
root.layerId = layerId;
|
||||||
root.@base = true;
|
root.@base = true;
|
||||||
|
|
||||||
stack.Add(i);
|
nstack = 0;
|
||||||
|
stack[nstack++] = ((byte)i);
|
||||||
|
|
||||||
while (stack.Count != 0)
|
while (0 != nstack)
|
||||||
{
|
{
|
||||||
// Pop front
|
// Pop front
|
||||||
int pop = stack[0]; // TODO : 여기에 stack 처럼 작동하게 했는데, 스택인지는 모르겠음
|
RcLayerRegion reg = regs[stack[0]];
|
||||||
stack.RemoveAt(0);
|
nstack--;
|
||||||
RcLayerRegion reg = regs[pop];
|
for (int j = 0; j < nstack; ++j)
|
||||||
|
stack[j] = stack[j + 1];
|
||||||
|
|
||||||
foreach (int nei in reg.neis)
|
foreach (int nei in reg.neis)
|
||||||
{
|
{
|
||||||
|
@ -307,19 +305,22 @@ namespace DotRecast.Recast
|
||||||
if ((ymax - ymin) >= 255)
|
if ((ymax - ymin) >= 255)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Deepen
|
if (nstack < MAX_STACK)
|
||||||
stack.Add(nei);
|
|
||||||
|
|
||||||
// Mark layer id
|
|
||||||
regn.layerId = layerId;
|
|
||||||
// Merge current layers to root.
|
|
||||||
foreach (int layer in regn.layers)
|
|
||||||
{
|
{
|
||||||
AddUnique(root.layers, layer);
|
// Deepen
|
||||||
}
|
stack[nstack++] = (byte)nei;
|
||||||
|
|
||||||
root.ymin = Math.Min(root.ymin, regn.ymin);
|
// Mark layer id
|
||||||
root.ymax = Math.Max(root.ymax, regn.ymax);
|
regn.layerId = layerId;
|
||||||
|
// Merge current layers to root.
|
||||||
|
foreach (int layer in regn.layers)
|
||||||
|
{
|
||||||
|
AddUnique(root.layers, layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
root.ymin = Math.Min(root.ymin, regn.ymin);
|
||||||
|
root.ymax = Math.Max(root.ymax, regn.ymax);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +336,7 @@ namespace DotRecast.Recast
|
||||||
if (!ri.@base)
|
if (!ri.@base)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int newId = ri.layerId;
|
byte newId = ri.layerId;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -411,7 +412,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compact layerIds
|
// Compact layerIds
|
||||||
int[] remap = new int[256];
|
Span<byte> remap = stackalloc byte[256];
|
||||||
|
|
||||||
// Find number of unique layers.
|
// Find number of unique layers.
|
||||||
layerId = 0;
|
layerId = 0;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public readonly struct RcLevelStackEntry
|
public readonly struct RcLevelStackEntry
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -22,178 +22,57 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using static DotRecast.Recast.RcConstants;
|
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcCommons;
|
using static RcRecast;
|
||||||
|
using static RcVec;
|
||||||
|
using static EdgeValues;
|
||||||
|
|
||||||
public static class RcMeshDetails
|
public static class RcMeshDetails
|
||||||
{
|
{
|
||||||
public const int MAX_VERTS = 127;
|
public const int RC_UNSET_HEIGHT = RC_SPAN_MAX_HEIGHT;
|
||||||
public const int MAX_TRIS = 255; // Max tris for delaunay is 2n-2-k (n=num verts, k=num hull verts).
|
|
||||||
public const int MAX_VERTS_PER_EDGE = 32;
|
|
||||||
|
|
||||||
public const int RC_UNSET_HEIGHT = RcConstants.RC_SPAN_MAX_HEIGHT;
|
|
||||||
public const int EV_UNDEF = -1;
|
|
||||||
public const int EV_HULL = -2;
|
|
||||||
|
|
||||||
|
|
||||||
private static float Vdot2(float[] a, float[] b)
|
public static bool CircumCircle(RcVec3f p1, RcVec3f p2, RcVec3f p3, ref RcVec3f c, out float r)
|
||||||
{
|
|
||||||
return a[0] * b[0] + a[2] * b[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float Vdot2(RcVec3f a, RcVec3f b)
|
|
||||||
{
|
|
||||||
return a.X * b.X + a.Z * b.Z;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static float VdistSq2(float[] verts, int p, int q)
|
|
||||||
{
|
|
||||||
float dx = verts[q + 0] - verts[p + 0];
|
|
||||||
float dy = verts[q + 2] - verts[p + 2];
|
|
||||||
return dx * dx + dy * dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float Vdist2(float[] verts, int p, int q)
|
|
||||||
{
|
|
||||||
return MathF.Sqrt(VdistSq2(verts, p, q));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float VdistSq2(float[] p, float[] q)
|
|
||||||
{
|
|
||||||
float dx = q[0] - p[0];
|
|
||||||
float dy = q[2] - p[2];
|
|
||||||
return dx * dx + dy * dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float VdistSq2(float[] p, RcVec3f q)
|
|
||||||
{
|
|
||||||
float dx = q.X - p[0];
|
|
||||||
float dy = q.Z - p[2];
|
|
||||||
return dx * dx + dy * dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static float VdistSq2(RcVec3f p, RcVec3f q)
|
|
||||||
{
|
|
||||||
float dx = q.X - p.X;
|
|
||||||
float dy = q.Z - p.Z;
|
|
||||||
return dx * dx + dy * dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static float Vdist2(float[] p, float[] q)
|
|
||||||
{
|
|
||||||
return MathF.Sqrt(VdistSq2(p, q));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float Vdist2(RcVec3f p, RcVec3f q)
|
|
||||||
{
|
|
||||||
return MathF.Sqrt(VdistSq2(p, q));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float Vdist2(float[] p, RcVec3f q)
|
|
||||||
{
|
|
||||||
return MathF.Sqrt(VdistSq2(p, q));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static float VdistSq2(float[] p, float[] verts, int q)
|
|
||||||
{
|
|
||||||
float dx = verts[q + 0] - p[0];
|
|
||||||
float dy = verts[q + 2] - p[2];
|
|
||||||
return dx * dx + dy * dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float VdistSq2(RcVec3f p, float[] verts, int q)
|
|
||||||
{
|
|
||||||
float dx = verts[q + 0] - p.X;
|
|
||||||
float dy = verts[q + 2] - p.Z;
|
|
||||||
return dx * dx + dy * dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static float Vdist2(float[] p, float[] verts, int q)
|
|
||||||
{
|
|
||||||
return MathF.Sqrt(VdistSq2(p, verts, q));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float Vdist2(RcVec3f p, float[] verts, int q)
|
|
||||||
{
|
|
||||||
return MathF.Sqrt(VdistSq2(p, verts, q));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static float Vcross2(float[] verts, int p1, int p2, int p3)
|
|
||||||
{
|
|
||||||
float u1 = verts[p2 + 0] - verts[p1 + 0];
|
|
||||||
float v1 = verts[p2 + 2] - verts[p1 + 2];
|
|
||||||
float u2 = verts[p3 + 0] - verts[p1 + 0];
|
|
||||||
float v2 = verts[p3 + 2] - verts[p1 + 2];
|
|
||||||
return u1 * v2 - v1 * u2;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float Vcross2(float[] p1, float[] p2, float[] p3)
|
|
||||||
{
|
|
||||||
float u1 = p2[0] - p1[0];
|
|
||||||
float v1 = p2[2] - p1[2];
|
|
||||||
float u2 = p3[0] - p1[0];
|
|
||||||
float v2 = p3[2] - p1[2];
|
|
||||||
return u1 * v2 - v1 * u2;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float Vcross2(RcVec3f p1, RcVec3f p2, RcVec3f p3)
|
|
||||||
{
|
|
||||||
float u1 = p2.X - p1.X;
|
|
||||||
float v1 = p2.Z - p1.Z;
|
|
||||||
float u2 = p3.X - p1.X;
|
|
||||||
float v2 = p3.Z - p1.Z;
|
|
||||||
return u1 * v2 - v1 * u2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static bool CircumCircle(float[] verts, int p1, int p2, int p3, ref RcVec3f c, RcAtomicFloat r)
|
|
||||||
{
|
{
|
||||||
const float EPS = 1e-6f;
|
const float EPS = 1e-6f;
|
||||||
// Calculate the circle relative to p1, to avoid some precision issues.
|
// Calculate the circle relative to p1, to avoid some precision issues.
|
||||||
var v1 = new RcVec3f();
|
var v1 = new RcVec3f();
|
||||||
var v2 = RcVecUtils.Subtract(verts, p2, p1);
|
var v2 = p2 - p1;
|
||||||
var v3 = RcVecUtils.Subtract(verts, p3, p1);
|
var v3 = p3 - p1;
|
||||||
|
|
||||||
float cp = Vcross2(v1, v2, v3);
|
float cp = Cross2(v1, v2, v3);
|
||||||
if (MathF.Abs(cp) > EPS)
|
if (MathF.Abs(cp) > EPS)
|
||||||
{
|
{
|
||||||
float v1Sq = Vdot2(v1, v1);
|
float v1Sq = Dot2(v1, v1);
|
||||||
float v2Sq = Vdot2(v2, v2);
|
float v2Sq = Dot2(v2, v2);
|
||||||
float v3Sq = Vdot2(v3, v3);
|
float v3Sq = Dot2(v3, v3);
|
||||||
c.X = (v1Sq * (v2.Z - v3.Z) + v2Sq * (v3.Z - v1.Z) + v3Sq * (v1.Z - v2.Z)) / (2 * cp);
|
c.X = (v1Sq * (v2.Z - v3.Z) + v2Sq * (v3.Z - v1.Z) + v3Sq * (v1.Z - v2.Z)) / (2 * cp);
|
||||||
c.Y = 0;
|
c.Y = 0;
|
||||||
c.Z = (v1Sq * (v3.X - v2.X) + v2Sq * (v1.X - v3.X) + v3Sq * (v2.X - v1.X)) / (2 * cp);
|
c.Z = (v1Sq * (v3.X - v2.X) + v2Sq * (v1.X - v3.X) + v3Sq * (v2.X - v1.X)) / (2 * cp);
|
||||||
r.Exchange(Vdist2(c, v1));
|
r = Dist2(c, v1);
|
||||||
c = RcVecUtils.Add(c, verts, p1);
|
c = c + p1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = RcVecUtils.Create(verts, p1);
|
c = p1;
|
||||||
r.Exchange(0f);
|
r = 0f;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float DistPtTri(RcVec3f p, float[] verts, int a, int b, int c)
|
public static float DistPtTri(RcVec3f p, RcVec3f a, RcVec3f b, RcVec3f c)
|
||||||
{
|
{
|
||||||
var v0 = RcVecUtils.Subtract(verts, c, a);
|
var v0 = c - a;
|
||||||
var v1 = RcVecUtils.Subtract(verts, b, a);
|
var v1 = b - a;
|
||||||
var v2 = RcVecUtils.Subtract(p, verts, a);
|
var v2 = p - a;
|
||||||
|
|
||||||
float dot00 = Vdot2(v0, v0);
|
float dot00 = Dot2(v0, v0);
|
||||||
float dot01 = Vdot2(v0, v1);
|
float dot01 = Dot2(v0, v1);
|
||||||
float dot02 = Vdot2(v0, v2);
|
float dot02 = Dot2(v0, v2);
|
||||||
float dot11 = Vdot2(v1, v1);
|
float dot11 = Dot2(v1, v1);
|
||||||
float dot12 = Vdot2(v1, v2);
|
float dot12 = Dot2(v1, v2);
|
||||||
|
|
||||||
// Compute barycentric coordinates
|
// Compute barycentric coordinates
|
||||||
float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
|
float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
|
||||||
|
@ -204,14 +83,14 @@ namespace DotRecast.Recast
|
||||||
const float EPS = 1e-4f;
|
const float EPS = 1e-4f;
|
||||||
if (u >= -EPS && v >= -EPS && (u + v) <= 1 + EPS)
|
if (u >= -EPS && v >= -EPS && (u + v) <= 1 + EPS)
|
||||||
{
|
{
|
||||||
float y = verts[a + 1] + v0.Y * u + v1.Y * v;
|
float y = a.Y + v0.Y * u + v1.Y * v;
|
||||||
return MathF.Abs(y - p.Y);
|
return MathF.Abs(y - p.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
return float.MaxValue;
|
return float.MaxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float DistancePtSeg(float[] verts, int pt, int p, int q)
|
public static float DistancePtSeg(float[] verts, int pt, int p, int q)
|
||||||
{
|
{
|
||||||
float pqx = verts[q + 0] - verts[p + 0];
|
float pqx = verts[q + 0] - verts[p + 0];
|
||||||
float pqy = verts[q + 1] - verts[p + 1];
|
float pqy = verts[q + 1] - verts[p + 1];
|
||||||
|
@ -242,7 +121,7 @@ namespace DotRecast.Recast
|
||||||
return dx * dx + dy * dy + dz * dz;
|
return dx * dx + dy * dy + dz * dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float DistancePtSeg2d(RcVec3f verts, float[] poly, int p, int q)
|
public static float DistancePtSeg2d(RcVec3f verts, float[] poly, int p, int q)
|
||||||
{
|
{
|
||||||
float pqx = poly[q + 0] - poly[p + 0];
|
float pqx = poly[q + 0] - poly[p + 0];
|
||||||
float pqz = poly[q + 2] - poly[p + 2];
|
float pqz = poly[q + 2] - poly[p + 2];
|
||||||
|
@ -270,7 +149,7 @@ namespace DotRecast.Recast
|
||||||
return dx * dx + dz * dz;
|
return dx * dx + dz * dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float DistancePtSeg2d(float[] verts, int pt, float[] poly, int p, int q)
|
public static float DistancePtSeg2d(float[] verts, int pt, float[] poly, int p, int q)
|
||||||
{
|
{
|
||||||
float pqx = poly[q + 0] - poly[p + 0];
|
float pqx = poly[q + 0] - poly[p + 0];
|
||||||
float pqz = poly[q + 2] - poly[p + 2];
|
float pqz = poly[q + 2] - poly[p + 2];
|
||||||
|
@ -298,15 +177,15 @@ namespace DotRecast.Recast
|
||||||
return dx * dx + dz * dz;
|
return dx * dx + dz * dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float DistToTriMesh(RcVec3f p, float[] verts, int nverts, List<int> tris, int ntris)
|
public static float DistToTriMesh(RcVec3f p, float[] verts, int nverts, List<int> tris, int ntris)
|
||||||
{
|
{
|
||||||
float dmin = float.MaxValue;
|
float dmin = float.MaxValue;
|
||||||
for (int i = 0; i < ntris; ++i)
|
for (int i = 0; i < ntris; ++i)
|
||||||
{
|
{
|
||||||
int va = tris[i * 4 + 0] * 3;
|
RcVec3f va = RcVec.Create(verts, tris[i * 4 + 0] * 3);
|
||||||
int vb = tris[i * 4 + 1] * 3;
|
RcVec3f vb = RcVec.Create(verts, tris[i * 4 + 1] * 3);
|
||||||
int vc = tris[i * 4 + 2] * 3;
|
RcVec3f vc = RcVec.Create(verts, tris[i * 4 + 2] * 3);
|
||||||
float d = DistPtTri(p, verts, va, vb, vc);
|
float d = DistPtTri(p, va, vb, vc);
|
||||||
if (d < dmin)
|
if (d < dmin)
|
||||||
{
|
{
|
||||||
dmin = d;
|
dmin = d;
|
||||||
|
@ -321,7 +200,7 @@ namespace DotRecast.Recast
|
||||||
return dmin;
|
return dmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float DistToPoly(int nvert, float[] verts, RcVec3f p)
|
public static float DistToPoly(int nvert, float[] verts, RcVec3f p)
|
||||||
{
|
{
|
||||||
float dmin = float.MaxValue;
|
float dmin = float.MaxValue;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -342,7 +221,7 @@ namespace DotRecast.Recast
|
||||||
return c ? -dmin : dmin;
|
return c ? -dmin : dmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetHeight(float fx, float fy, float fz, float cs, float ics, float ch, int radius,
|
public static int GetHeight(float fx, float fy, float fz, float cs, float ics, float ch, int radius,
|
||||||
RcHeightPatch hp)
|
RcHeightPatch hp)
|
||||||
{
|
{
|
||||||
int ix = (int)MathF.Floor(fx * ics + 0.01f);
|
int ix = (int)MathF.Floor(fx * ics + 0.01f);
|
||||||
|
@ -425,7 +304,7 @@ namespace DotRecast.Recast
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int FindEdge(List<int> edges, int s, int t)
|
public static int FindEdge(List<int> edges, int s, int t)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < edges.Count / 4; i++)
|
for (int i = 0; i < edges.Count / 4; i++)
|
||||||
{
|
{
|
||||||
|
@ -439,7 +318,7 @@ namespace DotRecast.Recast
|
||||||
return EV_UNDEF;
|
return EV_UNDEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddEdge(RcContext ctx, List<int> edges, int maxEdges, int s, int t, int l, int r)
|
public static void AddEdge(RcContext ctx, List<int> edges, int maxEdges, int s, int t, int l, int r)
|
||||||
{
|
{
|
||||||
if (edges.Count / 4 >= maxEdges)
|
if (edges.Count / 4 >= maxEdges)
|
||||||
{
|
{
|
||||||
|
@ -457,7 +336,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdateLeftFace(List<int> edges, int e, int s, int t, int f)
|
public static void UpdateLeftFace(List<int> edges, int e, int s, int t, int f)
|
||||||
{
|
{
|
||||||
if (edges[e + 0] == s && edges[e + 1] == t && edges[e + 2] == EV_UNDEF)
|
if (edges[e + 0] == s && edges[e + 1] == t && edges[e + 2] == EV_UNDEF)
|
||||||
{
|
{
|
||||||
|
@ -469,13 +348,13 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool OverlapSegSeg2d(float[] verts, int a, int b, int c, int d)
|
public static bool OverlapSegSeg2d(float[] verts, int a, int b, int c, int d)
|
||||||
{
|
{
|
||||||
float a1 = Vcross2(verts, a, b, d);
|
float a1 = Cross2(verts, a, b, d);
|
||||||
float a2 = Vcross2(verts, a, b, c);
|
float a2 = Cross2(verts, a, b, c);
|
||||||
if (a1 * a2 < 0.0f)
|
if (a1 * a2 < 0.0f)
|
||||||
{
|
{
|
||||||
float a3 = Vcross2(verts, c, d, a);
|
float a3 = Cross2(verts, c, d, a);
|
||||||
float a4 = a3 + a2 - a1;
|
float a4 = a3 + a2 - a1;
|
||||||
if (a3 * a4 < 0.0f)
|
if (a3 * a4 < 0.0f)
|
||||||
{
|
{
|
||||||
|
@ -486,7 +365,7 @@ namespace DotRecast.Recast
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool OverlapEdges(float[] pts, List<int> edges, int s1, int t1)
|
public static bool OverlapEdges(float[] pts, List<int> edges, int s1, int t1)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < edges.Count / 4; ++i)
|
for (int i = 0; i < edges.Count / 4; ++i)
|
||||||
{
|
{
|
||||||
|
@ -507,7 +386,7 @@ namespace DotRecast.Recast
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CompleteFacet(RcContext ctx, float[] pts, int npts, List<int> edges, int maxEdges, int nfaces, int e)
|
public static int CompleteFacet(RcContext ctx, float[] pts, int npts, List<int> edges, int maxEdges, int nfaces, int e)
|
||||||
{
|
{
|
||||||
const float EPS = 1e-5f;
|
const float EPS = 1e-5f;
|
||||||
|
|
||||||
|
@ -534,7 +413,7 @@ namespace DotRecast.Recast
|
||||||
// Find best point on left of edge.
|
// Find best point on left of edge.
|
||||||
int pt = npts;
|
int pt = npts;
|
||||||
RcVec3f c = new RcVec3f();
|
RcVec3f c = new RcVec3f();
|
||||||
RcAtomicFloat r = new RcAtomicFloat(-1f);
|
float r = -1f;
|
||||||
for (int u = 0; u < npts; ++u)
|
for (int u = 0; u < npts; ++u)
|
||||||
{
|
{
|
||||||
if (u == s || u == t)
|
if (u == s || u == t)
|
||||||
|
@ -542,28 +421,32 @@ namespace DotRecast.Recast
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Vcross2(pts, s * 3, t * 3, u * 3) > EPS)
|
RcVec3f vs = RcVec.Create(pts, s * 3);
|
||||||
|
RcVec3f vt = RcVec.Create(pts, t * 3);
|
||||||
|
RcVec3f vu = RcVec.Create(pts, u * 3);
|
||||||
|
|
||||||
|
if (Cross2(vs, vt, vu) > EPS)
|
||||||
{
|
{
|
||||||
if (r.Get() < 0)
|
if (r < 0)
|
||||||
{
|
{
|
||||||
// The circle is not updated yet, do it now.
|
// The circle is not updated yet, do it now.
|
||||||
pt = u;
|
pt = u;
|
||||||
CircumCircle(pts, s * 3, t * 3, u * 3, ref c, r);
|
CircumCircle(vs, vt, vu, ref c, out r);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float d = Vdist2(c, pts, u * 3);
|
float d = Dist2(c, vu);
|
||||||
float tol = 0.001f;
|
float tol = 0.001f;
|
||||||
if (d > r.Get() * (1 + tol))
|
if (d > r * (1 + tol))
|
||||||
{
|
{
|
||||||
// Outside current circumcircle, skip.
|
// Outside current circumcircle, skip.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (d < r.Get() * (1 - tol))
|
else if (d < r * (1 - tol))
|
||||||
{
|
{
|
||||||
// Inside safe circumcircle, update circle.
|
// Inside safe circumcircle, update circle.
|
||||||
pt = u;
|
pt = u;
|
||||||
CircumCircle(pts, s * 3, t * 3, u * 3, ref c, r);
|
CircumCircle(vs, vt, vu, ref c, out r);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -581,7 +464,7 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
// Edge is valid.
|
// Edge is valid.
|
||||||
pt = u;
|
pt = u;
|
||||||
CircumCircle(pts, s * 3, t * 3, u * 3, ref c, r);
|
CircumCircle(vs, vt, vu, ref c, out r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -624,7 +507,7 @@ namespace DotRecast.Recast
|
||||||
return nfaces;
|
return nfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DelaunayHull(RcContext ctx, int npts, float[] pts, int nhull, int[] hull, List<int> tris)
|
public static void DelaunayHull(RcContext ctx, int npts, float[] pts, int nhull, int[] hull, List<int> tris)
|
||||||
{
|
{
|
||||||
int nfaces = 0;
|
int nfaces = 0;
|
||||||
int maxEdges = npts * 10;
|
int maxEdges = npts * 10;
|
||||||
|
@ -720,7 +603,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate minimum extend of the polygon.
|
// Calculate minimum extend of the polygon.
|
||||||
private static float PolyMinExtent(float[] verts, int nverts)
|
public static float PolyMinExtent(float[] verts, int nverts)
|
||||||
{
|
{
|
||||||
float minDist = float.MaxValue;
|
float minDist = float.MaxValue;
|
||||||
for (int i = 0; i < nverts; i++)
|
for (int i = 0; i < nverts; i++)
|
||||||
|
@ -746,7 +629,7 @@ namespace DotRecast.Recast
|
||||||
return MathF.Sqrt(minDist);
|
return MathF.Sqrt(minDist);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TriangulateHull(int nverts, float[] verts, int nhull, int[] hull, int nin, List<int> tris)
|
public static void TriangulateHull(int nverts, float[] verts, int nhull, int[] hull, int nin, List<int> tris)
|
||||||
{
|
{
|
||||||
int start = 0, left = 1, right = nhull - 1;
|
int start = 0, left = 1, right = nhull - 1;
|
||||||
|
|
||||||
|
@ -766,7 +649,7 @@ namespace DotRecast.Recast
|
||||||
int pv = hull[pi] * 3;
|
int pv = hull[pi] * 3;
|
||||||
int cv = hull[i] * 3;
|
int cv = hull[i] * 3;
|
||||||
int nv = hull[ni] * 3;
|
int nv = hull[ni] * 3;
|
||||||
float d = Vdist2(verts, pv, cv) + Vdist2(verts, cv, nv) + Vdist2(verts, nv, pv);
|
float d = Dist2(verts, pv, cv) + Dist2(verts, cv, nv) + Dist2(verts, nv, pv);
|
||||||
if (d < dmin)
|
if (d < dmin)
|
||||||
{
|
{
|
||||||
start = i;
|
start = i;
|
||||||
|
@ -796,8 +679,8 @@ namespace DotRecast.Recast
|
||||||
int nvleft = hull[nleft] * 3;
|
int nvleft = hull[nleft] * 3;
|
||||||
int cvright = hull[right] * 3;
|
int cvright = hull[right] * 3;
|
||||||
int nvright = hull[nright] * 3;
|
int nvright = hull[nright] * 3;
|
||||||
float dleft = Vdist2(verts, cvleft, nvleft) + Vdist2(verts, nvleft, cvright);
|
float dleft = Dist2(verts, cvleft, nvleft) + Dist2(verts, nvleft, cvright);
|
||||||
float dright = Vdist2(verts, cvright, nvright) + Vdist2(verts, cvleft, nvright);
|
float dright = Dist2(verts, cvright, nvright) + Dist2(verts, cvleft, nvright);
|
||||||
|
|
||||||
if (dleft < dright)
|
if (dleft < dright)
|
||||||
{
|
{
|
||||||
|
@ -818,33 +701,37 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float GetJitterX(int i)
|
public static float GetJitterX(int i)
|
||||||
{
|
{
|
||||||
return (((i * 0x8da6b343) & 0xffff) / 65535.0f * 2.0f) - 1.0f;
|
return (((i * 0x8da6b343) & 0xffff) / 65535.0f * 2.0f) - 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float GetJitterY(int i)
|
public static float GetJitterY(int i)
|
||||||
{
|
{
|
||||||
return (((i * 0xd8163841) & 0xffff) / 65535.0f * 2.0f) - 1.0f;
|
return (((i * 0xd8163841) & 0xffff) / 65535.0f * 2.0f) - 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int BuildPolyDetail(RcContext ctx, float[] @in, int nin, float sampleDist, float sampleMaxError,
|
public static int BuildPolyDetail(RcContext ctx, float[] @in, int nin,
|
||||||
int heightSearchRadius, RcCompactHeightfield chf, RcHeightPatch hp, float[] verts, List<int> tris)
|
float sampleDist, float sampleMaxError,
|
||||||
|
int heightSearchRadius, RcCompactHeightfield chf,
|
||||||
|
RcHeightPatch hp, float[] verts,
|
||||||
|
ref List<int> tris, ref List<int> edges, ref List<int> samples)
|
||||||
{
|
{
|
||||||
List<int> samples = new List<int>(512);
|
const int MAX_VERTS = 127;
|
||||||
|
const int MAX_TRIS = 255; // Max tris for delaunay is 2n-2-k (n=num verts, k=num hull verts).
|
||||||
int nverts = 0;
|
const int MAX_VERTS_PER_EDGE = 32;
|
||||||
float[] edge = new float[(MAX_VERTS_PER_EDGE + 1) * 3];
|
float[] edge = new float[(MAX_VERTS_PER_EDGE + 1) * 3];
|
||||||
int[] hull = new int[MAX_VERTS];
|
int[] hull = new int[MAX_VERTS];
|
||||||
int nhull = 0;
|
int nhull = 0;
|
||||||
|
|
||||||
nverts = nin;
|
int nverts = nin;
|
||||||
|
|
||||||
for (int i = 0; i < nin; ++i)
|
for (int i = 0; i < nin; ++i)
|
||||||
{
|
{
|
||||||
RcVecUtils.Copy(verts, i * 3, @in, i * 3);
|
RcVec.Copy(verts, i * 3, @in, i * 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
edges.Clear();
|
||||||
tris.Clear();
|
tris.Clear();
|
||||||
|
|
||||||
float cs = chf.cs;
|
float cs = chf.cs;
|
||||||
|
@ -957,7 +844,7 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
for (int k = nidx - 2; k > 0; --k)
|
for (int k = nidx - 2; k > 0; --k)
|
||||||
{
|
{
|
||||||
RcVecUtils.Copy(verts, nverts * 3, edge, idx[k] * 3);
|
RcVec.Copy(verts, nverts * 3, edge, idx[k] * 3);
|
||||||
hull[nhull++] = nverts;
|
hull[nhull++] = nverts;
|
||||||
nverts++;
|
nverts++;
|
||||||
}
|
}
|
||||||
|
@ -966,7 +853,7 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
for (int k = 1; k < nidx - 1; ++k)
|
for (int k = 1; k < nidx - 1; ++k)
|
||||||
{
|
{
|
||||||
RcVecUtils.Copy(verts, nverts * 3, edge, idx[k] * 3);
|
RcVec.Copy(verts, nverts * 3, edge, idx[k] * 3);
|
||||||
hull[nhull++] = nverts;
|
hull[nhull++] = nverts;
|
||||||
nverts++;
|
nverts++;
|
||||||
}
|
}
|
||||||
|
@ -997,12 +884,12 @@ namespace DotRecast.Recast
|
||||||
if (sampleDist > 0)
|
if (sampleDist > 0)
|
||||||
{
|
{
|
||||||
// Create sample locations in a grid.
|
// Create sample locations in a grid.
|
||||||
RcVec3f bmin = RcVecUtils.Create(@in);
|
RcVec3f bmin = new RcVec3f(@in);
|
||||||
RcVec3f bmax = RcVecUtils.Create(@in);
|
RcVec3f bmax = new RcVec3f(@in);
|
||||||
for (int i = 1; i < nin; ++i)
|
for (int i = 1; i < nin; ++i)
|
||||||
{
|
{
|
||||||
bmin = RcVecUtils.Min(bmin, @in, i * 3);
|
bmin = RcVec3f.Min(bmin, RcVec.Create(@in, i * 3));
|
||||||
bmax = RcVecUtils.Max(bmax, @in, i * 3);
|
bmax = RcVec3f.Max(bmax, RcVec.Create(@in, i * 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
int x0 = (int)MathF.Floor(bmin.X / sampleDist);
|
int x0 = (int)MathF.Floor(bmin.X / sampleDist);
|
||||||
|
@ -1105,7 +992,7 @@ namespace DotRecast.Recast
|
||||||
return nverts;
|
return nverts;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool OnHull(int a, int b, int nhull, int[] hull)
|
public static bool OnHull(int a, int b, int nhull, int[] hull)
|
||||||
{
|
{
|
||||||
// All internal sampled points come after the hull so we can early out for those.
|
// All internal sampled points come after the hull so we can early out for those.
|
||||||
if (a >= nhull || b >= nhull)
|
if (a >= nhull || b >= nhull)
|
||||||
|
@ -1121,7 +1008,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find edges that lie on hull and mark them as such.
|
// Find edges that lie on hull and mark them as such.
|
||||||
static void SetTriFlags(List<int> tris, int nhull, int[] hull)
|
public static void SetTriFlags(List<int> tris, int nhull, int[] hull)
|
||||||
{
|
{
|
||||||
// Matches DT_DETAIL_EDGE_BOUNDARY
|
// Matches DT_DETAIL_EDGE_BOUNDARY
|
||||||
const int DETAIL_EDGE_BOUNDARY = 0x1;
|
const int DETAIL_EDGE_BOUNDARY = 0x1;
|
||||||
|
@ -1140,7 +1027,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void SeedArrayWithPolyCenter(RcContext ctx, RcCompactHeightfield chf, int[] meshpoly, int poly, int npoly,
|
public static void SeedArrayWithPolyCenter(RcContext ctx, RcCompactHeightfield chf, int[] meshpoly, int poly, int npoly,
|
||||||
int[] verts, int bs, RcHeightPatch hp, List<int> array)
|
int[] verts, int bs, RcHeightPatch hp, List<int> array)
|
||||||
{
|
{
|
||||||
// Note: Reads to the compact heightfield are offset by border size (bs)
|
// Note: Reads to the compact heightfield are offset by border size (bs)
|
||||||
|
@ -1289,22 +1176,25 @@ namespace DotRecast.Recast
|
||||||
hp.data[cx - hp.xmin + (cy - hp.ymin) * hp.width] = cs2.y;
|
hp.data[cx - hp.xmin + (cy - hp.ymin) * hp.width] = cs2.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int RETRACT_SIZE = 256;
|
|
||||||
|
|
||||||
static void Push3(List<int> queue, int v1, int v2, int v3)
|
public static void Push3(List<int> queue, int v1, int v2, int v3)
|
||||||
{
|
{
|
||||||
queue.Add(v1);
|
queue.Add(v1);
|
||||||
queue.Add(v2);
|
queue.Add(v2);
|
||||||
queue.Add(v3);
|
queue.Add(v3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GetHeightData(RcContext ctx, RcCompactHeightfield chf, int[] meshpolys, int poly, int npoly, int[] verts,
|
public static void GetHeightData(RcContext ctx, RcCompactHeightfield chf,
|
||||||
int bs, RcHeightPatch hp, int region)
|
int[] meshpolys, int poly, int npoly,
|
||||||
|
int[] verts, int bs,
|
||||||
|
ref RcHeightPatch hp, ref List<int> queue,
|
||||||
|
int region)
|
||||||
{
|
{
|
||||||
// Note: Reads to the compact heightfield are offset by border size (bs)
|
// Note: Reads to the compact heightfield are offset by border size (bs)
|
||||||
// since border size offset is already removed from the polymesh vertices.
|
// since border size offset is already removed from the polymesh vertices.
|
||||||
|
|
||||||
List<int> queue = new List<int>(512);
|
queue.Clear();
|
||||||
|
// Set all heights to RC_UNSET_HEIGHT.
|
||||||
Array.Fill(hp.data, RC_UNSET_HEIGHT, 0, (hp.width * hp.height) - (0));
|
Array.Fill(hp.data, RC_UNSET_HEIGHT, 0, (hp.width * hp.height) - (0));
|
||||||
|
|
||||||
bool empty = true;
|
bool empty = true;
|
||||||
|
@ -1370,6 +1260,7 @@ namespace DotRecast.Recast
|
||||||
SeedArrayWithPolyCenter(ctx, chf, meshpolys, poly, npoly, verts, bs, hp, queue);
|
SeedArrayWithPolyCenter(ctx, chf, meshpolys, poly, npoly, verts, bs, hp, queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int RETRACT_SIZE = 256;
|
||||||
int head = 0;
|
int head = 0;
|
||||||
|
|
||||||
// We assume the seed is centered in the polygon, so a BFS to collect
|
// We assume the seed is centered in the polygon, so a BFS to collect
|
||||||
|
@ -1441,7 +1332,10 @@ namespace DotRecast.Recast
|
||||||
int borderSize = mesh.borderSize;
|
int borderSize = mesh.borderSize;
|
||||||
int heightSearchRadius = (int)Math.Max(1, MathF.Ceiling(mesh.maxEdgeError));
|
int heightSearchRadius = (int)Math.Max(1, MathF.Ceiling(mesh.maxEdgeError));
|
||||||
|
|
||||||
|
List<int> edges = new List<int>(64);
|
||||||
List<int> tris = new List<int>(512);
|
List<int> tris = new List<int>(512);
|
||||||
|
List<int> arr = new List<int>(512);
|
||||||
|
List<int> samples = new List<int>(512);
|
||||||
float[] verts = new float[256 * 3];
|
float[] verts = new float[256 * 3];
|
||||||
RcHeightPatch hp = new RcHeightPatch();
|
RcHeightPatch hp = new RcHeightPatch();
|
||||||
int nPolyVerts = 0;
|
int nPolyVerts = 0;
|
||||||
|
@ -1526,18 +1420,20 @@ namespace DotRecast.Recast
|
||||||
hp.ymin = bounds[i * 4 + 2];
|
hp.ymin = bounds[i * 4 + 2];
|
||||||
hp.width = bounds[i * 4 + 1] - bounds[i * 4 + 0];
|
hp.width = bounds[i * 4 + 1] - bounds[i * 4 + 0];
|
||||||
hp.height = bounds[i * 4 + 3] - bounds[i * 4 + 2];
|
hp.height = bounds[i * 4 + 3] - bounds[i * 4 + 2];
|
||||||
GetHeightData(ctx, chf, mesh.polys, p, npoly, mesh.verts, borderSize, hp, mesh.regs[i]);
|
GetHeightData(ctx, chf, mesh.polys, p, npoly, mesh.verts, borderSize, ref hp, ref arr, mesh.regs[i]);
|
||||||
|
|
||||||
// Build detail mesh.
|
// Build detail mesh.
|
||||||
int nverts = BuildPolyDetail(ctx, poly, npoly, sampleDist, sampleMaxError, heightSearchRadius, chf, hp,
|
int nverts = BuildPolyDetail(ctx, poly, npoly,
|
||||||
verts, tris);
|
sampleDist, sampleMaxError,
|
||||||
|
heightSearchRadius, chf, hp,
|
||||||
|
verts, ref tris,
|
||||||
|
ref edges, ref samples);
|
||||||
|
|
||||||
// Move detail verts to world space.
|
// Move detail verts to world space.
|
||||||
for (int j = 0; j < nverts; ++j)
|
for (int j = 0; j < nverts; ++j)
|
||||||
{
|
{
|
||||||
verts[j * 3 + 0] += orig.X;
|
verts[j * 3 + 0] += orig.X;
|
||||||
verts[j * 3 + 1] += orig.Y + chf.ch; // Is this offset necessary? See
|
verts[j * 3 + 1] += orig.Y + chf.ch; // Is this offset necessary? See
|
||||||
// https://groups.google.com/d/msg/recastnavigation/UQFN6BGCcV0/-1Ny4koOBpkJ
|
|
||||||
verts[j * 3 + 2] += orig.Z;
|
verts[j * 3 + 2] += orig.Z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1614,7 +1510,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @see rcAllocPolyMeshDetail, rcPolyMeshDetail
|
/// @see rcAllocPolyMeshDetail, rcPolyMeshDetail
|
||||||
private static RcPolyMeshDetail MergePolyMeshDetails(RcContext ctx, RcPolyMeshDetail[] meshes, int nmeshes)
|
public static RcPolyMeshDetail MergePolyMeshDetails(RcContext ctx, RcPolyMeshDetail[] meshes, int nmeshes)
|
||||||
{
|
{
|
||||||
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_MERGE_POLYMESHDETAIL);
|
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_MERGE_POLYMESHDETAIL);
|
||||||
|
|
||||||
|
@ -1665,7 +1561,7 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
for (int k = 0; k < dm.nverts; ++k)
|
for (int k = 0; k < dm.nverts; ++k)
|
||||||
{
|
{
|
||||||
RcVecUtils.Copy(mesh.verts, mesh.nverts * 3, dm.verts, k * 3);
|
RcVec.Copy(mesh.verts, mesh.nverts * 3, dm.verts, k * 3);
|
||||||
mesh.nverts++;
|
mesh.nverts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -24,7 +24,7 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcConstants;
|
using static RcRecast;
|
||||||
|
|
||||||
public static class RcMeshs
|
public static class RcMeshs
|
||||||
{
|
{
|
||||||
|
@ -715,8 +715,13 @@ namespace DotRecast.Recast
|
||||||
int nv = CountPolyVerts(mesh.polys, p, nvp);
|
int nv = CountPolyVerts(mesh.polys, p, nvp);
|
||||||
bool hasRem = false;
|
bool hasRem = false;
|
||||||
for (int j = 0; j < nv; ++j)
|
for (int j = 0; j < nv; ++j)
|
||||||
|
{
|
||||||
if (mesh.polys[p + j] == rem)
|
if (mesh.polys[p + j] == rem)
|
||||||
|
{
|
||||||
hasRem = true;
|
hasRem = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (hasRem)
|
if (hasRem)
|
||||||
{
|
{
|
||||||
// Collect edges which does not touch the removed vertex.
|
// Collect edges which does not touch the removed vertex.
|
||||||
|
@ -956,7 +961,7 @@ namespace DotRecast.Recast
|
||||||
mesh.npolys++;
|
mesh.npolys++;
|
||||||
if (mesh.npolys > maxTris)
|
if (mesh.npolys > maxTris)
|
||||||
{
|
{
|
||||||
throw new Exception("removeVertex: Too many polygons " + mesh.npolys + " (max:" + maxTris + ".");
|
throw new Exception($"removeVertex: Too many polygons {mesh.npolys} max:({maxTris}).");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1033,11 +1038,23 @@ namespace DotRecast.Recast
|
||||||
// Triangulate contour
|
// Triangulate contour
|
||||||
for (int j = 0; j < cont.nverts; ++j)
|
for (int j = 0; j < cont.nverts; ++j)
|
||||||
indices[j] = j;
|
indices[j] = j;
|
||||||
|
|
||||||
int ntris = Triangulate(cont.nverts, cont.verts, indices, tris);
|
int ntris = Triangulate(cont.nverts, cont.verts, indices, tris);
|
||||||
if (ntris <= 0)
|
if (ntris <= 0)
|
||||||
{
|
{
|
||||||
// Bad triangulation, should not happen.
|
// Bad triangulation, should not happen.
|
||||||
ctx.Warn("buildPolyMesh: Bad triangulation Contour " + i + ".");
|
/*
|
||||||
|
printf("\tconst float bmin[3] = {%ff,%ff,%ff};\n", cset.bmin[0], cset.bmin[1], cset.bmin[2]);
|
||||||
|
printf("\tconst float cs = %ff;\n", cset.cs);
|
||||||
|
printf("\tconst float ch = %ff;\n", cset.ch);
|
||||||
|
printf("\tconst int verts[] = {\n");
|
||||||
|
for (int k = 0; k < cont.nverts; ++k)
|
||||||
|
{
|
||||||
|
const int* v = &cont.verts[k*4];
|
||||||
|
printf("\t\t%d,%d,%d,%d,\n", v[0], v[1], v[2], v[3]);
|
||||||
|
}
|
||||||
|
printf("\t};\n\tconst int nverts = sizeof(verts)/(sizeof(int)*4);\n");*/
|
||||||
|
ctx.Warn($"BuildPolyMesh: Bad triangulation Contour {i}.");
|
||||||
ntris = -ntris;
|
ntris = -ntris;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1198,14 +1215,12 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
if (mesh.nverts > MAX_MESH_VERTS_POLY)
|
if (mesh.nverts > MAX_MESH_VERTS_POLY)
|
||||||
{
|
{
|
||||||
throw new Exception("rcBuildPolyMesh: The resulting mesh has too many vertices " + mesh.nverts
|
throw new Exception($"BuildPolyMesh: The resulting mesh has too many vertices {mesh.nverts} (max {MAX_MESH_VERTS_POLY}). Data can be corrupted.");
|
||||||
+ " (max " + MAX_MESH_VERTS_POLY + "). Data can be corrupted.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mesh.npolys > MAX_MESH_VERTS_POLY)
|
if (mesh.npolys > MAX_MESH_VERTS_POLY)
|
||||||
{
|
{
|
||||||
throw new Exception("rcBuildPolyMesh: The resulting mesh has too many polygons " + mesh.npolys
|
throw new Exception($"BuildPolyMesh: The resulting mesh has too many polygons {mesh.npolys} (max {MAX_MESH_VERTS_POLY}). Data can be corrupted.");
|
||||||
+ " (max " + MAX_MESH_VERTS_POLY + "). Data can be corrupted.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public enum RcPartition
|
public enum RcPartition
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +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
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -17,6 +17,7 @@ freely, subject to the following restrictions:
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
@ -45,6 +46,7 @@ namespace DotRecast.Recast
|
||||||
private static bool Raycast(RcPolyMesh poly, RcPolyMeshDetail meshDetail, RcVec3f sp, RcVec3f sq, out float hitTime)
|
private static bool Raycast(RcPolyMesh poly, RcPolyMeshDetail meshDetail, RcVec3f sp, RcVec3f sq, out float hitTime)
|
||||||
{
|
{
|
||||||
hitTime = 0;
|
hitTime = 0;
|
||||||
|
Span<RcVec3f> tempVs = stackalloc RcVec3f[3];
|
||||||
if (meshDetail != null)
|
if (meshDetail != null)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < meshDetail.nmeshes; ++i)
|
for (int i = 0; i < meshDetail.nmeshes; ++i)
|
||||||
|
@ -57,7 +59,7 @@ namespace DotRecast.Recast
|
||||||
int tris = btris * 4;
|
int tris = btris * 4;
|
||||||
for (int j = 0; j < ntris; ++j)
|
for (int j = 0; j < ntris; ++j)
|
||||||
{
|
{
|
||||||
RcVec3f[] vs = new RcVec3f[3];
|
Span<RcVec3f> vs = tempVs;
|
||||||
for (int k = 0; k < 3; ++k)
|
for (int k = 0; k < 3; ++k)
|
||||||
{
|
{
|
||||||
vs[k].X = meshDetail.verts[verts + meshDetail.tris[tris + j * 4 + k] * 3];
|
vs[k].X = meshDetail.verts[verts + meshDetail.tris[tris + j * 4 + k] * 3];
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -21,10 +21,12 @@ freely, subject to the following restrictions:
|
||||||
using System;
|
using System;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using static DotRecast.Recast.RcConstants;
|
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
|
using static RcRecast;
|
||||||
|
|
||||||
public static class RcRasterizations
|
public static class RcRasterizations
|
||||||
{
|
{
|
||||||
/// Check whether two bounding boxes overlap
|
/// Check whether two bounding boxes overlap
|
||||||
|
@ -207,7 +209,7 @@ namespace DotRecast.Recast
|
||||||
/// @param[out] outVerts2Count The number of resulting polygon 2 vertices
|
/// @param[out] outVerts2Count The number of resulting polygon 2 vertices
|
||||||
/// @param[in] axisOffset THe offset along the specified axis
|
/// @param[in] axisOffset THe offset along the specified axis
|
||||||
/// @param[in] axis The separating axis
|
/// @param[in] axis The separating axis
|
||||||
private static void DividePoly(float[] inVerts, int inVertsOffset, int inVertsCount,
|
private static void DividePoly(Span<float> inVerts, int inVertsOffset, int inVertsCount,
|
||||||
int outVerts1, out int outVerts1Count,
|
int outVerts1, out int outVerts1Count,
|
||||||
int outVerts2, out int outVerts2Count,
|
int outVerts2, out int outVerts2Count,
|
||||||
float axisOffset, int axis)
|
float axisOffset, int axis)
|
||||||
|
@ -231,7 +233,7 @@ namespace DotRecast.Recast
|
||||||
inVerts[outVerts1 + poly1Vert * 3 + 0] = inVerts[inVertsOffset + inVertB * 3 + 0] + (inVerts[inVertsOffset + inVertA * 3 + 0] - inVerts[inVertsOffset + inVertB * 3 + 0]) * s;
|
inVerts[outVerts1 + poly1Vert * 3 + 0] = inVerts[inVertsOffset + inVertB * 3 + 0] + (inVerts[inVertsOffset + inVertA * 3 + 0] - inVerts[inVertsOffset + inVertB * 3 + 0]) * s;
|
||||||
inVerts[outVerts1 + poly1Vert * 3 + 1] = inVerts[inVertsOffset + inVertB * 3 + 1] + (inVerts[inVertsOffset + inVertA * 3 + 1] - inVerts[inVertsOffset + inVertB * 3 + 1]) * s;
|
inVerts[outVerts1 + poly1Vert * 3 + 1] = inVerts[inVertsOffset + inVertB * 3 + 1] + (inVerts[inVertsOffset + inVertA * 3 + 1] - inVerts[inVertsOffset + inVertB * 3 + 1]) * s;
|
||||||
inVerts[outVerts1 + poly1Vert * 3 + 2] = inVerts[inVertsOffset + inVertB * 3 + 2] + (inVerts[inVertsOffset + inVertA * 3 + 2] - inVerts[inVertsOffset + inVertB * 3 + 2]) * s;
|
inVerts[outVerts1 + poly1Vert * 3 + 2] = inVerts[inVertsOffset + inVertB * 3 + 2] + (inVerts[inVertsOffset + inVertA * 3 + 2] - inVerts[inVertsOffset + inVertB * 3 + 2]) * s;
|
||||||
RcVecUtils.Copy(inVerts, outVerts2 + poly2Vert * 3, inVerts, outVerts1 + poly1Vert * 3);
|
RcVec.Copy(inVerts, outVerts2 + poly2Vert * 3, inVerts, outVerts1 + poly1Vert * 3);
|
||||||
poly1Vert++;
|
poly1Vert++;
|
||||||
poly2Vert++;
|
poly2Vert++;
|
||||||
|
|
||||||
|
@ -239,12 +241,12 @@ namespace DotRecast.Recast
|
||||||
// since these were already added above
|
// since these were already added above
|
||||||
if (inVertAxisDelta[inVertA] > 0)
|
if (inVertAxisDelta[inVertA] > 0)
|
||||||
{
|
{
|
||||||
RcVecUtils.Copy(inVerts, outVerts1 + poly1Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
RcVec.Copy(inVerts, outVerts1 + poly1Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
||||||
poly1Vert++;
|
poly1Vert++;
|
||||||
}
|
}
|
||||||
else if (inVertAxisDelta[inVertA] < 0)
|
else if (inVertAxisDelta[inVertA] < 0)
|
||||||
{
|
{
|
||||||
RcVecUtils.Copy(inVerts, outVerts2 + poly2Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
RcVec.Copy(inVerts, outVerts2 + poly2Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
||||||
poly2Vert++;
|
poly2Vert++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,7 +255,7 @@ namespace DotRecast.Recast
|
||||||
// add the i'th point to the right polygon. Addition is done even for points on the dividing line
|
// add the i'th point to the right polygon. Addition is done even for points on the dividing line
|
||||||
if (inVertAxisDelta[inVertA] >= 0)
|
if (inVertAxisDelta[inVertA] >= 0)
|
||||||
{
|
{
|
||||||
RcVecUtils.Copy(inVerts, outVerts1 + poly1Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
RcVec.Copy(inVerts, outVerts1 + poly1Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
||||||
poly1Vert++;
|
poly1Vert++;
|
||||||
if (inVertAxisDelta[inVertA] != 0)
|
if (inVertAxisDelta[inVertA] != 0)
|
||||||
{
|
{
|
||||||
|
@ -261,7 +263,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RcVecUtils.Copy(inVerts, outVerts2 + poly2Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
RcVec.Copy(inVerts, outVerts2 + poly2Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
||||||
poly2Vert++;
|
poly2Vert++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,13 +295,13 @@ namespace DotRecast.Recast
|
||||||
int flagMergeThreshold)
|
int flagMergeThreshold)
|
||||||
{
|
{
|
||||||
// Calculate the bounding box of the triangle.
|
// Calculate the bounding box of the triangle.
|
||||||
RcVec3f triBBMin = RcVecUtils.Create(verts, v0 * 3);
|
RcVec3f triBBMin = RcVec.Create(verts, v0 * 3);
|
||||||
triBBMin = RcVecUtils.Min(triBBMin, verts, v1 * 3);
|
triBBMin = RcVec3f.Min(triBBMin, RcVec.Create(verts, v1 * 3));
|
||||||
triBBMin = RcVecUtils.Min(triBBMin, verts, v2 * 3);
|
triBBMin = RcVec3f.Min(triBBMin, RcVec.Create(verts, v2 * 3));
|
||||||
|
|
||||||
RcVec3f triBBMax = RcVecUtils.Create(verts, v0 * 3);
|
RcVec3f triBBMax = RcVec.Create(verts, v0 * 3);
|
||||||
triBBMax = RcVecUtils.Max(triBBMax, verts, v1 * 3);
|
triBBMax = RcVec3f.Max(triBBMax, RcVec.Create(verts, v1 * 3));
|
||||||
triBBMax = RcVecUtils.Max(triBBMax, verts, v2 * 3);
|
triBBMax = RcVec3f.Max(triBBMax, RcVec.Create(verts, v2 * 3));
|
||||||
|
|
||||||
// If the triangle does not touch the bounding box of the heightfield, skip the triangle.
|
// If the triangle does not touch the bounding box of the heightfield, skip the triangle.
|
||||||
if (!OverlapBounds(triBBMin, triBBMax, heightfieldBBMin, heightfieldBBMax))
|
if (!OverlapBounds(triBBMin, triBBMax, heightfieldBBMin, heightfieldBBMax))
|
||||||
|
@ -320,15 +322,15 @@ namespace DotRecast.Recast
|
||||||
z1 = Math.Clamp(z1, 0, h - 1);
|
z1 = Math.Clamp(z1, 0, h - 1);
|
||||||
|
|
||||||
// Clip the triangle into all grid cells it touches.
|
// Clip the triangle into all grid cells it touches.
|
||||||
float[] buf = new float[7 * 3 * 4];
|
Span<float> buf = stackalloc float[7 * 3 * 4];
|
||||||
int @in = 0;
|
int @in = 0;
|
||||||
int inRow = 7 * 3;
|
int inRow = 7 * 3;
|
||||||
int p1 = inRow + 7 * 3;
|
int p1 = inRow + 7 * 3;
|
||||||
int p2 = p1 + 7 * 3;
|
int p2 = p1 + 7 * 3;
|
||||||
|
|
||||||
RcVecUtils.Copy(buf, 0, verts, v0 * 3);
|
RcVec.Copy(buf, 0, verts, v0 * 3);
|
||||||
RcVecUtils.Copy(buf, 3, verts, v1 * 3);
|
RcVec.Copy(buf, 3, verts, v1 * 3);
|
||||||
RcVecUtils.Copy(buf, 6, verts, v2 * 3);
|
RcVec.Copy(buf, 6, verts, v2 * 3);
|
||||||
int nvRow;
|
int nvRow;
|
||||||
int nvIn = 3;
|
int nvIn = 3;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -24,10 +24,81 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcConstants;
|
public static class RcRecast
|
||||||
|
|
||||||
public static class RcCommons
|
|
||||||
{
|
{
|
||||||
|
/// Represents the null area.
|
||||||
|
/// When a data element is given this value it is considered to no longer be
|
||||||
|
/// assigned to a usable area. (E.g. It is un-walkable.)
|
||||||
|
public const int RC_NULL_AREA = 0;
|
||||||
|
|
||||||
|
/// The default area id used to indicate a walkable polygon.
|
||||||
|
/// This is also the maximum allowed area id, and the only non-null area id
|
||||||
|
/// recognized by some steps in the build process.
|
||||||
|
public const int RC_WALKABLE_AREA = 63;
|
||||||
|
|
||||||
|
/// The value returned by #rcGetCon if the specified direction is not connected
|
||||||
|
/// to another span. (Has no neighbor.)
|
||||||
|
public const int RC_NOT_CONNECTED = 0x3f;
|
||||||
|
|
||||||
|
/// Defines the number of bits allocated to rcSpan::smin and rcSpan::smax.
|
||||||
|
public const int RC_SPAN_HEIGHT_BITS = 20;
|
||||||
|
|
||||||
|
/// Defines the maximum value for rcSpan::smin and rcSpan::smax.
|
||||||
|
public const int RC_SPAN_MAX_HEIGHT = (1 << RC_SPAN_HEIGHT_BITS) - 1;
|
||||||
|
|
||||||
|
/// The number of spans allocated per span spool.
|
||||||
|
/// @see rcSpanPool
|
||||||
|
public const int RC_SPANS_PER_POOL = 2048;
|
||||||
|
|
||||||
|
// Must be 255 or smaller (not 256) because layer IDs are stored as
|
||||||
|
// a byte where 255 is a special value.
|
||||||
|
public const int RC_MAX_LAYERS = RC_NOT_CONNECTED;
|
||||||
|
public const int RC_MAX_NEIS = 16;
|
||||||
|
|
||||||
|
/// Heighfield border flag.
|
||||||
|
/// If a heightfield region ID has this bit set, then the region is a border
|
||||||
|
/// region and its spans are considered unwalkable.
|
||||||
|
/// (Used during the region and contour build process.)
|
||||||
|
/// @see rcCompactSpan::reg
|
||||||
|
public const int RC_BORDER_REG = 0x8000;
|
||||||
|
|
||||||
|
/// Polygon touches multiple regions.
|
||||||
|
/// If a polygon has this region ID it was merged with or created
|
||||||
|
/// from polygons of different regions during the polymesh
|
||||||
|
/// build step that removes redundant border vertices.
|
||||||
|
/// (Used during the polymesh and detail polymesh build processes)
|
||||||
|
/// @see rcPolyMesh::regs
|
||||||
|
public const int RC_MULTIPLE_REGS = 0;
|
||||||
|
|
||||||
|
// Border vertex flag.
|
||||||
|
/// If a region ID has this bit set, then the associated element lies on
|
||||||
|
/// a tile border. If a contour vertex's region ID has this bit set, the
|
||||||
|
/// vertex will later be removed in order to match the segments and vertices
|
||||||
|
/// at tile boundaries.
|
||||||
|
/// (Used during the build process.)
|
||||||
|
/// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts
|
||||||
|
public const int RC_BORDER_VERTEX = 0x10000;
|
||||||
|
|
||||||
|
/// Area border flag.
|
||||||
|
/// If a region ID has this bit set, then the associated element lies on
|
||||||
|
/// the border of an area.
|
||||||
|
/// (Used during the region and contour build process.)
|
||||||
|
/// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts
|
||||||
|
public const int RC_AREA_BORDER = 0x20000;
|
||||||
|
|
||||||
|
/// Applied to the region id field of contour vertices in order to extract the region id.
|
||||||
|
/// The region id field of a vertex may have several flags applied to it. So the
|
||||||
|
/// fields value can't be used directly.
|
||||||
|
/// @see rcContour::verts, rcContour::rverts
|
||||||
|
public const int RC_CONTOUR_REG_MASK = 0xffff;
|
||||||
|
|
||||||
|
/// A value which indicates an invalid index within a mesh.
|
||||||
|
/// @note This does not necessarily indicate an error.
|
||||||
|
/// @see rcPolyMesh::polys
|
||||||
|
public const int RC_MESH_NULL_IDX = 0xffff;
|
||||||
|
|
||||||
|
public const int RC_LOG_WARNING = 1;
|
||||||
|
|
||||||
private static readonly int[] DirOffsetX = { -1, 0, 1, 0, };
|
private static readonly int[] DirOffsetX = { -1, 0, 1, 0, };
|
||||||
private static readonly int[] DirOffsetY = { 0, 1, 0, -1 };
|
private static readonly int[] DirOffsetY = { 0, 1, 0, -1 };
|
||||||
private static readonly int[] DirForOffset = { 3, 0, -1, 2, 1 };
|
private static readonly int[] DirForOffset = { 3, 0, -1, 2, 1 };
|
||||||
|
@ -127,7 +198,10 @@ namespace DotRecast.Recast
|
||||||
for (int i = 0; i < nt; ++i)
|
for (int i = 0; i < nt; ++i)
|
||||||
{
|
{
|
||||||
int tri = i * 3;
|
int tri = i * 3;
|
||||||
CalcTriNormal(verts, tris[tri], tris[tri + 1], tris[tri + 2], ref norm);
|
RcVec3f v0 = RcVec.Create(verts, tris[tri + 0] * 3);
|
||||||
|
RcVec3f v1 = RcVec.Create(verts, tris[tri + 1] * 3);
|
||||||
|
RcVec3f v2 = RcVec.Create(verts, tris[tri + 2] * 3);
|
||||||
|
CalcTriNormal(v0, v1, v2, ref norm);
|
||||||
// Check if the face is walkable.
|
// Check if the face is walkable.
|
||||||
if (norm.Y > walkableThr)
|
if (norm.Y > walkableThr)
|
||||||
areas[i] = areaMod.Apply(areas[i]);
|
areas[i] = areaMod.Apply(areas[i]);
|
||||||
|
@ -136,10 +210,10 @@ namespace DotRecast.Recast
|
||||||
return areas;
|
return areas;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CalcTriNormal(float[] verts, int v0, int v1, int v2, ref RcVec3f norm)
|
public static void CalcTriNormal(RcVec3f v0, RcVec3f v1, RcVec3f v2, ref RcVec3f norm)
|
||||||
{
|
{
|
||||||
var e0 = RcVecUtils.Subtract(verts, v1 * 3, v0 * 3);
|
var e0 = v1 - v0;
|
||||||
var e1 = RcVecUtils.Subtract(verts, v2 * 3, v0 * 3);
|
var e1 = v2 - v0;
|
||||||
norm = RcVec3f.Cross(e0, e1);
|
norm = RcVec3f.Cross(e0, e1);
|
||||||
norm = RcVec3f.Normalize(norm);
|
norm = RcVec3f.Normalize(norm);
|
||||||
}
|
}
|
||||||
|
@ -162,7 +236,10 @@ namespace DotRecast.Recast
|
||||||
for (int i = 0; i < nt; ++i)
|
for (int i = 0; i < nt; ++i)
|
||||||
{
|
{
|
||||||
int tri = i * 3;
|
int tri = i * 3;
|
||||||
CalcTriNormal(verts, tris[tri], tris[tri + 1], tris[tri + 2], ref norm);
|
RcVec3f v0 = RcVec.Create(verts, tris[tri + 0] * 3);
|
||||||
|
RcVec3f v1 = RcVec.Create(verts, tris[tri + 1] * 3);
|
||||||
|
RcVec3f v2 = RcVec.Create(verts, tris[tri + 2] * 3);
|
||||||
|
CalcTriNormal(v0, v1, v2, ref norm);
|
||||||
// Check if the face is walkable.
|
// Check if the face is walkable.
|
||||||
if (norm.Y <= walkableThr)
|
if (norm.Y <= walkableThr)
|
||||||
areas[i] = RC_NULL_AREA;
|
areas[i] = RC_NULL_AREA;
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -25,8 +25,8 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcConstants;
|
|
||||||
using static RcCommons;
|
using static RcRecast;
|
||||||
|
|
||||||
public static class RcRegions
|
public static class RcRegions
|
||||||
{
|
{
|
||||||
|
@ -1665,8 +1665,8 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_WATERSHED);
|
ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_WATERSHED);
|
||||||
|
|
||||||
int LOG_NB_STACKS = 3;
|
const int LOG_NB_STACKS = 3;
|
||||||
int NB_STACKS = 1 << LOG_NB_STACKS;
|
const int NB_STACKS = 1 << LOG_NB_STACKS;
|
||||||
List<List<RcLevelStackEntry>> lvlStacks = new List<List<RcLevelStackEntry>>();
|
List<List<RcLevelStackEntry>> lvlStacks = new List<List<RcLevelStackEntry>>();
|
||||||
for (int i = 0; i < NB_STACKS; ++i)
|
for (int i = 0; i < NB_STACKS; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -20,19 +20,13 @@ freely, subject to the following restrictions:
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
/** Represents a span in a heightfield. */
|
/// Represents a span in a heightfield.
|
||||||
|
/// @see rcHeightfield
|
||||||
public class RcSpan
|
public class RcSpan
|
||||||
{
|
{
|
||||||
/** The lower limit of the span. [Limit: < smax] */
|
public int smin; //< The lower limit of the span. [Limit: < #smax]
|
||||||
public int smin;
|
public int smax; //< The upper limit of the span. [Limit: <= #RC_SPAN_MAX_HEIGHT]
|
||||||
|
public int area; //< The area id assigned to the span.
|
||||||
/** The upper limit of the span. [Limit: <= SPAN_MAX_HEIGHT] */
|
public RcSpan next; //< The next span higher up in column.
|
||||||
public int smax;
|
|
||||||
|
|
||||||
/** The area id assigned to the span. */
|
|
||||||
public int area;
|
|
||||||
|
|
||||||
/** The next span higher up in column. */
|
|
||||||
public RcSpan next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -28,7 +28,7 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
public RcSpanPool()
|
public RcSpanPool()
|
||||||
{
|
{
|
||||||
items = new RcSpan[RcConstants.RC_SPANS_PER_POOL];
|
items = new RcSpan[RcRecast.RC_SPANS_PER_POOL];
|
||||||
for (int i = 0; i < items.Length; ++i)
|
for (int i = 0; i < items.Length; ++i)
|
||||||
{
|
{
|
||||||
items[i] = new RcSpan();
|
items[i] = new RcSpan();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public class RcSweepSpan
|
public class RcSweepSpan
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -19,6 +19,7 @@ freely, subject to the following restrictions:
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
|
using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Recast.Geom;
|
using DotRecast.Recast.Geom;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
|
@ -44,18 +45,18 @@ namespace DotRecast.Recast
|
||||||
float[] verts = geom.GetVerts();
|
float[] verts = geom.GetVerts();
|
||||||
if (cfg.UseTiles)
|
if (cfg.UseTiles)
|
||||||
{
|
{
|
||||||
float[] tbmin = new float[2];
|
RcVec2f tbmin;
|
||||||
float[] tbmax = new float[2];
|
RcVec2f tbmax;
|
||||||
tbmin[0] = builderCfg.bmin.X;
|
tbmin.X = builderCfg.bmin.X;
|
||||||
tbmin[1] = builderCfg.bmin.Z;
|
tbmin.Y = builderCfg.bmin.Z;
|
||||||
tbmax[0] = builderCfg.bmax.X;
|
tbmax.X = builderCfg.bmax.X;
|
||||||
tbmax[1] = builderCfg.bmax.Z;
|
tbmax.Y = builderCfg.bmax.Z;
|
||||||
List<RcChunkyTriMeshNode> nodes = geom.GetChunksOverlappingRect(tbmin, tbmax);
|
List<RcChunkyTriMeshNode> nodes = geom.GetChunksOverlappingRect(tbmin, tbmax);
|
||||||
foreach (RcChunkyTriMeshNode node in nodes)
|
foreach (RcChunkyTriMeshNode node in nodes)
|
||||||
{
|
{
|
||||||
int[] tris = node.tris;
|
int[] tris = node.tris;
|
||||||
int ntris = tris.Length / 3;
|
int ntris = tris.Length / 3;
|
||||||
int[] m_triareas = RcCommons.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
|
int[] m_triareas = RcRecast.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
|
||||||
RcRasterizations.RasterizeTriangles(ctx, verts, tris, m_triareas, ntris, solid, cfg.WalkableClimb);
|
RcRasterizations.RasterizeTriangles(ctx, verts, tris, m_triareas, ntris, solid, cfg.WalkableClimb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +64,7 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
int[] tris = geom.GetTris();
|
int[] tris = geom.GetTris();
|
||||||
int ntris = tris.Length / 3;
|
int ntris = tris.Length / 3;
|
||||||
int[] m_triareas = RcCommons.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
|
int[] m_triareas = RcRecast.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
|
||||||
RcRasterizations.RasterizeTriangles(ctx, verts, tris, m_triareas, ntris, solid, cfg.WalkableClimb);
|
RcRasterizations.RasterizeTriangles(ctx, verts, tris, m_triareas, ntris, solid, cfg.WalkableClimb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Linq;
|
||||||
|
using BenchmarkDotNet.Running;
|
||||||
|
using DotRecast.Benchmark.Benchmarks;
|
||||||
|
|
||||||
|
namespace DotRecast.Benchmark;
|
||||||
|
|
||||||
|
public static class BenchmarkProgram
|
||||||
|
{
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
var runs = ImmutableArray.Create(
|
||||||
|
BenchmarkConverter.TypeToBenchmarks(typeof(VectorBenchmarks)),
|
||||||
|
BenchmarkConverter.TypeToBenchmarks(typeof(PriorityQueueBenchmarks)),
|
||||||
|
BenchmarkConverter.TypeToBenchmarks(typeof(StackallocBenchmarks))
|
||||||
|
);
|
||||||
|
|
||||||
|
var summary = BenchmarkRunner.Run(runs.ToArray());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,278 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using DotRecast.Core.Collections;
|
||||||
|
|
||||||
|
namespace DotRecast.Benchmark.Benchmarks;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
// * Summary *
|
||||||
|
BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3958/23H2/2023Update/SunValley3)
|
||||||
|
AMD Ryzen 5 3600, 1 CPU, 12 logical and 6 physical cores
|
||||||
|
.NET SDK 8.0.101
|
||||||
|
[Host] : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
|
||||||
|
DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX2
|
||||||
|
|
||||||
|
| Method | Count | Mean | Error | StdDev |
|
||||||
|
|------------------------------- |------ |--------------------:|-----------------:|-----------------:|
|
||||||
|
| Enqueue_RcSortedQueue | 10 | 87.49 ns | 0.774 ns | 0.724 ns |
|
||||||
|
| Enqueue_RcBinaryMinHeap | 10 | 185.23 ns | 1.730 ns | 1.533 ns |
|
||||||
|
| Enqueue_PriorityQueue | 10 | 202.95 ns | 1.611 ns | 1.428 ns |
|
||||||
|
| DequeueAll_RcSortedQueue | 10 | 460.97 ns | 2.169 ns | 2.029 ns |
|
||||||
|
| DequeueAll_RcBinaryMinHeap | 10 | 573.17 ns | 2.542 ns | 2.378 ns |
|
||||||
|
| DequeueAll_PriorityQueue | 10 | 500.68 ns | 2.364 ns | 2.212 ns |
|
||||||
|
| EnqueueDequeue_RcSortedQueue | 10 | 525.43 ns | 1.842 ns | 1.632 ns |
|
||||||
|
| EnqueueDequeue_RcBinaryMinHeap | 10 | 455.65 ns | 2.410 ns | 2.254 ns |
|
||||||
|
| EnqueueDequeue_PriorityQueue | 10 | 381.82 ns | 6.036 ns | 5.646 ns |
|
||||||
|
| Enqueue_RcSortedQueue | 100 | 730.57 ns | 5.229 ns | 4.635 ns |
|
||||||
|
| Enqueue_RcBinaryMinHeap | 100 | 3,012.15 ns | 10.875 ns | 9.640 ns |
|
||||||
|
| Enqueue_PriorityQueue | 100 | 2,306.80 ns | 26.694 ns | 23.663 ns |
|
||||||
|
| DequeueAll_RcSortedQueue | 100 | 6,241.67 ns | 31.856 ns | 29.798 ns |
|
||||||
|
| DequeueAll_RcBinaryMinHeap | 100 | 13,692.29 ns | 38.829 ns | 34.421 ns |
|
||||||
|
| DequeueAll_PriorityQueue | 100 | 12,482.93 ns | 93.955 ns | 87.886 ns |
|
||||||
|
| EnqueueDequeue_RcSortedQueue | 100 | 64,002.79 ns | 316.081 ns | 280.197 ns |
|
||||||
|
| EnqueueDequeue_RcBinaryMinHeap | 100 | 8,655.79 ns | 23.703 ns | 22.172 ns |
|
||||||
|
| EnqueueDequeue_PriorityQueue | 100 | 7,806.20 ns | 105.801 ns | 98.967 ns |
|
||||||
|
| Enqueue_RcSortedQueue | 1000 | 7,566.23 ns | 149.010 ns | 218.418 ns |
|
||||||
|
| Enqueue_RcBinaryMinHeap | 1000 | 36,277.43 ns | 96.710 ns | 90.462 ns |
|
||||||
|
| Enqueue_PriorityQueue | 1000 | 28,564.19 ns | 186.866 ns | 174.795 ns |
|
||||||
|
| DequeueAll_RcSortedQueue | 1000 | 108,574.26 ns | 745.459 ns | 697.303 ns |
|
||||||
|
| DequeueAll_RcBinaryMinHeap | 1000 | 210,346.25 ns | 332.478 ns | 311.000 ns |
|
||||||
|
| DequeueAll_PriorityQueue | 1000 | 189,536.32 ns | 1,180.045 ns | 1,046.079 ns |
|
||||||
|
| EnqueueDequeue_RcSortedQueue | 1000 | 8,957,965.42 ns | 45,715.567 ns | 42,762.370 ns |
|
||||||
|
| EnqueueDequeue_RcBinaryMinHeap | 1000 | 131,615.02 ns | 394.216 ns | 368.750 ns |
|
||||||
|
| EnqueueDequeue_PriorityQueue | 1000 | 114,799.89 ns | 1,269.621 ns | 1,060.191 ns |
|
||||||
|
| Enqueue_RcSortedQueue | 10000 | 77,143.76 ns | 996.372 ns | 932.007 ns |
|
||||||
|
| Enqueue_RcBinaryMinHeap | 10000 | 417,620.57 ns | 853.343 ns | 756.466 ns |
|
||||||
|
| Enqueue_PriorityQueue | 10000 | 278,791.68 ns | 1,566.093 ns | 1,464.924 ns |
|
||||||
|
| DequeueAll_RcSortedQueue | 10000 | 1,435,539.99 ns | 9,329.910 ns | 8,727.204 ns |
|
||||||
|
| DequeueAll_RcBinaryMinHeap | 10000 | 2,956,366.90 ns | 6,344.030 ns | 5,934.210 ns |
|
||||||
|
| DequeueAll_PriorityQueue | 10000 | 2,642,186.54 ns | 9,482.374 ns | 8,869.819 ns |
|
||||||
|
| EnqueueDequeue_RcSortedQueue | 10000 | 1,318,277,320.00 ns | 6,725,701.525 ns | 6,291,225.379 ns |
|
||||||
|
| EnqueueDequeue_RcBinaryMinHeap | 10000 | 1,712,170.68 ns | 5,674.513 ns | 5,307.943 ns |
|
||||||
|
| EnqueueDequeue_PriorityQueue | 10000 | 1,466,910.77 ns | 4,394.686 ns | 4,110.792 ns |
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class PriorityQueueBenchmarks
|
||||||
|
{
|
||||||
|
[Params(10, 100, 1000, 10000)] public int Count;
|
||||||
|
|
||||||
|
private RcSortedQueue<Node> _sq;
|
||||||
|
private RcBinaryMinHeap<Node> _bmHeap;
|
||||||
|
private PriorityQueue<Node, Node> _pq;
|
||||||
|
|
||||||
|
private float[] _priority;
|
||||||
|
|
||||||
|
class Node
|
||||||
|
{
|
||||||
|
public int id;
|
||||||
|
public float total;
|
||||||
|
}
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
static int Comp(Node x, Node y)
|
||||||
|
{
|
||||||
|
var v = x.total.CompareTo(y.total);
|
||||||
|
if (v != 0)
|
||||||
|
return v;
|
||||||
|
return x.id.CompareTo(y.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
_sq = new(Comp);
|
||||||
|
_bmHeap = new(Count, Comp);
|
||||||
|
_pq = new(Count, Comparer<Node>.Create(Comp));
|
||||||
|
|
||||||
|
_priority = new float[Count];
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
_priority[i] = (float)Random.Shared.NextDouble() * 100f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void Enqueue_RcSortedQueue()
|
||||||
|
{
|
||||||
|
_sq.Clear();
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
_sq.Enqueue(new Node
|
||||||
|
{
|
||||||
|
id = i,
|
||||||
|
total = _priority[i],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void Enqueue_RcBinaryMinHeap()
|
||||||
|
{
|
||||||
|
_bmHeap.Clear();
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
_bmHeap.Push(new Node
|
||||||
|
{
|
||||||
|
id = i,
|
||||||
|
total = _priority[i],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void Enqueue_PriorityQueue()
|
||||||
|
{
|
||||||
|
_pq.Clear();
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
var node = new Node
|
||||||
|
{
|
||||||
|
id = i,
|
||||||
|
total = _priority[i],
|
||||||
|
};
|
||||||
|
_pq.Enqueue(node, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void DequeueAll_RcSortedQueue()
|
||||||
|
{
|
||||||
|
_sq.Clear();
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
_sq.Enqueue(new Node
|
||||||
|
{
|
||||||
|
id = i,
|
||||||
|
total = _priority[i],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
while (_sq.Count() > 0)
|
||||||
|
{
|
||||||
|
_sq.Dequeue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void DequeueAll_RcBinaryMinHeap()
|
||||||
|
{
|
||||||
|
_bmHeap.Clear();
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
_bmHeap.Push(new Node
|
||||||
|
{
|
||||||
|
id = i,
|
||||||
|
total = _priority[i],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
while (_bmHeap.Count > 0)
|
||||||
|
{
|
||||||
|
_bmHeap.Pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void DequeueAll_PriorityQueue()
|
||||||
|
{
|
||||||
|
_pq.Clear();
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
var node = new Node
|
||||||
|
{
|
||||||
|
id = i,
|
||||||
|
total = _priority[i],
|
||||||
|
};
|
||||||
|
_pq.Enqueue(node, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (_pq.Count > 0)
|
||||||
|
{
|
||||||
|
_pq.Dequeue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void EnqueueDequeue_RcSortedQueue()
|
||||||
|
{
|
||||||
|
_sq.Clear();
|
||||||
|
int half = Count / 2;
|
||||||
|
for (int i = 0; i < half; i++)
|
||||||
|
{
|
||||||
|
_sq.Enqueue(new Node
|
||||||
|
{
|
||||||
|
id = i,
|
||||||
|
total = _priority[i],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = half; i < Count; i++)
|
||||||
|
{
|
||||||
|
_sq.Enqueue(new Node
|
||||||
|
{
|
||||||
|
id = i,
|
||||||
|
total = _priority[i],
|
||||||
|
});
|
||||||
|
|
||||||
|
_sq.Dequeue();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void EnqueueDequeue_RcBinaryMinHeap()
|
||||||
|
{
|
||||||
|
_bmHeap.Clear();
|
||||||
|
int half = Count / 2;
|
||||||
|
for (int i = 0; i < half; i++)
|
||||||
|
{
|
||||||
|
_bmHeap.Push(new Node
|
||||||
|
{
|
||||||
|
id = i,
|
||||||
|
total = _priority[i],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = half; i < Count; i++)
|
||||||
|
{
|
||||||
|
_bmHeap.Push(new Node
|
||||||
|
{
|
||||||
|
id = i,
|
||||||
|
total = _priority[i],
|
||||||
|
});
|
||||||
|
|
||||||
|
_bmHeap.Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void EnqueueDequeue_PriorityQueue()
|
||||||
|
{
|
||||||
|
_pq.Clear();
|
||||||
|
int half = Count / 2;
|
||||||
|
for (int i = 0; i < half; i++)
|
||||||
|
{
|
||||||
|
var node = new Node
|
||||||
|
{
|
||||||
|
id = i,
|
||||||
|
total = _priority[i],
|
||||||
|
};
|
||||||
|
_pq.Enqueue(node, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = half; i < Count; i++)
|
||||||
|
{
|
||||||
|
var node = new Node
|
||||||
|
{
|
||||||
|
id = i,
|
||||||
|
total = _priority[i],
|
||||||
|
};
|
||||||
|
_pq.Enqueue(node, node);
|
||||||
|
_pq.Dequeue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using BenchmarkDotNet.Engines;
|
||||||
|
|
||||||
|
namespace DotRecast.Benchmark.Benchmarks;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
| Method | TestArraySize | Mean | Error | StdDev | Median |
|
||||||
|
|------------------------------- |-------------- |-------------:|-----------:|------------:|-------------:|
|
||||||
|
| Stackalloc_Long | 16 | 3.016 ns | 0.0179 ns | 0.0149 ns | 3.017 ns |
|
||||||
|
| Stackalloc_Long_SkipLocalsInit | 16 | 2.265 ns | 0.0197 ns | 0.0184 ns | 2.258 ns |
|
||||||
|
| New_Long | 16 | 5.917 ns | 0.1964 ns | 0.5634 ns | 5.761 ns |
|
||||||
|
| New_Long_SkipLocalsInit | 16 | 5.703 ns | 0.1371 ns | 0.3935 ns | 5.661 ns |
|
||||||
|
| Stackalloc_Long | 256 | 39.418 ns | 0.2737 ns | 0.2285 ns | 39.410 ns |
|
||||||
|
| Stackalloc_Long_SkipLocalsInit | 256 | 2.274 ns | 0.0147 ns | 0.0131 ns | 2.274 ns |
|
||||||
|
| New_Long | 256 | 53.901 ns | 2.9999 ns | 8.4614 ns | 51.449 ns |
|
||||||
|
| New_Long_SkipLocalsInit | 256 | 53.480 ns | 1.8716 ns | 5.4298 ns | 51.858 ns |
|
||||||
|
| Stackalloc_Long | 1024 | 137.037 ns | 0.3652 ns | 0.3416 ns | 137.031 ns |
|
||||||
|
| Stackalloc_Long_SkipLocalsInit | 1024 | 3.669 ns | 0.0254 ns | 0.0226 ns | 3.668 ns |
|
||||||
|
| New_Long | 1024 | 197.324 ns | 9.2795 ns | 27.0687 ns | 186.588 ns |
|
||||||
|
| New_Long_SkipLocalsInit | 1024 | 210.996 ns | 10.0255 ns | 27.9471 ns | 206.110 ns |
|
||||||
|
| Stackalloc_Long | 8192 | 1,897.989 ns | 7.1814 ns | 5.9968 ns | 1,897.814 ns |
|
||||||
|
| Stackalloc_Long_SkipLocalsInit | 8192 | 20.598 ns | 0.2645 ns | 0.2344 ns | 20.572 ns |
|
||||||
|
| New_Long | 8192 | 1,324.061 ns | 39.8447 ns | 116.2288 ns | 1,298.794 ns |
|
||||||
|
| New_Long_SkipLocalsInit | 8192 | 1,305.211 ns | 35.1855 ns | 102.0796 ns | 1,295.539 ns |
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class StackallocBenchmarks
|
||||||
|
{
|
||||||
|
private readonly Consumer _consumer = new();
|
||||||
|
|
||||||
|
[Params(1 << 4, 1 << 8, 1 << 10, 1 << 13)]
|
||||||
|
public int HashTableSize;
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void Stackalloc_Long()
|
||||||
|
{
|
||||||
|
Span<long> hashTable = stackalloc long[HashTableSize];
|
||||||
|
|
||||||
|
_consumer.Consume(hashTable[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
[SkipLocalsInit]
|
||||||
|
public void Stackalloc_Long_SkipLocalsInit()
|
||||||
|
{
|
||||||
|
Span<long> hashTable = stackalloc long[HashTableSize];
|
||||||
|
|
||||||
|
_consumer.Consume(hashTable[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void New_Long()
|
||||||
|
{
|
||||||
|
Span<long> hashTable = new long[HashTableSize];
|
||||||
|
|
||||||
|
_consumer.Consume(hashTable[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
[SkipLocalsInit]
|
||||||
|
public void New_Long_SkipLocalsInit()
|
||||||
|
{
|
||||||
|
Span<long> hashTable = new long[HashTableSize];
|
||||||
|
|
||||||
|
_consumer.Consume(hashTable[0]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using BenchmarkDotNet.Engines;
|
||||||
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
|
namespace DotRecast.Benchmark.Benchmarks;
|
||||||
|
|
||||||
|
/*
|
||||||
|
| Method | Mean | Error | StdDev |
|
||||||
|
|------------------ |----------:|----------:|----------:|
|
||||||
|
| Dot_Vector3 | 0.6395 ns | 0.0125 ns | 0.0104 ns |
|
||||||
|
| Dot_RcVec3f | 0.2275 ns | 0.0281 ns | 0.0375 ns |
|
||||||
|
| Cross_Vector3 | 1.1652 ns | 0.0102 ns | 0.0085 ns |
|
||||||
|
| Cross_RcVec3f | 1.1687 ns | 0.0140 ns | 0.0124 ns |
|
||||||
|
| Normalize_Vector3 | 1.7964 ns | 0.0173 ns | 0.0162 ns |
|
||||||
|
| Normalize_RcVec3f | 1.2806 ns | 0.0088 ns | 0.0078 ns |
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class VectorBenchmarks
|
||||||
|
{
|
||||||
|
private readonly Consumer _consumer = new();
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void Dot_Vector3()
|
||||||
|
{
|
||||||
|
var v1 = new System.Numerics.Vector3(1, 2, 3);
|
||||||
|
var v2 = new System.Numerics.Vector3(1, 2, 3);
|
||||||
|
var v = System.Numerics.Vector3.Dot(v1, v2);
|
||||||
|
_consumer.Consume(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void Dot_RcVec3f()
|
||||||
|
{
|
||||||
|
var v1 = new RcVec3f(1, 2, 3);
|
||||||
|
var v2 = new RcVec3f(1, 2, 3);
|
||||||
|
var v = RcVec3f.Dot(v1, v2);
|
||||||
|
_consumer.Consume(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void Cross_Vector3()
|
||||||
|
{
|
||||||
|
var v1 = new System.Numerics.Vector3(1, 2, 3);
|
||||||
|
var v2 = new System.Numerics.Vector3(1, 2, 3);
|
||||||
|
var v = System.Numerics.Vector3.Cross(v1, v2);
|
||||||
|
_consumer.Consume(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void Cross_RcVec3f()
|
||||||
|
{
|
||||||
|
var v1 = new RcVec3f(1, 2, 3);
|
||||||
|
var v2 = new RcVec3f(1, 2, 3);
|
||||||
|
var v = RcVec3f.Cross(v1, v2);
|
||||||
|
_consumer.Consume(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void Normalize_Vector3()
|
||||||
|
{
|
||||||
|
var v1 = new System.Numerics.Vector3(1, 2, 3);
|
||||||
|
var v = System.Numerics.Vector3.Normalize(v1);
|
||||||
|
_consumer.Consume(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void Normalize_RcVec3f()
|
||||||
|
{
|
||||||
|
var v1 = new RcVec3f(1, 2, 3);
|
||||||
|
var v = RcVec3f.Normalize(v1);
|
||||||
|
_consumer.Consume(v);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\DotRecast.Core\DotRecast.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -7,11 +7,11 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
<PackageReference Include="Moq" Version="4.20.70" />
|
<PackageReference Include="Moq" Version="4.20.72" />
|
||||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
<PackageReference Include="NUnit" Version="4.2.2" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.2.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
using DotRecast.Core.Collections;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace DotRecast.Core.Test;
|
||||||
|
|
||||||
|
public class RcBinaryMinHeapTest
|
||||||
|
{
|
||||||
|
private static readonly RcAtomicLong Gen = new();
|
||||||
|
|
||||||
|
private class Node
|
||||||
|
{
|
||||||
|
public readonly long Id;
|
||||||
|
public long Value;
|
||||||
|
|
||||||
|
public Node(int value)
|
||||||
|
{
|
||||||
|
Id = Gen.IncrementAndGet();
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPush()
|
||||||
|
{
|
||||||
|
var minHeap = new RcBinaryMinHeap<Node>((x, y) => x.Value.CompareTo(y.Value));
|
||||||
|
|
||||||
|
minHeap.Push(new Node(5));
|
||||||
|
minHeap.Push(new Node(3));
|
||||||
|
minHeap.Push(new Node(7));
|
||||||
|
minHeap.Push(new Node(2));
|
||||||
|
minHeap.Push(new Node(4));
|
||||||
|
|
||||||
|
// Push 후 힙의 속성을 검증
|
||||||
|
AssertHeapProperty(minHeap.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPop()
|
||||||
|
{
|
||||||
|
var minHeap = new RcBinaryMinHeap<Node>((x, y) => x.Value.CompareTo(y.Value));
|
||||||
|
|
||||||
|
minHeap.Push(new Node(5));
|
||||||
|
minHeap.Push(new Node(3));
|
||||||
|
minHeap.Push(new Node(7));
|
||||||
|
minHeap.Push(new Node(2));
|
||||||
|
minHeap.Push(new Node(4));
|
||||||
|
|
||||||
|
// Pop을 통해 최소 값부터 순서대로 제거하면서 검증
|
||||||
|
Assert.That(minHeap.Pop().Value, Is.EqualTo(2));
|
||||||
|
Assert.That(minHeap.Pop().Value, Is.EqualTo(3));
|
||||||
|
Assert.That(minHeap.Pop().Value, Is.EqualTo(4));
|
||||||
|
Assert.That(minHeap.Pop().Value, Is.EqualTo(5));
|
||||||
|
Assert.That(minHeap.Pop().Value, Is.EqualTo(7));
|
||||||
|
|
||||||
|
// 모든 요소를 Pop한 후에는 비어있어야 함
|
||||||
|
Assert.That(minHeap.IsEmpty(), Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestTop()
|
||||||
|
{
|
||||||
|
var minHeap = new RcBinaryMinHeap<Node>((x, y) => x.Value.CompareTo(y.Value));
|
||||||
|
|
||||||
|
minHeap.Push(new Node(5));
|
||||||
|
minHeap.Push(new Node(3));
|
||||||
|
minHeap.Push(new Node(7));
|
||||||
|
|
||||||
|
Assert.That(minHeap.Top().Value, Is.EqualTo(3));
|
||||||
|
AssertHeapProperty(minHeap.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestModify()
|
||||||
|
{
|
||||||
|
var minHeap = new RcBinaryMinHeap<Node>((x, y) => x.Value.CompareTo(y.Value));
|
||||||
|
|
||||||
|
var node7 = new Node(7);
|
||||||
|
minHeap.Push(new Node(5));
|
||||||
|
minHeap.Push(new Node(3));
|
||||||
|
minHeap.Push(node7);
|
||||||
|
minHeap.Push(new Node(2));
|
||||||
|
minHeap.Push(new Node(4));
|
||||||
|
|
||||||
|
node7.Value = 1;
|
||||||
|
var result = minHeap.Modify(node7); // Modify value 7 to 1
|
||||||
|
var result2 = minHeap.Modify(new Node(4));
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(true));
|
||||||
|
Assert.That(result2, Is.EqualTo(false));
|
||||||
|
Assert.That(minHeap.Top().Value, Is.EqualTo(1));
|
||||||
|
AssertHeapProperty(minHeap.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCount()
|
||||||
|
{
|
||||||
|
var minHeap = new RcBinaryMinHeap<Node>((x, y) => x.Value.CompareTo(y.Value));
|
||||||
|
|
||||||
|
minHeap.Push(new Node(5));
|
||||||
|
minHeap.Push(new Node(3));
|
||||||
|
minHeap.Push(new Node(7));
|
||||||
|
|
||||||
|
Assert.That(minHeap.Count, Is.EqualTo(3));
|
||||||
|
|
||||||
|
minHeap.Pop();
|
||||||
|
|
||||||
|
Assert.That(minHeap.Count, Is.EqualTo(2));
|
||||||
|
|
||||||
|
minHeap.Clear();
|
||||||
|
|
||||||
|
Assert.That(minHeap.Count, Is.EqualTo(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestIsEmpty()
|
||||||
|
{
|
||||||
|
var minHeap = new RcBinaryMinHeap<Node>((x, y) => x.Value.CompareTo(y.Value));
|
||||||
|
|
||||||
|
Assert.That(minHeap.IsEmpty(), Is.True);
|
||||||
|
|
||||||
|
minHeap.Push(new Node(5));
|
||||||
|
|
||||||
|
Assert.That(minHeap.IsEmpty(), Is.False);
|
||||||
|
|
||||||
|
minHeap.Pop();
|
||||||
|
|
||||||
|
Assert.That(minHeap.IsEmpty(), Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertHeapProperty(Node[] array)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < array.Length / 2; i++)
|
||||||
|
{
|
||||||
|
int leftChildIndex = 2 * i + 1;
|
||||||
|
int rightChildIndex = 2 * i + 2;
|
||||||
|
|
||||||
|
// 왼쪽 자식 노드가 있는지 확인하고 비교
|
||||||
|
if (leftChildIndex < array.Length)
|
||||||
|
Assert.That(array[i].Value, Is.LessThanOrEqualTo(array[leftChildIndex].Value));
|
||||||
|
|
||||||
|
// 오른쪽 자식 노드가 있는지 확인하고 비교
|
||||||
|
if (rightChildIndex < array.Length)
|
||||||
|
Assert.That(array[i].Value, Is.LessThanOrEqualTo(array[rightChildIndex].Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using DotRecast.Core.Buffers;
|
using DotRecast.Core.Buffers;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Core.Test;
|
namespace DotRecast.Core.Test;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace DotRecast.Core.Test;
|
||||||
|
|
||||||
|
public class RcIoTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void Test()
|
||||||
|
{
|
||||||
|
const long tileRef = 281474976710656L;
|
||||||
|
const int dataSize = 344;
|
||||||
|
|
||||||
|
byte[] actual;
|
||||||
|
|
||||||
|
{
|
||||||
|
using MemoryStream ms = new MemoryStream();
|
||||||
|
using BinaryWriter bw = new BinaryWriter(ms);
|
||||||
|
|
||||||
|
RcIO.Write(bw, tileRef, RcByteOrder.LITTLE_ENDIAN);
|
||||||
|
RcIO.Write(bw, dataSize, RcByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
|
bw.Flush();
|
||||||
|
actual= ms.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using MemoryStream ms = new MemoryStream(actual);
|
||||||
|
using BinaryReader br = new BinaryReader(ms);
|
||||||
|
var byteBuffer = RcIO.ToByteBuffer(br);
|
||||||
|
byteBuffer.Order(RcByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
|
Assert.That(byteBuffer.GetLong(), Is.EqualTo(tileRef));
|
||||||
|
Assert.That(byteBuffer.GetInt(), Is.EqualTo(dataSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace DotRecast.Core.Test;
|
||||||
|
|
||||||
|
public class RcMathTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestSqr()
|
||||||
|
{
|
||||||
|
Assert.That(RcMath.Sqr(0), Is.EqualTo(0));
|
||||||
|
Assert.That(RcMath.Sqr(5), Is.EqualTo(25));
|
||||||
|
Assert.That(RcMath.Sqr(-5), Is.EqualTo(25));
|
||||||
|
Assert.That(RcMath.Sqr(float.PositiveInfinity), Is.EqualTo(float.PositiveInfinity));
|
||||||
|
Assert.That(RcMath.Sqr(float.NegativeInfinity), Is.EqualTo(float.PositiveInfinity));
|
||||||
|
Assert.That(RcMath.Sqr(float.NaN), Is.EqualTo(float.NaN));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestLerp()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
Assert.That(RcMath.Lerp(-10, 10, 2f), Is.EqualTo(30));
|
||||||
|
Assert.That(RcMath.Lerp(-10, 10, 1f), Is.EqualTo(10));
|
||||||
|
Assert.That(RcMath.Lerp(-10, 10, 0.5f), Is.EqualTo(0));
|
||||||
|
Assert.That(RcMath.Lerp(-10, 10, 0.25f), Is.EqualTo(-5));
|
||||||
|
Assert.That(RcMath.Lerp(-10, 10, 0), Is.EqualTo(-10));
|
||||||
|
Assert.That(RcMath.Lerp(-10, 10, -0.5f), Is.EqualTo(-20));
|
||||||
|
Assert.That(RcMath.Lerp(-10, 10, -1f), Is.EqualTo(-30));
|
||||||
|
|
||||||
|
//
|
||||||
|
Assert.That(RcMath.Lerp(10, 10, 0.5f), Is.EqualTo(10));
|
||||||
|
Assert.That(RcMath.Lerp(10, 10, 0.8f), Is.EqualTo(10));
|
||||||
|
|
||||||
|
//
|
||||||
|
Assert.That(RcMath.Lerp(10, -10, 0.75f), Is.EqualTo(-5));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml;
|
|
||||||
using DotRecast.Core.Buffers;
|
using DotRecast.Core.Buffers;
|
||||||
using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Serialization;
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Core.Test;
|
namespace DotRecast.Core.Test;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace DotRecast.Core.Test;
|
||||||
|
|
||||||
|
public class RcSpanTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestCopy()
|
||||||
|
{
|
||||||
|
// Test for copying all elements to the destination span.
|
||||||
|
{
|
||||||
|
Span<long> src = stackalloc long[] { 1, 2, 3 };
|
||||||
|
Span<long> dst = stackalloc long[] { 0, 0, 0 };
|
||||||
|
|
||||||
|
RcSpans.Copy(src, dst);
|
||||||
|
Assert.That(src.ToArray(), Is.EqualTo(dst.ToArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for successful copying when the destination Span has a larger size.
|
||||||
|
{
|
||||||
|
Span<long> src = stackalloc long[] { 1, 2 };
|
||||||
|
Span<long> dst = stackalloc long[] { 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
RcSpans.Copy(src, dst);
|
||||||
|
Assert.That(src.ToArray(), Is.EqualTo(dst.Slice(0, src.Length).ToArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for an error when copying to a Span with a smaller size.
|
||||||
|
{
|
||||||
|
Assert.Throws<ArgumentException>(() =>
|
||||||
|
{
|
||||||
|
Span<long> src = stackalloc long[] { 1, 2, 3, 4, 5 };
|
||||||
|
Span<long> dst = stackalloc long[] { 0, 0, 0 };
|
||||||
|
RcSpans.Copy(src, dst);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for copying a specific range of elements from the source span to a specific range in the destination span.
|
||||||
|
{
|
||||||
|
Span<long> src = stackalloc long[] { 1, 2, 3, 4, 5 };
|
||||||
|
Span<long> dst = stackalloc long[] { 0, 0, 0 };
|
||||||
|
|
||||||
|
RcSpans.Copy(src, 2, dst, 0, 2);
|
||||||
|
Assert.That(src.Slice(2, 2).ToArray(), Is.EqualTo(dst.Slice(0, 2).ToArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for copying a specific range of elements from the source span to a specific range in the destination span.
|
||||||
|
{
|
||||||
|
Span<long> src = stackalloc long[] { 5, 4, 3, 2, 1 };
|
||||||
|
Span<long> dst = stackalloc long[] { 0, 0, 0 };
|
||||||
|
|
||||||
|
RcSpans.Copy(src, 2, dst, 0, 3);
|
||||||
|
Assert.That(src.Slice(2, 3).ToArray(), Is.EqualTo(dst.ToArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for src (index + length) over
|
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||||
|
{
|
||||||
|
Span<long> src = stackalloc long[] { 5, 4, 3, 2, 1 };
|
||||||
|
Span<long> dst = stackalloc long[] { 0, 0, 0 };
|
||||||
|
|
||||||
|
//
|
||||||
|
RcSpans.Copy(src, 3, dst, 0, 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test for src (index + length) over
|
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||||
|
{
|
||||||
|
Span<long> src = stackalloc long[] { 5, 4, 3, 2, 1 };
|
||||||
|
Span<long> dst = stackalloc long[] { 0, 0, 0 };
|
||||||
|
|
||||||
|
//
|
||||||
|
RcSpans.Copy(src, 5, dst, 0, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Test for dst (idx + length) over
|
||||||
|
Assert.Throws<ArgumentException>(() =>
|
||||||
|
{
|
||||||
|
Span<long> src = stackalloc long[] { 5, 4, 3, 2, 1 };
|
||||||
|
Span<long> dst = stackalloc long[] { 0, 0, 0 };
|
||||||
|
|
||||||
|
//
|
||||||
|
RcSpans.Copy(src, 0, dst, 1, 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test for dst (idx + length) over
|
||||||
|
Assert.Throws<ArgumentException>(() =>
|
||||||
|
{
|
||||||
|
Span<long> src = stackalloc long[] { 5, 4, 3, 2, 1 };
|
||||||
|
Span<long> dst = stackalloc long[] { 0, 0, 0 };
|
||||||
|
|
||||||
|
//
|
||||||
|
RcSpans.Copy(src, 0, dst, 0, 4);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMove()
|
||||||
|
{
|
||||||
|
// [3, 2, 1] -> [3, 1, 1]
|
||||||
|
{
|
||||||
|
var expected = new List<long>() { 3, 1, 1 };
|
||||||
|
Span<long> src = stackalloc long[] { 3, 2, 1 };
|
||||||
|
RcSpans.Move(src, 2, 1, 1);
|
||||||
|
Assert.That(src.ToArray(), Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// [3, 2, 1] -> [2, 1, 1]
|
||||||
|
{
|
||||||
|
var expected = new List<long>() { 2, 1, 1 };
|
||||||
|
Span<long> src = stackalloc long[] { 3, 2, 1 };
|
||||||
|
RcSpans.Move(src, 1, 0, 2);
|
||||||
|
Assert.That(src.ToArray(), Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// [3, 2, 1] -> [3, 2, 1]
|
||||||
|
{
|
||||||
|
var expected = new List<long>() { 3, 2, 1 };
|
||||||
|
Span<long> src = stackalloc long[] { 3, 2, 1 };
|
||||||
|
RcSpans.Move(src, 0, 0, 3);
|
||||||
|
Assert.That(src.ToArray(), Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// length over
|
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||||
|
{
|
||||||
|
Span<long> src = stackalloc long[] { 3, 2, 1 };
|
||||||
|
RcSpans.Move(src, 0, 0, 4);
|
||||||
|
});
|
||||||
|
|
||||||
|
// source index over
|
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||||
|
{
|
||||||
|
Span<long> src = stackalloc long[] { 3, 2, 1 };
|
||||||
|
RcSpans.Move(src, 3, 0, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
// destination index over
|
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||||
|
{
|
||||||
|
Span<long> src = stackalloc long[] { 3, 2, 1 };
|
||||||
|
RcSpans.Move(src, 0, 3, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -25,7 +25,6 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Crowd.Test;
|
namespace DotRecast.Detour.Crowd.Test;
|
||||||
|
|
||||||
|
|
||||||
public class AbstractCrowdTest
|
public class AbstractCrowdTest
|
||||||
{
|
{
|
||||||
protected readonly long[] startRefs =
|
protected readonly long[] startRefs =
|
||||||
|
@ -63,8 +62,9 @@ public class AbstractCrowdTest
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp()
|
public void SetUp()
|
||||||
{
|
{
|
||||||
nmd = new RecastTestMeshBuilder().GetMeshData();
|
nmd = TestMeshDataFactory.Create();
|
||||||
navmesh = new DtNavMesh(nmd, 6, 0);
|
navmesh = new DtNavMesh();
|
||||||
|
navmesh.Init(nmd, 6, 0);
|
||||||
query = new DtNavMeshQuery(navmesh);
|
query = new DtNavMeshQuery(navmesh);
|
||||||
DtCrowdConfig config = new DtCrowdConfig(0.6f);
|
DtCrowdConfig config = new DtCrowdConfig(0.6f);
|
||||||
crowd = new DtCrowd(config, navmesh);
|
crowd = new DtCrowd(config, navmesh);
|
||||||
|
@ -153,7 +153,7 @@ public class AbstractCrowdTest
|
||||||
RcVec3f vel = RcVec3f.Subtract(tgt, pos);
|
RcVec3f vel = RcVec3f.Subtract(tgt, pos);
|
||||||
vel.Y = 0.0f;
|
vel.Y = 0.0f;
|
||||||
vel = RcVec3f.Normalize(vel);
|
vel = RcVec3f.Normalize(vel);
|
||||||
vel = vel.Scale(speed);
|
vel = vel * speed;
|
||||||
return vel;
|
return vel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
<PackageReference Include="Moq" Version="4.20.70" />
|
<PackageReference Include="Moq" Version="4.20.72" />
|
||||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
<PackageReference Include="NUnit" Version="4.2.2" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.2.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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.Numerics;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace DotRecast.Detour.Crowd.Test;
|
||||||
|
|
||||||
|
public class DtPathCorridorTest
|
||||||
|
{
|
||||||
|
private readonly DtPathCorridor corridor = new DtPathCorridor();
|
||||||
|
private readonly IDtQueryFilter filter = new DtQueryDefaultFilter();
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
corridor.Init(256);
|
||||||
|
corridor.Reset(0, new RcVec3f(10, 20, 30));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ShouldKeepOriginalPathInFindCornersWhenNothingCanBePruned()
|
||||||
|
{
|
||||||
|
var straightPath = new DtStraightPath[4];
|
||||||
|
straightPath[0] = new DtStraightPath(new RcVec3f(11, 20, 30.00001f), 0, 0);
|
||||||
|
straightPath[1] = new DtStraightPath(new RcVec3f(12, 20, 30.00002f), 0, 0);
|
||||||
|
straightPath[2] = new DtStraightPath(new RcVec3f(11f, 21, 32f), 0, 0);
|
||||||
|
straightPath[3] = new DtStraightPath(new RcVec3f(11f, 21, 32f), 0, 0);
|
||||||
|
var query = new DtNavMeshQueryMock(straightPath, DtStatus.DT_SUCCESS);
|
||||||
|
|
||||||
|
Span<DtStraightPath> path = stackalloc DtStraightPath[8];
|
||||||
|
var npath = corridor.FindCorners(path, 8, query, filter);
|
||||||
|
Assert.That(npath, Is.EqualTo(4));
|
||||||
|
Assert.That(path.Slice(0, npath).ToArray(), Is.EqualTo(straightPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ShouldPrunePathInFindCorners()
|
||||||
|
{
|
||||||
|
DtStraightPath[] straightPath = new DtStraightPath[5];
|
||||||
|
straightPath[0] = (new DtStraightPath(new RcVec3f(10, 20, 30.00001f), 0, 0)); // too close
|
||||||
|
straightPath[1] = (new DtStraightPath(new RcVec3f(10, 20, 30.00002f), 0, 0)); // too close
|
||||||
|
straightPath[2] = (new DtStraightPath(new RcVec3f(11f, 21, 32f), 0, 0));
|
||||||
|
straightPath[3] = (new DtStraightPath(new RcVec3f(12f, 22, 33f), DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION, 0)); // offmesh
|
||||||
|
straightPath[4] = (new DtStraightPath(new RcVec3f(11f, 21, 32f), DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION, 0)); // offmesh
|
||||||
|
|
||||||
|
var query = new DtNavMeshQueryMock(straightPath, DtStatus.DT_SUCCESS);
|
||||||
|
|
||||||
|
Span<DtStraightPath> path = stackalloc DtStraightPath[8];
|
||||||
|
int npath = corridor.FindCorners(path, 8, query, filter);
|
||||||
|
Assert.That(npath, Is.EqualTo(2));
|
||||||
|
Assert.That(path.Slice(0, npath).ToArray(), Is.EqualTo(new DtStraightPath[] { straightPath[2], straightPath[3] }));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,101 +0,0 @@
|
||||||
/*
|
|
||||||
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.Core.Numerics;
|
|
||||||
|
|
||||||
using Moq;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour.Crowd.Test;
|
|
||||||
|
|
||||||
|
|
||||||
public class PathCorridorTest
|
|
||||||
{
|
|
||||||
private readonly DtPathCorridor corridor = new DtPathCorridor();
|
|
||||||
private readonly IDtQueryFilter filter = new DtQueryDefaultFilter();
|
|
||||||
|
|
||||||
[SetUp]
|
|
||||||
public void SetUp()
|
|
||||||
{
|
|
||||||
corridor.Init(256);
|
|
||||||
corridor.Reset(0, new RcVec3f(10, 20, 30));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ShouldKeepOriginalPathInFindCornersWhenNothingCanBePruned()
|
|
||||||
{
|
|
||||||
List<DtStraightPath> straightPath = new();
|
|
||||||
straightPath.Add(new DtStraightPath(new RcVec3f(11, 20, 30.00001f), 0, 0));
|
|
||||||
straightPath.Add(new DtStraightPath(new RcVec3f(12, 20, 30.00002f), 0, 0));
|
|
||||||
straightPath.Add(new DtStraightPath(new RcVec3f(11f, 21, 32f), 0, 0));
|
|
||||||
straightPath.Add(new DtStraightPath(new RcVec3f(11f, 21, 32f), 0, 0));
|
|
||||||
var mockQuery = new Mock<DtNavMeshQuery>(It.IsAny<DtNavMesh>());
|
|
||||||
mockQuery.Setup(q => q.FindStraightPath(
|
|
||||||
It.IsAny<RcVec3f>(),
|
|
||||||
It.IsAny<RcVec3f>(),
|
|
||||||
It.IsAny<List<long>>(),
|
|
||||||
ref It.Ref<List<DtStraightPath>>.IsAny,
|
|
||||||
It.IsAny<int>(),
|
|
||||||
It.IsAny<int>())
|
|
||||||
)
|
|
||||||
.Callback((RcVec3f startPos, RcVec3f endPos, List<long> path,
|
|
||||||
ref List<DtStraightPath> refStraightPath, int maxStraightPath, int options) =>
|
|
||||||
{
|
|
||||||
refStraightPath = straightPath;
|
|
||||||
})
|
|
||||||
.Returns(() => DtStatus.DT_SUCCESS);
|
|
||||||
|
|
||||||
var path = new List<DtStraightPath>();
|
|
||||||
corridor.FindCorners(ref path, int.MaxValue, mockQuery.Object, filter);
|
|
||||||
Assert.That(path.Count, Is.EqualTo(4));
|
|
||||||
Assert.That(path, Is.EqualTo(straightPath));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ShouldPrunePathInFindCorners()
|
|
||||||
{
|
|
||||||
List<DtStraightPath> straightPath = new();
|
|
||||||
straightPath.Add(new DtStraightPath(new RcVec3f(10, 20, 30.00001f), 0, 0)); // too close
|
|
||||||
straightPath.Add(new DtStraightPath(new RcVec3f(10, 20, 30.00002f), 0, 0)); // too close
|
|
||||||
straightPath.Add(new DtStraightPath(new RcVec3f(11f, 21, 32f), 0, 0));
|
|
||||||
straightPath.Add(new DtStraightPath(new RcVec3f(12f, 22, 33f), DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION, 0)); // offmesh
|
|
||||||
straightPath.Add(new DtStraightPath(new RcVec3f(11f, 21, 32f), DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION, 0)); // offmesh
|
|
||||||
|
|
||||||
var mockQuery = new Mock<DtNavMeshQuery>(It.IsAny<DtNavMesh>());
|
|
||||||
mockQuery.Setup(q => q.FindStraightPath(
|
|
||||||
It.IsAny<RcVec3f>(),
|
|
||||||
It.IsAny<RcVec3f>(),
|
|
||||||
It.IsAny<List<long>>(),
|
|
||||||
ref It.Ref<List<DtStraightPath>>.IsAny,
|
|
||||||
It.IsAny<int>(),
|
|
||||||
It.IsAny<int>())
|
|
||||||
).Callback((RcVec3f startPos, RcVec3f endPos, List<long> path,
|
|
||||||
ref List<DtStraightPath> refStraightPath, int maxStraightPath, int options) =>
|
|
||||||
{
|
|
||||||
refStraightPath = straightPath;
|
|
||||||
})
|
|
||||||
.Returns(() => DtStatus.DT_SUCCESS);
|
|
||||||
|
|
||||||
var path = new List<DtStraightPath>();
|
|
||||||
corridor.FindCorners(ref path, int.MaxValue, mockQuery.Object, filter);
|
|
||||||
Assert.That(path.Count, Is.EqualTo(2));
|
|
||||||
Assert.That(path, Is.EqualTo(new List<DtStraightPath> { straightPath[2], straightPath[3] }));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -22,46 +23,42 @@ using DotRecast.Recast.Geom;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Crowd.Test;
|
namespace DotRecast.Detour.Crowd.Test;
|
||||||
|
|
||||||
public class RecastTestMeshBuilder
|
public class TestMeshDataFactory
|
||||||
{
|
{
|
||||||
private readonly DtMeshData meshData;
|
private const float m_cellSize = 0.3f;
|
||||||
public const float m_cellSize = 0.3f;
|
private const float m_cellHeight = 0.2f;
|
||||||
public const float m_cellHeight = 0.2f;
|
private const float m_agentHeight = 2.0f;
|
||||||
public const float m_agentHeight = 2.0f;
|
private const float m_agentRadius = 0.6f;
|
||||||
public const float m_agentRadius = 0.6f;
|
private const float m_agentMaxClimb = 0.9f;
|
||||||
public const float m_agentMaxClimb = 0.9f;
|
private const float m_agentMaxSlope = 45.0f;
|
||||||
public const float m_agentMaxSlope = 45.0f;
|
private const int m_regionMinSize = 8;
|
||||||
public const int m_regionMinSize = 8;
|
private const int m_regionMergeSize = 20;
|
||||||
public const int m_regionMergeSize = 20;
|
private const float m_edgeMaxLen = 12.0f;
|
||||||
public const float m_edgeMaxLen = 12.0f;
|
private const float m_edgeMaxError = 1.3f;
|
||||||
public const float m_edgeMaxError = 1.3f;
|
private const int m_vertsPerPoly = 6;
|
||||||
public const int m_vertsPerPoly = 6;
|
private const float m_detailSampleDist = 6.0f;
|
||||||
public const float m_detailSampleDist = 6.0f;
|
private const float m_detailSampleMaxError = 1.0f;
|
||||||
public const float m_detailSampleMaxError = 1.0f;
|
|
||||||
|
|
||||||
public RecastTestMeshBuilder()
|
public static DtMeshData Create()
|
||||||
: this(SimpleInputGeomProvider.LoadFile("dungeon.obj"),
|
|
||||||
RcPartition.WATERSHED,
|
|
||||||
m_cellSize, m_cellHeight,
|
|
||||||
m_agentMaxSlope, m_agentHeight, m_agentRadius, m_agentMaxClimb,
|
|
||||||
m_regionMinSize, m_regionMergeSize,
|
|
||||||
m_edgeMaxLen, m_edgeMaxError,
|
|
||||||
m_vertsPerPoly,
|
|
||||||
m_detailSampleDist, m_detailSampleMaxError)
|
|
||||||
{
|
{
|
||||||
}
|
IInputGeomProvider geom = SimpleInputGeomProvider.LoadFile("dungeon.obj");
|
||||||
|
RcPartition partition = RcPartition.WATERSHED;
|
||||||
|
float cellSize = m_cellSize;
|
||||||
|
float cellHeight = m_cellHeight;
|
||||||
|
float agentMaxSlope = m_agentMaxSlope;
|
||||||
|
float agentHeight = m_agentHeight;
|
||||||
|
float agentRadius = m_agentRadius;
|
||||||
|
float agentMaxClimb = m_agentMaxClimb;
|
||||||
|
int regionMinSize = m_regionMinSize;
|
||||||
|
int regionMergeSize = m_regionMergeSize;
|
||||||
|
float edgeMaxLen = m_edgeMaxLen;
|
||||||
|
float edgeMaxError = m_edgeMaxError;
|
||||||
|
int vertsPerPoly = m_vertsPerPoly;
|
||||||
|
float detailSampleDist = m_detailSampleDist;
|
||||||
|
float detailSampleMaxError = m_detailSampleMaxError;
|
||||||
|
|
||||||
public RecastTestMeshBuilder(IInputGeomProvider geom,
|
|
||||||
RcPartition partitionType,
|
|
||||||
float cellSize, float cellHeight,
|
|
||||||
float agentMaxSlope, float agentHeight, float agentRadius, float agentMaxClimb,
|
|
||||||
int regionMinSize, int regionMergeSize,
|
|
||||||
float edgeMaxLen, float edgeMaxError,
|
|
||||||
int vertsPerPoly,
|
|
||||||
float detailSampleDist, float detailSampleMaxError)
|
|
||||||
{
|
|
||||||
RcConfig cfg = new RcConfig(
|
RcConfig cfg = new RcConfig(
|
||||||
partitionType,
|
partition,
|
||||||
cellSize, cellHeight,
|
cellSize, cellHeight,
|
||||||
agentMaxSlope, agentHeight, agentRadius, agentMaxClimb,
|
agentMaxSlope, agentHeight, agentRadius, agentMaxClimb,
|
||||||
regionMinSize, regionMergeSize,
|
regionMinSize, regionMergeSize,
|
||||||
|
@ -73,31 +70,31 @@ public class RecastTestMeshBuilder
|
||||||
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
|
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
|
||||||
RcBuilder rcBuilder = new RcBuilder();
|
RcBuilder rcBuilder = new RcBuilder();
|
||||||
RcBuilderResult rcResult = rcBuilder.Build(geom, bcfg, false);
|
RcBuilderResult rcResult = rcBuilder.Build(geom, bcfg, false);
|
||||||
RcPolyMesh m_pmesh = rcResult.Mesh;
|
RcPolyMesh pmesh = rcResult.Mesh;
|
||||||
for (int i = 0; i < m_pmesh.npolys; ++i)
|
for (int i = 0; i < pmesh.npolys; ++i)
|
||||||
{
|
{
|
||||||
m_pmesh.flags[i] = 1;
|
pmesh.flags[i] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
RcPolyMeshDetail m_dmesh = rcResult.MeshDetail;
|
RcPolyMeshDetail dmesh = rcResult.MeshDetail;
|
||||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||||
option.verts = m_pmesh.verts;
|
option.verts = pmesh.verts;
|
||||||
option.vertCount = m_pmesh.nverts;
|
option.vertCount = pmesh.nverts;
|
||||||
option.polys = m_pmesh.polys;
|
option.polys = pmesh.polys;
|
||||||
option.polyAreas = m_pmesh.areas;
|
option.polyAreas = pmesh.areas;
|
||||||
option.polyFlags = m_pmesh.flags;
|
option.polyFlags = pmesh.flags;
|
||||||
option.polyCount = m_pmesh.npolys;
|
option.polyCount = pmesh.npolys;
|
||||||
option.nvp = m_pmesh.nvp;
|
option.nvp = pmesh.nvp;
|
||||||
option.detailMeshes = m_dmesh.meshes;
|
option.detailMeshes = dmesh.meshes;
|
||||||
option.detailVerts = m_dmesh.verts;
|
option.detailVerts = dmesh.verts;
|
||||||
option.detailVertsCount = m_dmesh.nverts;
|
option.detailVertsCount = dmesh.nverts;
|
||||||
option.detailTris = m_dmesh.tris;
|
option.detailTris = dmesh.tris;
|
||||||
option.detailTriCount = m_dmesh.ntris;
|
option.detailTriCount = dmesh.ntris;
|
||||||
option.walkableHeight = agentHeight;
|
option.walkableHeight = agentHeight;
|
||||||
option.walkableRadius = agentRadius;
|
option.walkableRadius = agentRadius;
|
||||||
option.walkableClimb = agentMaxClimb;
|
option.walkableClimb = agentMaxClimb;
|
||||||
option.bmin = m_pmesh.bmin;
|
option.bmin = pmesh.bmin;
|
||||||
option.bmax = m_pmesh.bmax;
|
option.bmax = pmesh.bmax;
|
||||||
option.cs = cellSize;
|
option.cs = cellSize;
|
||||||
option.ch = cellHeight;
|
option.ch = cellHeight;
|
||||||
option.buildBvTree = true;
|
option.buildBvTree = true;
|
||||||
|
@ -120,11 +117,8 @@ public class RecastTestMeshBuilder
|
||||||
option.offMeshConUserID = new int[1];
|
option.offMeshConUserID = new int[1];
|
||||||
option.offMeshConUserID[0] = 0x4567;
|
option.offMeshConUserID[0] = 0x4567;
|
||||||
option.offMeshConCount = 1;
|
option.offMeshConCount = 1;
|
||||||
meshData = DtNavMeshBuilder.CreateNavMeshData(option);
|
var meshData = DtNavMeshBuilder.CreateNavMeshData(option);
|
||||||
}
|
|
||||||
|
|
||||||
public DtMeshData GetMeshData()
|
|
||||||
{
|
|
||||||
return meshData;
|
return meshData;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,11 +7,11 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
<PackageReference Include="Moq" Version="4.20.70" />
|
<PackageReference Include="Moq" Version="4.20.72" />
|
||||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
<PackageReference Include="NUnit" Version="4.2.2" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.2.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -6,6 +7,7 @@ using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Detour.Dynamic.Colliders;
|
using DotRecast.Detour.Dynamic.Colliders;
|
||||||
using DotRecast.Detour.Dynamic.Io;
|
using DotRecast.Detour.Dynamic.Io;
|
||||||
using DotRecast.Detour.Dynamic.Test.Io;
|
using DotRecast.Detour.Dynamic.Test.Io;
|
||||||
|
using DotRecast.Detour.Io;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Dynamic.Test;
|
namespace DotRecast.Detour.Dynamic.Test;
|
||||||
|
@ -21,7 +23,7 @@ public class DynamicNavMeshTest
|
||||||
[Test]
|
[Test]
|
||||||
public void E2eTest()
|
public void E2eTest()
|
||||||
{
|
{
|
||||||
byte[] bytes = RcResources.Load("test_tiles.voxels");
|
byte[] bytes = RcIO.ReadFileIfFound("test_tiles.voxels");
|
||||||
using var ms = new MemoryStream(bytes);
|
using var ms = new MemoryStream(bytes);
|
||||||
using var br = new BinaryReader(ms);
|
using var br = new BinaryReader(ms);
|
||||||
|
|
||||||
|
@ -78,4 +80,101 @@ public class DynamicNavMeshTest
|
||||||
// path length should be back to the initial value
|
// path length should be back to the initial value
|
||||||
Assert.That(path.Count, Is.EqualTo(16));
|
Assert.That(path.Count, Is.EqualTo(16));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ShouldSaveAndLoadDynamicNavMesh()
|
||||||
|
{
|
||||||
|
using var writerMs = new MemoryStream();
|
||||||
|
using var bw = new BinaryWriter(writerMs);
|
||||||
|
|
||||||
|
|
||||||
|
int maxVertsPerPoly = 6;
|
||||||
|
// load voxels from file
|
||||||
|
|
||||||
|
{
|
||||||
|
byte[] bytes = RcIO.ReadFileIfFound("test_tiles.voxels");
|
||||||
|
using var readMs = new MemoryStream(bytes);
|
||||||
|
using var br = new BinaryReader(readMs);
|
||||||
|
|
||||||
|
DtVoxelFileReader reader = new DtVoxelFileReader(DtVoxelTileLZ4ForTestCompressor.Shared);
|
||||||
|
DtVoxelFile f = reader.Read(br);
|
||||||
|
|
||||||
|
// create dynamic navmesh
|
||||||
|
DtDynamicNavMesh mesh = new DtDynamicNavMesh(f);
|
||||||
|
|
||||||
|
// build navmesh asynchronously using multiple threads
|
||||||
|
mesh.Build(Task.Factory);
|
||||||
|
|
||||||
|
// Save the resulting nav mesh and re-use it
|
||||||
|
new DtMeshSetWriter().Write(bw, mesh.NavMesh(), RcByteOrder.LITTLE_ENDIAN, true);
|
||||||
|
maxVertsPerPoly = mesh.NavMesh().GetMaxVertsPerPoly();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
byte[] bytes = RcIO.ReadFileIfFound("test_tiles.voxels");
|
||||||
|
using var readMs = new MemoryStream(bytes);
|
||||||
|
using var br = new BinaryReader(readMs);
|
||||||
|
|
||||||
|
// load voxels from file
|
||||||
|
DtVoxelFileReader reader = new DtVoxelFileReader(DtVoxelTileLZ4ForTestCompressor.Shared);
|
||||||
|
DtVoxelFile f = reader.Read(br);
|
||||||
|
|
||||||
|
// create dynamic navmesh
|
||||||
|
DtDynamicNavMesh mesh = new DtDynamicNavMesh(f);
|
||||||
|
// use the saved nav mesh instead of building from scratch
|
||||||
|
DtNavMesh navMesh = new DtMeshSetReader().Read(new RcByteBuffer(writerMs.ToArray()), maxVertsPerPoly);
|
||||||
|
mesh.NavMesh(navMesh);
|
||||||
|
|
||||||
|
DtNavMeshQuery query = new DtNavMeshQuery(mesh.NavMesh());
|
||||||
|
IDtQueryFilter filter = new DtQueryDefaultFilter();
|
||||||
|
|
||||||
|
// find path
|
||||||
|
_ = query.FindNearestPoly(START_POS, EXTENT, filter, out var startNearestRef, out var startNearestPos, out var _);
|
||||||
|
_ = query.FindNearestPoly(END_POS, EXTENT, filter, out var endNearestRef, out var endNearestPos, out var _);
|
||||||
|
|
||||||
|
List<long> path = new List<long>();
|
||||||
|
query.FindPath(startNearestRef, endNearestRef, startNearestPos, endNearestPos, filter, ref path, DtFindPathOption.AnyAngle);
|
||||||
|
|
||||||
|
// check path length without any obstacles
|
||||||
|
Assert.That(path.Count, Is.EqualTo(16));
|
||||||
|
|
||||||
|
// place obstacle
|
||||||
|
DtCollider colldier = new DtSphereCollider(SPHERE_POS, 20, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GROUND, 0.1f);
|
||||||
|
long colliderId = mesh.AddCollider(colldier);
|
||||||
|
|
||||||
|
// update navmesh asynchronously
|
||||||
|
mesh.Update(Task.Factory);
|
||||||
|
|
||||||
|
// create new query
|
||||||
|
query = new DtNavMeshQuery(mesh.NavMesh());
|
||||||
|
|
||||||
|
// find path again
|
||||||
|
_ = query.FindNearestPoly(START_POS, EXTENT, filter, out startNearestRef, out startNearestPos, out var _);
|
||||||
|
_ = query.FindNearestPoly(END_POS, EXTENT, filter, out endNearestRef, out endNearestPos, out var _);
|
||||||
|
|
||||||
|
path = new List<long>();
|
||||||
|
query.FindPath(startNearestRef, endNearestRef, startNearestPos, endNearestPos, filter, ref path, DtFindPathOption.AnyAngle);
|
||||||
|
|
||||||
|
// check path length with obstacles
|
||||||
|
Assert.That(path.Count, Is.EqualTo(19));
|
||||||
|
|
||||||
|
// remove obstacle
|
||||||
|
mesh.RemoveCollider(colliderId);
|
||||||
|
// update navmesh asynchronously
|
||||||
|
mesh.Update(Task.Factory);
|
||||||
|
|
||||||
|
// create new query
|
||||||
|
query = new DtNavMeshQuery(mesh.NavMesh());
|
||||||
|
// find path one more time
|
||||||
|
_ = query.FindNearestPoly(START_POS, EXTENT, filter, out startNearestRef, out startNearestPos, out var _);
|
||||||
|
_ = query.FindNearestPoly(END_POS, EXTENT, filter, out endNearestRef, out endNearestPos, out var _);
|
||||||
|
|
||||||
|
path = new List<long>();
|
||||||
|
query.FindPath(startNearestRef, endNearestRef, startNearestPos, endNearestPos, filter, ref path, DtFindPathOption.AnyAngle);
|
||||||
|
|
||||||
|
// path length should be back to the initial value
|
||||||
|
Assert.That(path.Count, Is.EqualTo(16));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -31,7 +31,7 @@ public class VoxelFileReaderTest
|
||||||
[Test]
|
[Test]
|
||||||
public void ShouldReadSingleTileFile()
|
public void ShouldReadSingleTileFile()
|
||||||
{
|
{
|
||||||
byte[] bytes = RcResources.Load("test.voxels");
|
byte[] bytes = RcIO.ReadFileIfFound("test.voxels");
|
||||||
using var ms = new MemoryStream(bytes);
|
using var ms = new MemoryStream(bytes);
|
||||||
using var br = new BinaryReader(ms);
|
using var br = new BinaryReader(ms);
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ public class VoxelFileReaderTest
|
||||||
[Test]
|
[Test]
|
||||||
public void ShouldReadMultiTileFile()
|
public void ShouldReadMultiTileFile()
|
||||||
{
|
{
|
||||||
byte[] bytes = RcResources.Load("test_tiles.voxels");
|
byte[] bytes = RcIO.ReadFileIfFound("test_tiles.voxels");
|
||||||
using var ms = new MemoryStream(bytes);
|
using var ms = new MemoryStream(bytes);
|
||||||
using var br = new BinaryReader(ms);
|
using var br = new BinaryReader(ms);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -32,7 +32,7 @@ public class VoxelFileReaderWriterTest
|
||||||
[TestCase(true)]
|
[TestCase(true)]
|
||||||
public void ShouldReadSingleTileFile(bool compression)
|
public void ShouldReadSingleTileFile(bool compression)
|
||||||
{
|
{
|
||||||
byte[] bytes = RcResources.Load("test.voxels");
|
byte[] bytes = RcIO.ReadFileIfFound("test.voxels");
|
||||||
using var ms = new MemoryStream(bytes);
|
using var ms = new MemoryStream(bytes);
|
||||||
using var br = new BinaryReader(ms);
|
using var br = new BinaryReader(ms);
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ public class VoxelFileReaderWriterTest
|
||||||
[TestCase(true)]
|
[TestCase(true)]
|
||||||
public void ShouldReadMultiTileFile(bool compression)
|
public void ShouldReadMultiTileFile(bool compression)
|
||||||
{
|
{
|
||||||
byte[] bytes = RcResources.Load("test_tiles.voxels");
|
byte[] bytes = RcIO.ReadFileIfFound("test_tiles.voxels");
|
||||||
using var ms = new MemoryStream(bytes);
|
using var ms = new MemoryStream(bytes);
|
||||||
using var br = new BinaryReader(ms);
|
using var br = new BinaryReader(ms);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -93,7 +93,7 @@ public class VoxelQueryTest
|
||||||
|
|
||||||
private DtDynamicNavMesh CreateDynaMesh()
|
private DtDynamicNavMesh CreateDynaMesh()
|
||||||
{
|
{
|
||||||
var bytes = RcResources.Load("test_tiles.voxels");
|
var bytes = RcIO.ReadFileIfFound("test_tiles.voxels");
|
||||||
using var ms = new MemoryStream(bytes);
|
using var ms = new MemoryStream(bytes);
|
||||||
using var br = new BinaryReader(ms);
|
using var br = new BinaryReader(ms);
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
<PackageReference Include="Moq" Version="4.20.70" />
|
<PackageReference Include="Moq" Version="4.20.72" />
|
||||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
<PackageReference Include="NUnit" Version="4.2.2" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.2.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -21,7 +22,6 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Test;
|
namespace DotRecast.Detour.Test;
|
||||||
|
|
||||||
|
|
||||||
public abstract class AbstractDetourTest
|
public abstract class AbstractDetourTest
|
||||||
{
|
{
|
||||||
protected static readonly long[] startRefs =
|
protected static readonly long[] startRefs =
|
||||||
|
@ -64,6 +64,8 @@ public abstract class AbstractDetourTest
|
||||||
|
|
||||||
protected DtNavMesh CreateNavMesh()
|
protected DtNavMesh CreateNavMesh()
|
||||||
{
|
{
|
||||||
return new DtNavMesh(new RecastTestMeshBuilder().GetMeshData(), 6, 0);
|
var mesh = new DtNavMesh();
|
||||||
|
mesh.Init(TestMeshDataFactory.Create(), 6, 0);
|
||||||
|
return mesh;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
<PackageReference Include="Moq" Version="4.20.70" />
|
<PackageReference Include="Moq" Version="4.20.72" />
|
||||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
<PackageReference Include="NUnit" Version="4.2.2" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.2.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using DotRecast.Core.Numerics;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace DotRecast.Detour.Test;
|
||||||
|
|
||||||
|
public class FindCollectPolyTest : AbstractDetourTest
|
||||||
|
{
|
||||||
|
private static readonly long[][] POLY_REFS =
|
||||||
|
{
|
||||||
|
new long[]
|
||||||
|
{
|
||||||
|
281474976710697L,
|
||||||
|
281474976710695L,
|
||||||
|
281474976710696L,
|
||||||
|
281474976710691L,
|
||||||
|
},
|
||||||
|
new long[]
|
||||||
|
{
|
||||||
|
281474976710769L,
|
||||||
|
281474976710773L,
|
||||||
|
},
|
||||||
|
new long[]
|
||||||
|
{
|
||||||
|
281474976710676L,
|
||||||
|
281474976710678L,
|
||||||
|
281474976710679L,
|
||||||
|
281474976710674L,
|
||||||
|
281474976710677L,
|
||||||
|
281474976710683L,
|
||||||
|
281474976710680L,
|
||||||
|
281474976710684L,
|
||||||
|
},
|
||||||
|
|
||||||
|
new long[]
|
||||||
|
{
|
||||||
|
281474976710748L,
|
||||||
|
281474976710753L,
|
||||||
|
281474976710752L,
|
||||||
|
281474976710750L,
|
||||||
|
},
|
||||||
|
|
||||||
|
new long[]
|
||||||
|
{
|
||||||
|
281474976710736L,
|
||||||
|
281474976710733L,
|
||||||
|
281474976710735L,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestFindNearestPoly()
|
||||||
|
{
|
||||||
|
IDtQueryFilter filter = new DtQueryDefaultFilter();
|
||||||
|
RcVec3f extents = new RcVec3f(2, 4, 2);
|
||||||
|
var polys = new long[32];
|
||||||
|
for (int i = 0; i < startRefs.Length; i++)
|
||||||
|
{
|
||||||
|
Array.Fill(polys, 0);
|
||||||
|
RcVec3f startPos = startPoss[i];
|
||||||
|
var status = query.QueryPolygons(startPos, extents, filter, polys, out var polyCount, 32);
|
||||||
|
Assert.That(status.Succeeded(), Is.True, $"index({i})");
|
||||||
|
Assert.That(polyCount, Is.EqualTo(POLY_REFS[i].Length), $"index({i})");
|
||||||
|
Assert.That(polys.AsSpan(0, polyCount).ToArray(), Is.EqualTo(POLY_REFS[i]), $"index({i})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -21,10 +22,12 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Test;
|
namespace DotRecast.Detour.Test;
|
||||||
|
|
||||||
|
|
||||||
public class FindNearestPolyTest : AbstractDetourTest
|
public class FindNearestPolyTest : AbstractDetourTest
|
||||||
{
|
{
|
||||||
private static readonly long[] POLY_REFS = { 281474976710696L, 281474976710773L, 281474976710680L, 281474976710753L, 281474976710733L };
|
private static readonly long[] POLY_REFS =
|
||||||
|
{
|
||||||
|
281474976710696L, 281474976710773L, 281474976710680L, 281474976710753L, 281474976710733L
|
||||||
|
};
|
||||||
|
|
||||||
private static readonly RcVec3f[] POLY_POS =
|
private static readonly RcVec3f[] POLY_POS =
|
||||||
{
|
{
|
||||||
|
@ -44,11 +47,11 @@ public class FindNearestPolyTest : AbstractDetourTest
|
||||||
{
|
{
|
||||||
RcVec3f startPos = startPoss[i];
|
RcVec3f startPos = startPoss[i];
|
||||||
var status = query.FindNearestPoly(startPos, extents, filter, out var nearestRef, out var nearestPt, out var _);
|
var status = query.FindNearestPoly(startPos, extents, filter, out var nearestRef, out var nearestPt, out var _);
|
||||||
Assert.That(status.Succeeded(), Is.True);
|
Assert.That(status.Succeeded(), Is.True, $"index({i})");
|
||||||
Assert.That(nearestRef, Is.EqualTo(POLY_REFS[i]));
|
Assert.That(nearestRef, Is.EqualTo(POLY_REFS[i]), $"index({i})");
|
||||||
Assert.That(nearestPt.X, Is.EqualTo(POLY_POS[i].X).Within(0.001f));
|
Assert.That(nearestPt.X, Is.EqualTo(POLY_POS[i].X).Within(0.001f), $"index({i})");
|
||||||
Assert.That(nearestPt.Y, Is.EqualTo(POLY_POS[i].Y).Within(0.001f));
|
Assert.That(nearestPt.Y, Is.EqualTo(POLY_POS[i].Y).Within(0.001f), $"index({i})");
|
||||||
Assert.That(nearestPt.Z, Is.EqualTo(POLY_POS[i].Z).Within(0.001f));
|
Assert.That(nearestPt.Z, Is.EqualTo(POLY_POS[i].Z).Within(0.001f), $"index({i})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -16,13 +17,13 @@ freely, subject to the following restrictions:
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Test;
|
namespace DotRecast.Detour.Test;
|
||||||
|
|
||||||
|
|
||||||
public class FindPathTest : AbstractDetourTest
|
public class FindPathTest : AbstractDetourTest
|
||||||
{
|
{
|
||||||
private static readonly DtStatus[] STATUSES =
|
private static readonly DtStatus[] STATUSES =
|
||||||
|
@ -184,6 +185,7 @@ public class FindPathTest : AbstractDetourTest
|
||||||
{
|
{
|
||||||
IDtQueryFilter filter = new DtQueryDefaultFilter();
|
IDtQueryFilter filter = new DtQueryDefaultFilter();
|
||||||
var path = new List<long>();
|
var path = new List<long>();
|
||||||
|
Span<DtStraightPath> straightPath = stackalloc DtStraightPath[256];
|
||||||
for (int i = 0; i < STRAIGHT_PATHS.Length; i++)
|
for (int i = 0; i < STRAIGHT_PATHS.Length; i++)
|
||||||
{
|
{
|
||||||
// startRefs.Length; i++) {
|
// startRefs.Length; i++) {
|
||||||
|
@ -192,9 +194,8 @@ public class FindPathTest : AbstractDetourTest
|
||||||
var startPos = startPoss[i];
|
var startPos = startPoss[i];
|
||||||
var endPos = endPoss[i];
|
var endPos = endPoss[i];
|
||||||
var status = query.FindPath(startRef, endRef, startPos, endPos, filter, ref path, DtFindPathOption.NoOption);
|
var status = query.FindPath(startRef, endRef, startPos, endPos, filter, ref path, DtFindPathOption.NoOption);
|
||||||
var straightPath = new List<DtStraightPath>();
|
query.FindStraightPath(startPos, endPos, path, path.Count, straightPath, out var nstraightPath, 256, 0);
|
||||||
query.FindStraightPath(startPos, endPos, path, ref straightPath, int.MaxValue, 0);
|
Assert.That(nstraightPath, Is.EqualTo(STRAIGHT_PATHS[i].Length));
|
||||||
Assert.That(straightPath.Count, Is.EqualTo(STRAIGHT_PATHS[i].Length));
|
|
||||||
for (int j = 0; j < STRAIGHT_PATHS[i].Length; j++)
|
for (int j = 0; j < STRAIGHT_PATHS[i].Length; j++)
|
||||||
{
|
{
|
||||||
Assert.That(straightPath[j].refs, Is.EqualTo(STRAIGHT_PATHS[i][j].refs));
|
Assert.That(straightPath[j].refs, Is.EqualTo(STRAIGHT_PATHS[i][j].refs));
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -16,13 +17,13 @@ freely, subject to the following restrictions:
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Test;
|
namespace DotRecast.Detour.Test;
|
||||||
|
|
||||||
|
|
||||||
public class GetPolyWallSegmentsTest : AbstractDetourTest
|
public class GetPolyWallSegmentsTest : AbstractDetourTest
|
||||||
{
|
{
|
||||||
private static readonly RcSegmentVert[][] VERTICES =
|
private static readonly RcSegmentVert[][] VERTICES =
|
||||||
|
@ -82,28 +83,30 @@ public class GetPolyWallSegmentsTest : AbstractDetourTest
|
||||||
[Test]
|
[Test]
|
||||||
public void TestFindDistanceToWall()
|
public void TestFindDistanceToWall()
|
||||||
{
|
{
|
||||||
var segmentVerts = new List<RcSegmentVert>();
|
const int MAX_SEGS = DtDetour.DT_VERTS_PER_POLYGON * 4;
|
||||||
var segmentRefs = new List<long>();
|
Span<RcSegmentVert> segs = stackalloc RcSegmentVert[MAX_SEGS];
|
||||||
|
Span<long> refs = stackalloc long[MAX_SEGS];
|
||||||
|
int nsegs = 0;
|
||||||
|
|
||||||
IDtQueryFilter filter = new DtQueryDefaultFilter();
|
IDtQueryFilter filter = new DtQueryDefaultFilter();
|
||||||
for (int i = 0; i < startRefs.Length; i++)
|
for (int i = 0; i < startRefs.Length; i++)
|
||||||
{
|
{
|
||||||
var result = query.GetPolyWallSegments(startRefs[i], true, filter, ref segmentVerts, ref segmentRefs);
|
var result = query.GetPolyWallSegments(startRefs[i], filter, segs, refs, ref nsegs, MAX_SEGS);
|
||||||
Assert.That(segmentVerts.Count, Is.EqualTo(VERTICES[i].Length));
|
Assert.That(nsegs, Is.EqualTo(VERTICES[i].Length));
|
||||||
Assert.That(segmentRefs.Count, Is.EqualTo(REFS[i].Length));
|
Assert.That(nsegs, Is.EqualTo(REFS[i].Length));
|
||||||
for (int v = 0; v < VERTICES[i].Length / 6; v++)
|
for (int v = 0; v < VERTICES[i].Length / 6; v++)
|
||||||
{
|
{
|
||||||
Assert.That(segmentVerts[v].vmin.X, Is.EqualTo(VERTICES[i][v].vmin.X).Within(0.001f));
|
Assert.That(segs[v].vmin.X, Is.EqualTo(VERTICES[i][v].vmin.X).Within(0.001f));
|
||||||
Assert.That(segmentVerts[v].vmin.Y, Is.EqualTo(VERTICES[i][v].vmin.Y).Within(0.001f));
|
Assert.That(segs[v].vmin.Y, Is.EqualTo(VERTICES[i][v].vmin.Y).Within(0.001f));
|
||||||
Assert.That(segmentVerts[v].vmin.Z, Is.EqualTo(VERTICES[i][v].vmin.Z).Within(0.001f));
|
Assert.That(segs[v].vmin.Z, Is.EqualTo(VERTICES[i][v].vmin.Z).Within(0.001f));
|
||||||
Assert.That(segmentVerts[v].vmax.X, Is.EqualTo(VERTICES[i][v].vmax.X).Within(0.001f));
|
Assert.That(segs[v].vmax.X, Is.EqualTo(VERTICES[i][v].vmax.X).Within(0.001f));
|
||||||
Assert.That(segmentVerts[v].vmax.Y, Is.EqualTo(VERTICES[i][v].vmax.Y).Within(0.001f));
|
Assert.That(segs[v].vmax.Y, Is.EqualTo(VERTICES[i][v].vmax.Y).Within(0.001f));
|
||||||
Assert.That(segmentVerts[v].vmax.Z, Is.EqualTo(VERTICES[i][v].vmax.Z).Within(0.001f));
|
Assert.That(segs[v].vmax.Z, Is.EqualTo(VERTICES[i][v].vmax.Z).Within(0.001f));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int v = 0; v < REFS[i].Length; v++)
|
for (int v = 0; v < REFS[i].Length; v++)
|
||||||
{
|
{
|
||||||
Assert.That(segmentRefs[v], Is.EqualTo(REFS[i][v]));
|
Assert.That(refs[v], Is.EqualTo(REFS[i][v]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -32,8 +33,7 @@ public class MeshDataReaderWriterTest
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp()
|
public void SetUp()
|
||||||
{
|
{
|
||||||
RecastTestMeshBuilder rcBuilder = new RecastTestMeshBuilder();
|
meshData = TestMeshDataFactory.Create();
|
||||||
meshData = rcBuilder.GetMeshData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -117,11 +117,8 @@ public class MeshDataReaderWriterTest
|
||||||
for (int i = 0; i < meshData.header.bvNodeCount; i++)
|
for (int i = 0; i < meshData.header.bvNodeCount; i++)
|
||||||
{
|
{
|
||||||
Assert.That(readData.bvTree[i].i, Is.EqualTo(meshData.bvTree[i].i));
|
Assert.That(readData.bvTree[i].i, Is.EqualTo(meshData.bvTree[i].i));
|
||||||
for (int j = 0; j < 3; j++)
|
Assert.That(readData.bvTree[i].bmin, Is.EqualTo(meshData.bvTree[i].bmin));
|
||||||
{
|
Assert.That(readData.bvTree[i].bmax, Is.EqualTo(meshData.bvTree[i].bmax));
|
||||||
Assert.That(readData.bvTree[i].bmin[j], Is.EqualTo(meshData.bvTree[i].bmin[j]));
|
|
||||||
Assert.That(readData.bvTree[i].bmax[j], Is.EqualTo(meshData.bvTree[i].bmax[j]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < meshData.header.offMeshConCount; i++)
|
for (int i = 0; i < meshData.header.offMeshConCount; i++)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -24,7 +25,6 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Test.Io;
|
namespace DotRecast.Detour.Test.Io;
|
||||||
|
|
||||||
|
|
||||||
public class MeshSetReaderTest
|
public class MeshSetReaderTest
|
||||||
{
|
{
|
||||||
private readonly DtMeshSetReader reader = new DtMeshSetReader();
|
private readonly DtMeshSetReader reader = new DtMeshSetReader();
|
||||||
|
@ -32,27 +32,35 @@ public class MeshSetReaderTest
|
||||||
[Test]
|
[Test]
|
||||||
public void TestNavmesh()
|
public void TestNavmesh()
|
||||||
{
|
{
|
||||||
byte[] @is = RcResources.Load("all_tiles_navmesh.bin");
|
byte[] @is = RcIO.ReadFileIfFound("all_tiles_navmesh.bin");
|
||||||
using var ms = new MemoryStream(@is);
|
using var ms = new MemoryStream(@is);
|
||||||
using var br = new BinaryReader(ms);
|
using var br = new BinaryReader(ms);
|
||||||
DtNavMesh mesh = reader.Read(br, 6);
|
DtNavMesh mesh = reader.Read(br, 6);
|
||||||
Assert.That(mesh.GetMaxTiles(), Is.EqualTo(128));
|
Assert.That(mesh.GetMaxTiles(), Is.EqualTo(128));
|
||||||
Assert.That(mesh.GetParams().maxPolys, Is.EqualTo(0x8000));
|
Assert.That(mesh.GetParams().maxPolys, Is.EqualTo(0x8000));
|
||||||
Assert.That(mesh.GetParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
|
Assert.That(mesh.GetParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
|
||||||
List<DtMeshTile> tiles = mesh.GetTilesAt(4, 7);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
const int MAX_NEIS = 32;
|
||||||
|
DtMeshTile[] tiles = new DtMeshTile[MAX_NEIS];
|
||||||
|
int nneis = 0;
|
||||||
|
|
||||||
|
nneis = mesh.GetTilesAt(4, 7, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(7));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(7));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(22 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(22 * 3));
|
||||||
tiles = mesh.GetTilesAt(1, 6);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
nneis = mesh.GetTilesAt(1, 6, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(7));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(7));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(26 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(26 * 3));
|
||||||
tiles = mesh.GetTilesAt(6, 2);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
nneis = mesh.GetTilesAt(6, 2, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(1));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(4 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(4 * 3));
|
||||||
tiles = mesh.GetTilesAt(7, 6);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
nneis = mesh.GetTilesAt(7, 6, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(8));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(8));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(24 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(24 * 3));
|
||||||
}
|
}
|
||||||
|
@ -60,7 +68,7 @@ public class MeshSetReaderTest
|
||||||
[Test]
|
[Test]
|
||||||
public void TestDungeon()
|
public void TestDungeon()
|
||||||
{
|
{
|
||||||
byte[] @is = RcResources.Load("dungeon_all_tiles_navmesh.bin");
|
byte[] @is = RcIO.ReadFileIfFound("dungeon_all_tiles_navmesh.bin");
|
||||||
using var ms = new MemoryStream(@is);
|
using var ms = new MemoryStream(@is);
|
||||||
using var br = new BinaryReader(ms);
|
using var br = new BinaryReader(ms);
|
||||||
|
|
||||||
|
@ -68,20 +76,28 @@ public class MeshSetReaderTest
|
||||||
Assert.That(mesh.GetMaxTiles(), Is.EqualTo(128));
|
Assert.That(mesh.GetMaxTiles(), Is.EqualTo(128));
|
||||||
Assert.That(mesh.GetParams().maxPolys, Is.EqualTo(0x8000));
|
Assert.That(mesh.GetParams().maxPolys, Is.EqualTo(0x8000));
|
||||||
Assert.That(mesh.GetParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
|
Assert.That(mesh.GetParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
|
||||||
List<DtMeshTile> tiles = mesh.GetTilesAt(6, 9);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
const int MAX_NEIS = 32;
|
||||||
|
DtMeshTile[] tiles = new DtMeshTile[MAX_NEIS];
|
||||||
|
int nneis = 0;
|
||||||
|
|
||||||
|
nneis = mesh.GetTilesAt(6, 9, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(7 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(7 * 3));
|
||||||
tiles = mesh.GetTilesAt(2, 9);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
nneis = mesh.GetTilesAt(2, 9, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(9 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(9 * 3));
|
||||||
tiles = mesh.GetTilesAt(4, 3);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
nneis = mesh.GetTilesAt(4, 3, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(3));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(3));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(6 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(6 * 3));
|
||||||
tiles = mesh.GetTilesAt(2, 8);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
nneis = mesh.GetTilesAt(2, 8, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(5));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(5));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(17 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(17 * 3));
|
||||||
}
|
}
|
||||||
|
@ -89,7 +105,7 @@ public class MeshSetReaderTest
|
||||||
[Test]
|
[Test]
|
||||||
public void TestDungeon32Bit()
|
public void TestDungeon32Bit()
|
||||||
{
|
{
|
||||||
byte[] @is = RcResources.Load("dungeon_all_tiles_navmesh_32bit.bin");
|
byte[] @is = RcIO.ReadFileIfFound("dungeon_all_tiles_navmesh_32bit.bin");
|
||||||
using var ms = new MemoryStream(@is);
|
using var ms = new MemoryStream(@is);
|
||||||
using var br = new BinaryReader(ms);
|
using var br = new BinaryReader(ms);
|
||||||
|
|
||||||
|
@ -97,20 +113,28 @@ public class MeshSetReaderTest
|
||||||
Assert.That(mesh.GetMaxTiles(), Is.EqualTo(128));
|
Assert.That(mesh.GetMaxTiles(), Is.EqualTo(128));
|
||||||
Assert.That(mesh.GetParams().maxPolys, Is.EqualTo(0x8000));
|
Assert.That(mesh.GetParams().maxPolys, Is.EqualTo(0x8000));
|
||||||
Assert.That(mesh.GetParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
|
Assert.That(mesh.GetParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
|
||||||
List<DtMeshTile> tiles = mesh.GetTilesAt(6, 9);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
const int MAX_NEIS = 32;
|
||||||
|
DtMeshTile[] tiles = new DtMeshTile[MAX_NEIS];
|
||||||
|
int nneis = 0;
|
||||||
|
|
||||||
|
nneis = mesh.GetTilesAt(6, 9, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(7 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(7 * 3));
|
||||||
tiles = mesh.GetTilesAt(2, 9);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
nneis = mesh.GetTilesAt(2, 9, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(9 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(9 * 3));
|
||||||
tiles = mesh.GetTilesAt(4, 3);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
nneis = mesh.GetTilesAt(4, 3, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(3));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(3));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(6 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(6 * 3));
|
||||||
tiles = mesh.GetTilesAt(2, 8);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
nneis = mesh.GetTilesAt(2, 8, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(5));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(5));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(17 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(17 * 3));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -28,7 +29,6 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Test.Io;
|
namespace DotRecast.Detour.Test.Io;
|
||||||
|
|
||||||
|
|
||||||
public class MeshSetReaderWriterTest
|
public class MeshSetReaderWriterTest
|
||||||
{
|
{
|
||||||
private readonly DtMeshSetWriter writer = new DtMeshSetWriter();
|
private readonly DtMeshSetWriter writer = new DtMeshSetWriter();
|
||||||
|
@ -66,11 +66,12 @@ public class MeshSetReaderWriterTest
|
||||||
header.option.maxTiles = m_maxTiles;
|
header.option.maxTiles = m_maxTiles;
|
||||||
header.option.maxPolys = m_maxPolysPerTile;
|
header.option.maxPolys = m_maxPolysPerTile;
|
||||||
header.numTiles = 0;
|
header.numTiles = 0;
|
||||||
DtNavMesh mesh = new DtNavMesh(header.option, 6);
|
DtNavMesh mesh = new DtNavMesh();
|
||||||
|
mesh.Init(header.option, 6);
|
||||||
|
|
||||||
RcVec3f bmin = geom.GetMeshBoundsMin();
|
RcVec3f bmin = geom.GetMeshBoundsMin();
|
||||||
RcVec3f bmax = geom.GetMeshBoundsMax();
|
RcVec3f bmax = geom.GetMeshBoundsMax();
|
||||||
RcCommons.CalcTileCount(bmin, bmax, m_cellSize, m_tileSize, m_tileSize, out var tw, out var th);
|
RcRecast.CalcTileCount(bmin, bmax, m_cellSize, m_tileSize, m_tileSize, out var tw, out var th);
|
||||||
for (int y = 0; y < th; ++y)
|
for (int y = 0; y < th; ++y)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < tw; ++x)
|
for (int x = 0; x < tw; ++x)
|
||||||
|
@ -92,7 +93,7 @@ public class MeshSetReaderWriterTest
|
||||||
if (data != null)
|
if (data != null)
|
||||||
{
|
{
|
||||||
mesh.RemoveTile(mesh.GetTileRefAt(x, y, 0));
|
mesh.RemoveTile(mesh.GetTileRefAt(x, y, 0));
|
||||||
mesh.AddTile(data, 0, 0);
|
mesh.AddTile(data, 0, 0, out _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,20 +108,28 @@ public class MeshSetReaderWriterTest
|
||||||
Assert.That(mesh.GetMaxTiles(), Is.EqualTo(128));
|
Assert.That(mesh.GetMaxTiles(), Is.EqualTo(128));
|
||||||
Assert.That(mesh.GetParams().maxPolys, Is.EqualTo(0x8000));
|
Assert.That(mesh.GetParams().maxPolys, Is.EqualTo(0x8000));
|
||||||
Assert.That(mesh.GetParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
|
Assert.That(mesh.GetParams().tileWidth, Is.EqualTo(9.6f).Within(0.001f));
|
||||||
List<DtMeshTile> tiles = mesh.GetTilesAt(6, 9);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
const int MAX_NEIS = 32;
|
||||||
|
DtMeshTile[] tiles = new DtMeshTile[MAX_NEIS];
|
||||||
|
int nneis = 0;
|
||||||
|
|
||||||
|
nneis = mesh.GetTilesAt(6, 9, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(7 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(7 * 3));
|
||||||
tiles = mesh.GetTilesAt(2, 9);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
nneis = mesh.GetTilesAt(2, 9, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(2));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(9 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(9 * 3));
|
||||||
tiles = mesh.GetTilesAt(4, 3);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
nneis = mesh.GetTilesAt(4, 3, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(3));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(3));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(6 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(6 * 3));
|
||||||
tiles = mesh.GetTilesAt(2, 8);
|
|
||||||
Assert.That(tiles.Count, Is.EqualTo(1));
|
nneis = mesh.GetTilesAt(2, 8, tiles, MAX_NEIS);
|
||||||
|
Assert.That(nneis, Is.EqualTo(1));
|
||||||
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(5));
|
Assert.That(tiles[0].data.polys.Length, Is.EqualTo(5));
|
||||||
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(17 * 3));
|
Assert.That(tiles[0].data.verts.Length, Is.EqualTo(17 * 3));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -16,13 +17,13 @@ freely, subject to the following restrictions:
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Test;
|
namespace DotRecast.Detour.Test;
|
||||||
|
|
||||||
|
|
||||||
public class MoveAlongSurfaceTest : AbstractDetourTest
|
public class MoveAlongSurfaceTest : AbstractDetourTest
|
||||||
{
|
{
|
||||||
private static readonly long[][] VISITED =
|
private static readonly long[][] VISITED =
|
||||||
|
@ -69,20 +70,21 @@ public class MoveAlongSurfaceTest : AbstractDetourTest
|
||||||
public void TestMoveAlongSurface()
|
public void TestMoveAlongSurface()
|
||||||
{
|
{
|
||||||
IDtQueryFilter filter = new DtQueryDefaultFilter();
|
IDtQueryFilter filter = new DtQueryDefaultFilter();
|
||||||
var visited = new List<long>();
|
const int MAX_VISITED = 32;
|
||||||
|
Span<long> visited = stackalloc long[MAX_VISITED];
|
||||||
for (int i = 0; i < startRefs.Length; i++)
|
for (int i = 0; i < startRefs.Length; i++)
|
||||||
{
|
{
|
||||||
long startRef = startRefs[i];
|
long startRef = startRefs[i];
|
||||||
RcVec3f startPos = startPoss[i];
|
RcVec3f startPos = startPoss[i];
|
||||||
RcVec3f endPos = endPoss[i];
|
RcVec3f endPos = endPoss[i];
|
||||||
var status = query.MoveAlongSurface(startRef, startPos, endPos, filter, out var result, ref visited);
|
var status = query.MoveAlongSurface(startRef, startPos, endPos, filter, out var result, visited, out var nvisited, MAX_VISITED);
|
||||||
Assert.That(status.Succeeded(), Is.True);
|
Assert.That(status.Succeeded(), Is.True);
|
||||||
|
|
||||||
Assert.That(result.X, Is.EqualTo(POSITION[i].X).Within(0.01f));
|
Assert.That(result.X, Is.EqualTo(POSITION[i].X).Within(0.01f));
|
||||||
Assert.That(result.Y, Is.EqualTo(POSITION[i].Y).Within(0.01f));
|
Assert.That(result.Y, Is.EqualTo(POSITION[i].Y).Within(0.01f));
|
||||||
Assert.That(result.Z, Is.EqualTo(POSITION[i].Z).Within(0.01f));
|
Assert.That(result.Z, Is.EqualTo(POSITION[i].Z).Within(0.01f));
|
||||||
|
|
||||||
Assert.That(visited.Count, Is.EqualTo(VISITED[i].Length));
|
Assert.That(nvisited, Is.EqualTo(VISITED[i].Length));
|
||||||
for (int j = 0; j < 3; j++)
|
for (int j = 0; j < 3; j++)
|
||||||
{
|
{
|
||||||
Assert.That(visited[j], Is.EqualTo(VISITED[i][j]));
|
Assert.That(visited[j], Is.EqualTo(VISITED[i][j]));
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -21,6 +22,7 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Test;
|
namespace DotRecast.Detour.Test;
|
||||||
|
|
||||||
|
using static DtDetour;
|
||||||
|
|
||||||
public class NavMeshBuilderTest
|
public class NavMeshBuilderTest
|
||||||
{
|
{
|
||||||
|
@ -29,7 +31,7 @@ public class NavMeshBuilderTest
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp()
|
public void SetUp()
|
||||||
{
|
{
|
||||||
nmd = new RecastTestMeshBuilder().GetMeshData();
|
nmd = TestMeshDataFactory.Create();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -52,12 +54,12 @@ public class NavMeshBuilderTest
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
Assert.That(RcVecUtils.Create(nmd.verts, 223 * 3 + (i * 3)), Is.EqualTo(nmd.offMeshCons[0].pos[i]));
|
Assert.That(RcVec.Create(nmd.verts, 223 * 3 + (i * 3)), Is.EqualTo(nmd.offMeshCons[0].pos[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.That(nmd.offMeshCons[0].rad, Is.EqualTo(0.1f));
|
Assert.That(nmd.offMeshCons[0].rad, Is.EqualTo(0.1f));
|
||||||
Assert.That(nmd.offMeshCons[0].poly, Is.EqualTo(118));
|
Assert.That(nmd.offMeshCons[0].poly, Is.EqualTo(118));
|
||||||
Assert.That(nmd.offMeshCons[0].flags, Is.EqualTo(DtNavMesh.DT_OFFMESH_CON_BIDIR));
|
Assert.That(nmd.offMeshCons[0].flags, Is.EqualTo(DT_OFFMESH_CON_BIDIR));
|
||||||
Assert.That(nmd.offMeshCons[0].side, Is.EqualTo(0xFF));
|
Assert.That(nmd.offMeshCons[0].side, Is.EqualTo(0xFF));
|
||||||
Assert.That(nmd.offMeshCons[0].userId, Is.EqualTo(0x4567));
|
Assert.That(nmd.offMeshCons[0].userId, Is.EqualTo(0x4567));
|
||||||
Assert.That(nmd.polys[118].vertCount, Is.EqualTo(2));
|
Assert.That(nmd.polys[118].vertCount, Is.EqualTo(2));
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
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
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2021 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2021 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -19,21 +20,22 @@ freely, subject to the following restrictions:
|
||||||
using System;
|
using System;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
|
||||||
namespace DotRecast.Detour.Test;
|
namespace DotRecast.Detour.Test;
|
||||||
|
|
||||||
|
|
||||||
public class RandomPointTest : AbstractDetourTest
|
public class RandomPointTest : AbstractDetourTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
|
[Repeat(10)]
|
||||||
public void TestRandom()
|
public void TestRandom()
|
||||||
{
|
{
|
||||||
RcRand f = new RcRand(1);
|
RcRand f = new RcRand(1);
|
||||||
IDtQueryFilter filter = new DtQueryDefaultFilter();
|
IDtQueryFilter filter = new DtQueryDefaultFilter();
|
||||||
for (int i = 0; i < 1000; i++)
|
|
||||||
|
var begin = RcFrequency.Ticks;
|
||||||
|
for (int i = 0; i < 10000; i++)
|
||||||
{
|
{
|
||||||
var status = query.FindRandomPoint(filter, f, out var randomRef, out var randomPt);
|
var status = query.FindRandomPoint(filter, f, out var randomRef, out var randomPt);
|
||||||
Assert.That(status.Succeeded(), Is.True);
|
Assert.That(status.Succeeded(), Is.True);
|
||||||
|
@ -55,6 +57,9 @@ public class RandomPointTest : AbstractDetourTest
|
||||||
Assert.That(randomPt.Z >= bmin[1], Is.True);
|
Assert.That(randomPt.Z >= bmin[1], Is.True);
|
||||||
Assert.That(randomPt.Z <= bmax[1], Is.True);
|
Assert.That(randomPt.Z <= bmax[1], Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ticks = RcFrequency.Ticks - begin;
|
||||||
|
Console.WriteLine($"RandomPointTest::TestRandom() - {(double)ticks / TimeSpan.TicksPerMillisecond} ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -103,7 +108,7 @@ public class RandomPointTest : AbstractDetourTest
|
||||||
var status = query.FindRandomPointWithinCircle(randomRef, randomPt, radius, filter, f, out var nextRandomRef, out var nextRandomPt);
|
var status = query.FindRandomPointWithinCircle(randomRef, randomPt, radius, filter, f, out var nextRandomRef, out var nextRandomPt);
|
||||||
Assert.That(status.Failed(), Is.False);
|
Assert.That(status.Failed(), Is.False);
|
||||||
|
|
||||||
float distance = RcVecUtils.Dist2D(randomPt, nextRandomPt);
|
float distance = RcVec.Dist2D(randomPt, nextRandomPt);
|
||||||
Assert.That(distance <= radius, Is.True);
|
Assert.That(distance <= radius, Is.True);
|
||||||
|
|
||||||
randomRef = nextRandomRef;
|
randomRef = nextRandomRef;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -16,15 +17,13 @@ freely, subject to the following restrictions:
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using DotRecast.Core.Numerics;
|
|
||||||
using DotRecast.Recast;
|
using DotRecast.Recast;
|
||||||
using DotRecast.Recast.Geom;
|
using DotRecast.Recast.Geom;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Test;
|
namespace DotRecast.Detour.Test;
|
||||||
|
|
||||||
public class RecastTestMeshBuilder
|
public static class TestMeshDataFactory
|
||||||
{
|
{
|
||||||
private readonly DtMeshData meshData;
|
|
||||||
private const float m_cellSize = 0.3f;
|
private const float m_cellSize = 0.3f;
|
||||||
private const float m_cellHeight = 0.2f;
|
private const float m_cellHeight = 0.2f;
|
||||||
private const float m_agentHeight = 2.0f;
|
private const float m_agentHeight = 2.0f;
|
||||||
|
@ -39,27 +38,24 @@ public class RecastTestMeshBuilder
|
||||||
private const float m_detailSampleDist = 6.0f;
|
private const float m_detailSampleDist = 6.0f;
|
||||||
private const float m_detailSampleMaxError = 1.0f;
|
private const float m_detailSampleMaxError = 1.0f;
|
||||||
|
|
||||||
public RecastTestMeshBuilder()
|
public static DtMeshData Create()
|
||||||
: this(SimpleInputGeomProvider.LoadFile("dungeon.obj"),
|
|
||||||
RcPartition.WATERSHED,
|
|
||||||
m_cellSize, m_cellHeight,
|
|
||||||
m_agentMaxSlope, m_agentHeight, m_agentRadius, m_agentMaxClimb,
|
|
||||||
m_regionMinSize, m_regionMergeSize,
|
|
||||||
m_edgeMaxLen, m_edgeMaxError,
|
|
||||||
m_vertsPerPoly,
|
|
||||||
m_detailSampleDist, m_detailSampleMaxError)
|
|
||||||
{
|
{
|
||||||
}
|
IInputGeomProvider geom = SimpleInputGeomProvider.LoadFile("dungeon.obj");
|
||||||
|
RcPartition partition = RcPartition.WATERSHED;
|
||||||
|
float cellSize = m_cellSize;
|
||||||
|
float cellHeight = m_cellHeight;
|
||||||
|
float agentMaxSlope = m_agentMaxSlope;
|
||||||
|
float agentHeight = m_agentHeight;
|
||||||
|
float agentRadius = m_agentRadius;
|
||||||
|
float agentMaxClimb = m_agentMaxClimb;
|
||||||
|
int regionMinSize = m_regionMinSize;
|
||||||
|
int regionMergeSize = m_regionMergeSize;
|
||||||
|
float edgeMaxLen = m_edgeMaxLen;
|
||||||
|
float edgeMaxError = m_edgeMaxError;
|
||||||
|
int vertsPerPoly = m_vertsPerPoly;
|
||||||
|
float detailSampleDist = m_detailSampleDist;
|
||||||
|
float detailSampleMaxError = m_detailSampleMaxError;
|
||||||
|
|
||||||
public RecastTestMeshBuilder(IInputGeomProvider geom,
|
|
||||||
RcPartition partition,
|
|
||||||
float cellSize, float cellHeight,
|
|
||||||
float agentMaxSlope, float agentHeight, float agentRadius, float agentMaxClimb,
|
|
||||||
int regionMinSize, int regionMergeSize,
|
|
||||||
float edgeMaxLen, float edgeMaxError,
|
|
||||||
int vertsPerPoly,
|
|
||||||
float detailSampleDist, float detailSampleMaxError)
|
|
||||||
{
|
|
||||||
RcConfig cfg = new RcConfig(
|
RcConfig cfg = new RcConfig(
|
||||||
partition,
|
partition,
|
||||||
cellSize, cellHeight,
|
cellSize, cellHeight,
|
||||||
|
@ -73,31 +69,31 @@ public class RecastTestMeshBuilder
|
||||||
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
|
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
|
||||||
RcBuilder rcBuilder = new RcBuilder();
|
RcBuilder rcBuilder = new RcBuilder();
|
||||||
RcBuilderResult rcResult = rcBuilder.Build(geom, bcfg, false);
|
RcBuilderResult rcResult = rcBuilder.Build(geom, bcfg, false);
|
||||||
RcPolyMesh m_pmesh = rcResult.Mesh;
|
RcPolyMesh pmesh = rcResult.Mesh;
|
||||||
for (int i = 0; i < m_pmesh.npolys; ++i)
|
for (int i = 0; i < pmesh.npolys; ++i)
|
||||||
{
|
{
|
||||||
m_pmesh.flags[i] = 1;
|
pmesh.flags[i] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
RcPolyMeshDetail m_dmesh = rcResult.MeshDetail;
|
RcPolyMeshDetail dmesh = rcResult.MeshDetail;
|
||||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||||
option.verts = m_pmesh.verts;
|
option.verts = pmesh.verts;
|
||||||
option.vertCount = m_pmesh.nverts;
|
option.vertCount = pmesh.nverts;
|
||||||
option.polys = m_pmesh.polys;
|
option.polys = pmesh.polys;
|
||||||
option.polyAreas = m_pmesh.areas;
|
option.polyAreas = pmesh.areas;
|
||||||
option.polyFlags = m_pmesh.flags;
|
option.polyFlags = pmesh.flags;
|
||||||
option.polyCount = m_pmesh.npolys;
|
option.polyCount = pmesh.npolys;
|
||||||
option.nvp = m_pmesh.nvp;
|
option.nvp = pmesh.nvp;
|
||||||
option.detailMeshes = m_dmesh.meshes;
|
option.detailMeshes = dmesh.meshes;
|
||||||
option.detailVerts = m_dmesh.verts;
|
option.detailVerts = dmesh.verts;
|
||||||
option.detailVertsCount = m_dmesh.nverts;
|
option.detailVertsCount = dmesh.nverts;
|
||||||
option.detailTris = m_dmesh.tris;
|
option.detailTris = dmesh.tris;
|
||||||
option.detailTriCount = m_dmesh.ntris;
|
option.detailTriCount = dmesh.ntris;
|
||||||
option.walkableHeight = agentHeight;
|
option.walkableHeight = agentHeight;
|
||||||
option.walkableRadius = agentRadius;
|
option.walkableRadius = agentRadius;
|
||||||
option.walkableClimb = agentMaxClimb;
|
option.walkableClimb = agentMaxClimb;
|
||||||
option.bmin = m_pmesh.bmin;
|
option.bmin = pmesh.bmin;
|
||||||
option.bmax = m_pmesh.bmax;
|
option.bmax = pmesh.bmax;
|
||||||
option.cs = cellSize;
|
option.cs = cellSize;
|
||||||
option.ch = cellHeight;
|
option.ch = cellHeight;
|
||||||
option.buildBvTree = true;
|
option.buildBvTree = true;
|
||||||
|
@ -120,11 +116,8 @@ public class RecastTestMeshBuilder
|
||||||
option.offMeshConUserID = new int[1];
|
option.offMeshConUserID = new int[1];
|
||||||
option.offMeshConUserID[0] = 0x4567;
|
option.offMeshConUserID[0] = 0x4567;
|
||||||
option.offMeshConCount = 1;
|
option.offMeshConCount = 1;
|
||||||
meshData = DtNavMeshBuilder.CreateNavMeshData(option);
|
var meshData = DtNavMeshBuilder.CreateNavMeshData(option);
|
||||||
}
|
|
||||||
|
|
||||||
public DtMeshData GetMeshData()
|
|
||||||
{
|
|
||||||
return meshData;
|
return meshData;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -17,7 +18,6 @@ freely, subject to the following restrictions:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core.Numerics;
|
|
||||||
using DotRecast.Recast;
|
using DotRecast.Recast;
|
||||||
using DotRecast.Recast.Geom;
|
using DotRecast.Recast.Geom;
|
||||||
|
|
||||||
|
@ -64,7 +64,8 @@ public class TestTiledNavMeshBuilder
|
||||||
navMeshParams.tileHeight = tileSize * cellSize;
|
navMeshParams.tileHeight = tileSize * cellSize;
|
||||||
navMeshParams.maxTiles = 128;
|
navMeshParams.maxTiles = 128;
|
||||||
navMeshParams.maxPolys = 32768;
|
navMeshParams.maxPolys = 32768;
|
||||||
navMesh = new DtNavMesh(navMeshParams, 6);
|
navMesh = new DtNavMesh();
|
||||||
|
navMesh.Init(navMeshParams, 6);
|
||||||
|
|
||||||
// Build all tiles
|
// Build all tiles
|
||||||
RcConfig cfg = new RcConfig(true, tileSize, tileSize, RcConfig.CalcBorder(agentRadius, cellSize),
|
RcConfig cfg = new RcConfig(true, tileSize, tileSize, RcConfig.CalcBorder(agentRadius, cellSize),
|
||||||
|
@ -119,7 +120,7 @@ public class TestTiledNavMeshBuilder
|
||||||
option.tileX = result.TileX;
|
option.tileX = result.TileX;
|
||||||
option.tileZ = result.TileZ;
|
option.tileZ = result.TileZ;
|
||||||
option.buildBvTree = true;
|
option.buildBvTree = true;
|
||||||
navMesh.AddTile(DtNavMeshBuilder.CreateNavMeshData(option), 0, 0);
|
navMesh.AddTile(Detour.DtNavMeshBuilder.CreateNavMeshData(option), 0, 0, out _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -44,7 +44,7 @@ public class AbstractTileCacheTest
|
||||||
public DtTileCache GetTileCache(IInputGeomProvider geom, RcByteOrder order, bool cCompatibility)
|
public DtTileCache GetTileCache(IInputGeomProvider geom, RcByteOrder order, bool cCompatibility)
|
||||||
{
|
{
|
||||||
DtTileCacheParams option = new DtTileCacheParams();
|
DtTileCacheParams option = new DtTileCacheParams();
|
||||||
RcCommons.CalcTileCount(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), m_cellSize, m_tileSize, m_tileSize, out var tw, out var th);
|
RcRecast.CalcTileCount(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), m_cellSize, m_tileSize, m_tileSize, out var tw, out var th);
|
||||||
option.ch = m_cellHeight;
|
option.ch = m_cellHeight;
|
||||||
option.cs = m_cellSize;
|
option.cs = m_cellSize;
|
||||||
option.orig = geom.GetMeshBoundsMin();
|
option.orig = geom.GetMeshBoundsMin();
|
||||||
|
@ -64,7 +64,8 @@ public class AbstractTileCacheTest
|
||||||
navMeshParams.maxTiles = 256;
|
navMeshParams.maxTiles = 256;
|
||||||
navMeshParams.maxPolys = 16384;
|
navMeshParams.maxPolys = 16384;
|
||||||
|
|
||||||
var navMesh = new DtNavMesh(navMeshParams, 6);
|
var navMesh = new DtNavMesh();
|
||||||
|
navMesh.Init(navMeshParams, 6);
|
||||||
var comp = DtTileCacheCompressorFactory.Shared.Create(cCompatibility ? 0 : 1);
|
var comp = DtTileCacheCompressorFactory.Shared.Create(cCompatibility ? 0 : 1);
|
||||||
var storageParams = new DtTileCacheStorageParams(order, cCompatibility);
|
var storageParams = new DtTileCacheStorageParams(order, cCompatibility);
|
||||||
var process = new TestTileCacheMeshProcess();
|
var process = new TestTileCacheMeshProcess();
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
<PackageReference Include="Moq" Version="4.20.70" />
|
<PackageReference Include="Moq" Version="4.20.72" />
|
||||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
<PackageReference Include="NUnit" Version="4.2.2" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.2.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -35,7 +35,7 @@ public class TileCacheReaderTest
|
||||||
[Test]
|
[Test]
|
||||||
public void TestNavmesh()
|
public void TestNavmesh()
|
||||||
{
|
{
|
||||||
using var ms = new MemoryStream(RcResources.Load("all_tiles_tilecache.bin"));
|
using var ms = new MemoryStream(RcIO.ReadFileIfFound("all_tiles_tilecache.bin"));
|
||||||
using var br = new BinaryReader(ms);
|
using var br = new BinaryReader(ms);
|
||||||
DtTileCache tc = reader.Read(br, 6, null);
|
DtTileCache tc = reader.Read(br, 6, null);
|
||||||
Assert.That(tc.GetNavMesh().GetMaxTiles(), Is.EqualTo(256));
|
Assert.That(tc.GetNavMesh().GetMaxTiles(), Is.EqualTo(256));
|
||||||
|
@ -133,7 +133,7 @@ public class TileCacheReaderTest
|
||||||
[Test]
|
[Test]
|
||||||
public void TestDungeon()
|
public void TestDungeon()
|
||||||
{
|
{
|
||||||
using var ms = new MemoryStream(RcResources.Load("dungeon_all_tiles_tilecache.bin"));
|
using var ms = new MemoryStream(RcIO.ReadFileIfFound("dungeon_all_tiles_tilecache.bin"));
|
||||||
using var br = new BinaryReader(ms);
|
using var br = new BinaryReader(ms);
|
||||||
DtTileCache tc = reader.Read(br, 6, null);
|
DtTileCache tc = reader.Read(br, 6, null);
|
||||||
Assert.That(tc.GetNavMesh().GetMaxTiles(), Is.EqualTo(256));
|
Assert.That(tc.GetNavMesh().GetMaxTiles(), Is.EqualTo(256));
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +26,6 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache.Test;
|
namespace DotRecast.Detour.TileCache.Test;
|
||||||
|
|
||||||
|
|
||||||
public class TempObstaclesTest : AbstractTileCacheTest
|
public class TempObstaclesTest : AbstractTileCacheTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -43,21 +42,29 @@ public class TempObstaclesTest : AbstractTileCacheTest
|
||||||
tc.BuildNavMeshTile(refs);
|
tc.BuildNavMeshTile(refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DtMeshTile> tiles = tc.GetNavMesh().GetTilesAt(1, 4);
|
const int MAX_NEIS = 32;
|
||||||
|
DtMeshTile[] tiles = new DtMeshTile[MAX_NEIS];
|
||||||
|
int nneis = 0;
|
||||||
|
|
||||||
|
nneis = tc.GetNavMesh().GetTilesAt(1, 4, tiles, MAX_NEIS);
|
||||||
DtMeshTile tile = tiles[0];
|
DtMeshTile tile = tiles[0];
|
||||||
Assert.That(tile.data.header.vertCount, Is.EqualTo(16));
|
Assert.That(tile.data.header.vertCount, Is.EqualTo(16));
|
||||||
Assert.That(tile.data.header.polyCount, Is.EqualTo(6));
|
Assert.That(tile.data.header.polyCount, Is.EqualTo(6));
|
||||||
|
|
||||||
long o = tc.AddObstacle(new RcVec3f(-1.815208f, 9.998184f, -20.307983f), 1f, 2f);
|
long o = tc.AddObstacle(new RcVec3f(-1.815208f, 9.998184f, -20.307983f), 1f, 2f);
|
||||||
bool upToDate = tc.Update();
|
bool upToDate = tc.Update();
|
||||||
Assert.That(upToDate, Is.True);
|
Assert.That(upToDate, Is.True);
|
||||||
tiles = tc.GetNavMesh().GetTilesAt(1, 4);
|
|
||||||
|
nneis = tc.GetNavMesh().GetTilesAt(1, 4, tiles, MAX_NEIS);
|
||||||
tile = tiles[0];
|
tile = tiles[0];
|
||||||
Assert.That(tile.data.header.vertCount, Is.EqualTo(22));
|
Assert.That(tile.data.header.vertCount, Is.EqualTo(22));
|
||||||
Assert.That(tile.data.header.polyCount, Is.EqualTo(11));
|
Assert.That(tile.data.header.polyCount, Is.EqualTo(11));
|
||||||
|
|
||||||
tc.RemoveObstacle(o);
|
tc.RemoveObstacle(o);
|
||||||
upToDate = tc.Update();
|
upToDate = tc.Update();
|
||||||
Assert.That(upToDate, Is.True);
|
Assert.That(upToDate, Is.True);
|
||||||
tiles = tc.GetNavMesh().GetTilesAt(1, 4);
|
|
||||||
|
nneis = tc.GetNavMesh().GetTilesAt(1, 4, tiles, MAX_NEIS);
|
||||||
tile = tiles[0];
|
tile = tiles[0];
|
||||||
Assert.That(tile.data.header.vertCount, Is.EqualTo(16));
|
Assert.That(tile.data.header.vertCount, Is.EqualTo(16));
|
||||||
Assert.That(tile.data.header.polyCount, Is.EqualTo(6));
|
Assert.That(tile.data.header.polyCount, Is.EqualTo(6));
|
||||||
|
@ -77,24 +84,32 @@ public class TempObstaclesTest : AbstractTileCacheTest
|
||||||
tc.BuildNavMeshTile(refs);
|
tc.BuildNavMeshTile(refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DtMeshTile> tiles = tc.GetNavMesh().GetTilesAt(1, 4);
|
const int MAX_NEIS = 32;
|
||||||
|
DtMeshTile[] tiles = new DtMeshTile[MAX_NEIS];
|
||||||
|
int nneis = 0;
|
||||||
|
|
||||||
|
nneis = tc.GetNavMesh().GetTilesAt(1, 4, tiles, MAX_NEIS);
|
||||||
DtMeshTile tile = tiles[0];
|
DtMeshTile tile = tiles[0];
|
||||||
Assert.That(tile.data.header.vertCount, Is.EqualTo(16));
|
Assert.That(tile.data.header.vertCount, Is.EqualTo(16));
|
||||||
Assert.That(tile.data.header.polyCount, Is.EqualTo(6));
|
Assert.That(tile.data.header.polyCount, Is.EqualTo(6));
|
||||||
|
|
||||||
long o = tc.AddBoxObstacle(
|
long o = tc.AddBoxObstacle(
|
||||||
new RcVec3f(-2.315208f, 9.998184f, -20.807983f),
|
new RcVec3f(-2.315208f, 9.998184f, -20.807983f),
|
||||||
new RcVec3f(-1.315208f, 11.998184f, -19.807983f)
|
new RcVec3f(-1.315208f, 11.998184f, -19.807983f)
|
||||||
);
|
);
|
||||||
bool upToDate = tc.Update();
|
bool upToDate = tc.Update();
|
||||||
Assert.That(upToDate, Is.True);
|
Assert.That(upToDate, Is.True);
|
||||||
tiles = tc.GetNavMesh().GetTilesAt(1, 4);
|
|
||||||
|
nneis = tc.GetNavMesh().GetTilesAt(1, 4, tiles, MAX_NEIS);
|
||||||
tile = tiles[0];
|
tile = tiles[0];
|
||||||
Assert.That(tile.data.header.vertCount, Is.EqualTo(22));
|
Assert.That(tile.data.header.vertCount, Is.EqualTo(22));
|
||||||
Assert.That(tile.data.header.polyCount, Is.EqualTo(11));
|
Assert.That(tile.data.header.polyCount, Is.EqualTo(11));
|
||||||
|
|
||||||
tc.RemoveObstacle(o);
|
tc.RemoveObstacle(o);
|
||||||
upToDate = tc.Update();
|
upToDate = tc.Update();
|
||||||
Assert.That(upToDate, Is.True);
|
Assert.That(upToDate, Is.True);
|
||||||
tiles = tc.GetNavMesh().GetTilesAt(1, 4);
|
|
||||||
|
nneis = tc.GetNavMesh().GetTilesAt(1, 4, tiles, MAX_NEIS);
|
||||||
tile = tiles[0];
|
tile = tiles[0];
|
||||||
Assert.That(tile.data.header.vertCount, Is.EqualTo(16));
|
Assert.That(tile.data.header.vertCount, Is.EqualTo(16));
|
||||||
Assert.That(tile.data.header.polyCount, Is.EqualTo(6));
|
Assert.That(tile.data.header.polyCount, Is.EqualTo(6));
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using DotRecast.Recast.Geom;
|
using DotRecast.Recast.Geom;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache.Test;
|
namespace DotRecast.Detour.TileCache.Test;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -73,7 +73,7 @@ public class TestTileLayerBuilder : DtTileCacheLayerBuilder
|
||||||
|
|
||||||
RcVec3f bmin = geom.GetMeshBoundsMin();
|
RcVec3f bmin = geom.GetMeshBoundsMin();
|
||||||
RcVec3f bmax = geom.GetMeshBoundsMax();
|
RcVec3f bmax = geom.GetMeshBoundsMax();
|
||||||
RcCommons.CalcTileCount(bmin, bmax, CellSize, m_tileSize, m_tileSize, out tw, out th);
|
RcRecast.CalcTileCount(bmin, bmax, CellSize, m_tileSize, m_tileSize, out tw, out th);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<byte[]> Build(RcByteOrder order, bool cCompatibility, int threads)
|
public List<byte[]> Build(RcByteOrder order, bool cCompatibility, int threads)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -18,6 +18,7 @@ freely, subject to the following restrictions:
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
|
@ -29,7 +30,6 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache.Test;
|
namespace DotRecast.Detour.TileCache.Test;
|
||||||
|
|
||||||
|
|
||||||
public class TileCacheFindPathTest : AbstractTileCacheTest
|
public class TileCacheFindPathTest : AbstractTileCacheTest
|
||||||
{
|
{
|
||||||
private readonly RcVec3f start = new RcVec3f(39.44734f, 9.998177f, -0.784811f);
|
private readonly RcVec3f start = new RcVec3f(39.44734f, 9.998177f, -0.784811f);
|
||||||
|
@ -39,7 +39,7 @@ public class TileCacheFindPathTest : AbstractTileCacheTest
|
||||||
|
|
||||||
public TileCacheFindPathTest()
|
public TileCacheFindPathTest()
|
||||||
{
|
{
|
||||||
using var msr = new MemoryStream(RcResources.Load("dungeon_all_tiles_tilecache.bin"));
|
using var msr = new MemoryStream(RcIO.ReadFileIfFound("dungeon_all_tiles_tilecache.bin"));
|
||||||
using var br = new BinaryReader(msr);
|
using var br = new BinaryReader(msr);
|
||||||
DtTileCache tcC = new DtTileCacheReader(DtTileCacheCompressorFactory.Shared).Read(br, 6, new TestTileCacheMeshProcess());
|
DtTileCache tcC = new DtTileCacheReader(DtTileCacheCompressorFactory.Shared).Read(br, 6, new TestTileCacheMeshProcess());
|
||||||
navmesh = tcC.GetNavMesh();
|
navmesh = tcC.GetNavMesh();
|
||||||
|
@ -56,11 +56,11 @@ public class TileCacheFindPathTest : AbstractTileCacheTest
|
||||||
|
|
||||||
var path = new List<long>();
|
var path = new List<long>();
|
||||||
var status = query.FindPath(startRef, endRef, startPos, endPos, filter, ref path, DtFindPathOption.NoOption);
|
var status = query.FindPath(startRef, endRef, startPos, endPos, filter, ref path, DtFindPathOption.NoOption);
|
||||||
int maxStraightPath = 256;
|
const int maxStraightPath = 256;
|
||||||
int options = 0;
|
int options = 0;
|
||||||
|
|
||||||
var pathStr = new List<DtStraightPath>();
|
Span<DtStraightPath> pathStr = stackalloc DtStraightPath[maxStraightPath];
|
||||||
query.FindStraightPath(startPos, endPos, path, ref pathStr, maxStraightPath, options);
|
query.FindStraightPath(startPos, endPos, path, path.Count, pathStr, out var npathStr, maxStraightPath, options);
|
||||||
Assert.That(pathStr.Count, Is.EqualTo(8));
|
Assert.That(npathStr, Is.EqualTo(8));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||||
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023-2024 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,4 +1,4 @@
|
||||||
using DotRecast.Detour.TileCache.Io.Compress;
|
using DotRecast.Detour.TileCache.Io.Compress;
|
||||||
using DotRecast.Detour.TileCache.Test.Io;
|
using DotRecast.Detour.TileCache.Test.Io;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||||
<PackageReference Include="Moq" Version="4.20.70" />
|
<PackageReference Include="Moq" Version="4.20.72" />
|
||||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
<PackageReference Include="NUnit" Version="4.2.2" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.2.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -24,9 +25,6 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Test;
|
namespace DotRecast.Recast.Test;
|
||||||
|
|
||||||
using static RcConstants;
|
|
||||||
|
|
||||||
|
|
||||||
public class RecastLayersTest
|
public class RecastLayersTest
|
||||||
{
|
{
|
||||||
private const float m_cellSize = 0.3f;
|
private const float m_cellSize = 0.3f;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -25,10 +26,9 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Test;
|
namespace DotRecast.Recast.Test;
|
||||||
|
|
||||||
using static RcConstants;
|
using static RcRecast;
|
||||||
using static RcAreas;
|
using static RcAreas;
|
||||||
|
|
||||||
|
|
||||||
public class RecastSoloMeshTest
|
public class RecastSoloMeshTest
|
||||||
{
|
{
|
||||||
private const float m_cellSize = 0.3f;
|
private const float m_cellSize = 0.3f;
|
||||||
|
@ -139,7 +139,7 @@ public class RecastSoloMeshTest
|
||||||
// Find triangles which are walkable based on their slope and rasterize them.
|
// Find triangles which are walkable based on their slope and rasterize them.
|
||||||
// If your input data is multiple meshes, you can transform them here, calculate
|
// If your input data is multiple meshes, you can transform them here, calculate
|
||||||
// the are type for each of the meshes and rasterize them.
|
// the are type for each of the meshes and rasterize them.
|
||||||
int[] m_triareas = RcCommons.MarkWalkableTriangles(m_ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
|
int[] m_triareas = RcRecast.MarkWalkableTriangles(m_ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
|
||||||
RcRasterizations.RasterizeTriangles(m_ctx, verts, tris, m_triareas, ntris, m_solid, cfg.WalkableClimb);
|
RcRasterizations.RasterizeTriangles(m_ctx, verts, tris, m_triareas, ntris, m_solid, cfg.WalkableClimb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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
|
||||||
|
@ -21,8 +22,7 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Test;
|
namespace DotRecast.Recast.Test;
|
||||||
|
|
||||||
using static RcConstants;
|
using static RcRecast;
|
||||||
|
|
||||||
|
|
||||||
public class RecastTest
|
public class RecastTest
|
||||||
{
|
{
|
||||||
|
@ -39,18 +39,18 @@ public class RecastTest
|
||||||
RcContext ctx = new RcContext();
|
RcContext ctx = new RcContext();
|
||||||
{
|
{
|
||||||
int[] areas = { 42 };
|
int[] areas = { 42 };
|
||||||
RcCommons.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, unwalkable_tri, nt, areas);
|
RcRecast.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, unwalkable_tri, nt, areas);
|
||||||
Assert.That(areas[0], Is.EqualTo(RC_NULL_AREA), "Sets area ID of unwalkable triangle to RC_NULL_AREA");
|
Assert.That(areas[0], Is.EqualTo(RC_NULL_AREA), "Sets area ID of unwalkable triangle to RC_NULL_AREA");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
int[] areas = { 42 };
|
int[] areas = { 42 };
|
||||||
RcCommons.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
|
RcRecast.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
|
||||||
Assert.That(areas[0], Is.EqualTo(42), "Does not modify walkable triangle aread ID's");
|
Assert.That(areas[0], Is.EqualTo(42), "Does not modify walkable triangle aread ID's");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
int[] areas = { 42 };
|
int[] areas = { 42 };
|
||||||
walkableSlopeAngle = 0;
|
walkableSlopeAngle = 0;
|
||||||
RcCommons.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
|
RcRecast.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
|
||||||
Assert.That(areas[0], Is.EqualTo(RC_NULL_AREA), "Slopes equal to the max slope are considered unwalkable.");
|
Assert.That(areas[0], Is.EqualTo(RC_NULL_AREA), "Slopes equal to the max slope are considered unwalkable.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
recast4j Copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
||||||
|
DotRecast Copyright (c) 2023-2024 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,15 @@
|
||||||
|
namespace DotRecast.Tool.PublishToUniRecast;
|
||||||
|
|
||||||
|
public class CsProj
|
||||||
|
{
|
||||||
|
public readonly string RootPath;
|
||||||
|
public readonly string Name;
|
||||||
|
public readonly string TargetPath;
|
||||||
|
|
||||||
|
public CsProj(string rootPath, string name, string targetPath)
|
||||||
|
{
|
||||||
|
RootPath = rootPath;
|
||||||
|
Name = name;
|
||||||
|
TargetPath = targetPath;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,169 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace DotRecast.Tool.PublishToUniRecast;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var source = SearchDirectory("DotRecast");
|
||||||
|
var destination = SearchDirectory("UniRecast");
|
||||||
|
|
||||||
|
if (!Directory.Exists(source))
|
||||||
|
{
|
||||||
|
throw new Exception("not found source directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(destination))
|
||||||
|
{
|
||||||
|
throw new Exception("not found destination directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
var ignorePaths = ImmutableArray.Create("bin", "obj");
|
||||||
|
var projs = ImmutableArray.Create(
|
||||||
|
// src
|
||||||
|
new CsProj("src", "DotRecast.Core", "Runtime"),
|
||||||
|
new CsProj("src", "DotRecast.Recast", "Runtime"),
|
||||||
|
new CsProj("src", "DotRecast.Detour", "Runtime"),
|
||||||
|
new CsProj("src", "DotRecast.Detour.Crowd", "Runtime"),
|
||||||
|
new CsProj("src", "DotRecast.Detour.Dynamic", "Runtime"),
|
||||||
|
new CsProj("src", "DotRecast.Detour.Extras", "Runtime"),
|
||||||
|
new CsProj("src", "DotRecast.Detour.TileCache", "Runtime"),
|
||||||
|
new CsProj("src", "DotRecast.Recast.Toolset", "Runtime")
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var proj in projs)
|
||||||
|
{
|
||||||
|
var sourcePath = Path.Combine(source, proj.RootPath, $"{proj.Name}");
|
||||||
|
var destPath = Path.Combine(destination, $"{proj.TargetPath}", $"{proj.Name}");
|
||||||
|
|
||||||
|
SyncFiles(sourcePath, destPath, ignorePaths, "*.cs");
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 몇몇 필요한 리소스 복사 하기
|
||||||
|
// string destResourcePath = destDotRecast + "/resources";
|
||||||
|
// if (!Directory.Exists(destResourcePath))
|
||||||
|
// {
|
||||||
|
// Directory.CreateDirectory(destResourcePath);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// string sourceResourcePath = Path.Combine(dotRecastPath, "resources/nav_test.obj");
|
||||||
|
// File.Copy(sourceResourcePath, destResourcePath + "/nav_test.obj", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string SearchPath(string searchPath, int depth, out bool isDir)
|
||||||
|
{
|
||||||
|
isDir = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < depth; ++i)
|
||||||
|
{
|
||||||
|
var relativePath = string.Join("", Enumerable.Range(0, i).Select(x => "../"));
|
||||||
|
var searchingPath = Path.Combine(relativePath, searchPath);
|
||||||
|
var fullSearchingPath = Path.GetFullPath(searchingPath);
|
||||||
|
|
||||||
|
if (File.Exists(fullSearchingPath))
|
||||||
|
{
|
||||||
|
return fullSearchingPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Directory.Exists(fullSearchingPath))
|
||||||
|
{
|
||||||
|
isDir = true;
|
||||||
|
return fullSearchingPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only directory
|
||||||
|
public static string SearchDirectory(string dirname, int depth = 10)
|
||||||
|
{
|
||||||
|
var searchingPath = SearchPath(dirname, depth, out var isDir);
|
||||||
|
if (isDir)
|
||||||
|
{
|
||||||
|
return searchingPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
var path = Path.GetDirectoryName(searchingPath) ?? string.Empty;
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string SearchFile(string filename, int depth = 10)
|
||||||
|
{
|
||||||
|
var searchingPath = SearchPath(filename, depth, out var isDir);
|
||||||
|
if (!isDir)
|
||||||
|
{
|
||||||
|
return searchingPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SyncFiles(string srcRootPath, string dstRootPath, IList<string> ignoreFolders, string searchPattern = "*")
|
||||||
|
{
|
||||||
|
// 끝에서부터 이그노어 폴더일 경우 패스
|
||||||
|
var destLastFolderName = Path.GetFileName(dstRootPath);
|
||||||
|
if (ignoreFolders.Any(x => x == destLastFolderName))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!Directory.Exists(dstRootPath))
|
||||||
|
Directory.CreateDirectory(dstRootPath);
|
||||||
|
|
||||||
|
// 소스파일 추출
|
||||||
|
var sourceFiles = Directory.GetFiles(srcRootPath, searchPattern).ToList();
|
||||||
|
var sourceFolders = Directory.GetDirectories(srcRootPath)
|
||||||
|
.Select(x => new DirectoryInfo(x))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// 대상 파일 추출
|
||||||
|
var destinationFiles = Directory.GetFiles(dstRootPath, searchPattern).ToList();
|
||||||
|
var destinationFolders = Directory.GetDirectories(dstRootPath)
|
||||||
|
.Select(x => new DirectoryInfo(x))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// 대상에 파일이 있는데, 소스에 없을 경우, 대상 파일을 삭제 한다.
|
||||||
|
foreach (var destinationFile in destinationFiles)
|
||||||
|
{
|
||||||
|
var destName = Path.GetFileName(destinationFile);
|
||||||
|
var found = sourceFiles.Any(x => Path.GetFileName(x) == destName);
|
||||||
|
if (found)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
File.Delete(destinationFile);
|
||||||
|
Console.WriteLine($"delete file - {destinationFile}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 대상에 폴더가 있는데, 소스에 없을 경우, 대상 폴더를 삭제 한다.
|
||||||
|
foreach (var destinationFolder in destinationFolders)
|
||||||
|
{
|
||||||
|
var found = sourceFolders.Any(sourceFolder => sourceFolder.Name == destinationFolder.Name);
|
||||||
|
if (found)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Directory.Delete(destinationFolder.FullName, true);
|
||||||
|
Console.WriteLine($"delete folder - {destinationFolder.FullName}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 소스 파일을 복사 한다.
|
||||||
|
foreach (var sourceFile in sourceFiles)
|
||||||
|
{
|
||||||
|
var name = Path.GetFileName(sourceFile);
|
||||||
|
var dest = Path.Combine(dstRootPath, name);
|
||||||
|
File.Copy(sourceFile, dest, true);
|
||||||
|
Console.WriteLine($"copy - {sourceFile} => {dest}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 대상 폴더를 복사 한다
|
||||||
|
foreach (var sourceFolder in sourceFolders)
|
||||||
|
{
|
||||||
|
var dest = Path.Combine(dstRootPath, sourceFolder.Name);
|
||||||
|
SyncFiles(sourceFolder.FullName, dest, ignoreFolders, searchPattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue