forked from mirror/DotRecast
Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
ikpil | a0800de245 | |
ikpil | eb1aa49363 |
|
@ -20,7 +20,6 @@ dotnet_sort_system_directives_first = true
|
||||||
csharp_preserve_single_line_statements = false
|
csharp_preserve_single_line_statements = false
|
||||||
csharp_preserve_single_line_blocks = true
|
csharp_preserve_single_line_blocks = true
|
||||||
|
|
||||||
# ReSharper properties
|
#
|
||||||
resharper_csharp_wrap_lines = false
|
|
||||||
resharper_csharp_space_before_trailing_comment = true
|
resharper_csharp_space_before_trailing_comment = true
|
||||||
resharper_csharp_space_after_operator_keyword = true
|
resharper_csharp_space_after_operator_keyword = true
|
||||||
|
|
|
@ -49,7 +49,7 @@ jobs:
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up .NET 8.0
|
- name: Set up .NET 8.0
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
dotnet-version: 8.x
|
dotnet-version: 8.x
|
||||||
|
|
||||||
|
|
|
@ -37,12 +37,9 @@ jobs:
|
||||||
fetch-depth: 0 # Get all history to allow automatic versioning using MinVer
|
fetch-depth: 0 # Get all history to allow automatic versioning using MinVer
|
||||||
|
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
dotnet-version: |
|
dotnet-version: ${{ matrix.dotnet-version }}.x
|
||||||
6
|
|
||||||
7
|
|
||||||
8
|
|
||||||
|
|
||||||
- name: Restore dependencies
|
- name: Restore dependencies
|
||||||
run: dotnet restore
|
run: dotnet restore
|
||||||
|
|
|
@ -33,7 +33,7 @@ jobs:
|
||||||
fetch-depth: 0 # Get all history to allow automatic versioning using MinVer
|
fetch-depth: 0 # Get all history to allow automatic versioning using MinVer
|
||||||
|
|
||||||
- name: Setup Dotnet
|
- name: Setup Dotnet
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
dotnet-version: '8.x'
|
dotnet-version: '8.x'
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ jobs:
|
||||||
fetch-depth: 0 # Get all history to allow automatic versioning using MinVer
|
fetch-depth: 0 # Get all history to allow automatic versioning using MinVer
|
||||||
|
|
||||||
- name: Setup Dotnet
|
- name: Setup Dotnet
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
dotnet-version: '8.x'
|
dotnet-version: '8.x'
|
||||||
|
|
||||||
|
|
110
CHANGELOG.md
110
CHANGELOG.md
|
@ -6,122 +6,12 @@ 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,12 +39,6 @@ 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
|
||||||
|
@ -118,33 +112,23 @@ 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}
|
||||||
{FA7EF26A-BA47-43FD-86F8-0A33CFDF643F} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
|
||||||
{53AF87DA-37F8-4504-B623-B2113F4438CA} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
|
||||||
{17E4F2F0-FC27-416E-9CB6-9F2CAAC49C9D} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
|
||||||
{DEB16B90-CCD4-497E-A2E9-4CC66FD7EF47} = {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}
|
|
||||||
{88754FE2-A05A-4D4D-A81A-90418AD32362} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
{88754FE2-A05A-4D4D-A81A-90418AD32362} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
||||||
{554CB5BD-D58A-4856-BFE1-666A62C9BEA3} = {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}
|
||||||
{F9C5B52E-C01D-4514-94E9-B1A6895352E2} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
{F9C5B52E-C01D-4514-94E9-B1A6895352E2} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
||||||
|
{53AF87DA-37F8-4504-B623-B2113F4438CA} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
||||||
{67C68B34-118A-439C-88E1-D6D1ED78DC59} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
{67C68B34-118A-439C-88E1-D6D1ED78DC59} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
||||||
|
{17E4F2F0-FC27-416E-9CB6-9F2CAAC49C9D} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
||||||
{7BAA69B2-EDC7-4603-B16F-BC7B24353F81} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
{7BAA69B2-EDC7-4603-B16F-BC7B24353F81} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
||||||
|
{DEB16B90-CCD4-497E-A2E9-4CC66FD7EF47} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
||||||
{3CAA7306-088E-4373-A406-99755CC2B605} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
{3CAA7306-088E-4373-A406-99755CC2B605} = {A7CB8D8B-70DA-4567-8316-0659FCAE1C73}
|
||||||
|
{023E1E6A-4895-4573-89AE-3D5D8E0B39C8} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
||||||
|
{DF987948-8C23-4337-AF83-D87D6407518D} = {8ED75CF7-A3D6-423D-8499-9316DD413DAD}
|
||||||
{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,22 +1,28 @@
|
||||||
# DotRecast
|
<h1 align="center">DotRecast</h1>
|
||||||
|
<p align="center">
|
||||||
*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.*
|
<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>
|
||||||
*If you'd like to support the project, we'd appreciate starring(⭐) our repos on Github for more visibility.*
|
</p>
|
||||||
|
<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>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
![GitHub License](https://img.shields.io/github/license/ikpil/DotRecast?style=for-the-badge)
|
<p align="center">
|
||||||
![Languages](https://img.shields.io/github/languages/top/ikpil/DotRecast?style=for-the-badge)
|
<img alt="![GitHub License]" src="https://img.shields.io/github/license/ikpil/DotRecast?style=for-the-badge">
|
||||||
![GitHub repo size](https://img.shields.io/github/repo-size/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 stars](https://img.shields.io/github/stars/ikpil/DotRecast?style=for-the-badge&logo=github)](https://github.com/ikpil/DotRecast)
|
<img alt="GitHub repo size" src="https://img.shields.io/github/repo-size/ikpil/DotRecast?style=for-the-badge">
|
||||||
[![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"><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/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/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 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/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 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/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 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 issues" src="https://img.shields.io/github/issues-raw/ikpil/DotRecast?style=for-the-badge&logo=github&color=44cc11"></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://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 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 Version" src="https://img.shields.io/nuget/vpre/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://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>
|
||||||
|
<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,8 +0,0 @@
|
||||||
{
|
|
||||||
"name": "rnd/dotrecastnetsim",
|
|
||||||
"description": "DotRecast",
|
|
||||||
"homepage": "https://git.bit5.ru/rnd/DotRecastNetSim.git",
|
|
||||||
"require": {
|
|
||||||
"php": ">=7.4"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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,30 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace DotRecast.Core.Buffers
|
|
||||||
{
|
|
||||||
// This implementation is thread unsafe
|
|
||||||
public class RcObjectPool<T> where T : class
|
|
||||||
{
|
|
||||||
private readonly Queue<T> _items = new Queue<T>();
|
|
||||||
private readonly Func<T> _createFunc;
|
|
||||||
|
|
||||||
public RcObjectPool(Func<T> createFunc)
|
|
||||||
{
|
|
||||||
_createFunc = createFunc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T Get()
|
|
||||||
{
|
|
||||||
if (_items.TryDequeue(out var result))
|
|
||||||
return result;
|
|
||||||
|
|
||||||
return _createFunc();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Return(T obj)
|
|
||||||
{
|
|
||||||
_items.Enqueue(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,57 +6,55 @@ namespace DotRecast.Core.Buffers
|
||||||
{
|
{
|
||||||
public static class RcRentedArray
|
public static class RcRentedArray
|
||||||
{
|
{
|
||||||
public static RcRentedArray<T> Rent<T>(int minimumLength)
|
public static RcRentedArray<T> RentDisposableArray<T>(int minimumLength)
|
||||||
{
|
{
|
||||||
var array = ArrayPool<T>.Shared.Rent(minimumLength);
|
var array = ArrayPool<T>.Shared.Rent(minimumLength);
|
||||||
return new RcRentedArray<T>(ArrayPool<T>.Shared, array, minimumLength);
|
return new RcRentedArray<T>(ArrayPool<T>.Shared, array, minimumLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct RcRentedArray<T> : IDisposable
|
public class RcRentedArray<T> : IDisposable
|
||||||
{
|
{
|
||||||
private ArrayPool<T> _owner;
|
private ArrayPool<T> _owner;
|
||||||
private T[] _array;
|
private T[] _array;
|
||||||
|
private readonly RcAtomicInteger _disposed;
|
||||||
|
|
||||||
public int Length { get; }
|
public int Length { get; }
|
||||||
public bool IsDisposed => null == _owner || null == _array;
|
|
||||||
|
|
||||||
internal RcRentedArray(ArrayPool<T> owner, T[] array, int length)
|
internal RcRentedArray(ArrayPool<T> owner, T[] array, int length)
|
||||||
{
|
{
|
||||||
_owner = owner;
|
_owner = owner;
|
||||||
_array = array;
|
_array = array;
|
||||||
Length = length;
|
Length = length;
|
||||||
|
_disposed = new RcAtomicInteger(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref T this[int index]
|
public T this[int index]
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
RcThrowHelper.ThrowExceptionIfIndexOutOfRange(index, Length);
|
RcThrowHelper.ThrowExceptionIfIndexOutOfRange(index, Length);
|
||||||
return ref _array[index];
|
return _array[index];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public T[] AsArray()
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
set
|
||||||
{
|
{
|
||||||
return _array;
|
RcThrowHelper.ThrowExceptionIfIndexOutOfRange(index, Length);
|
||||||
|
_array[index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Span<T> AsSpan()
|
|
||||||
{
|
|
||||||
return new Span<T>(_array, 0, Length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (null != _owner && null != _array)
|
if (1 != _disposed.IncrementAndGet())
|
||||||
{
|
return;
|
||||||
_owner.Return(_array, true);
|
|
||||||
_owner = null;
|
_owner?.Return(_array, true);
|
||||||
_array = null;
|
_array = null;
|
||||||
}
|
_owner = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Core.Collections
|
namespace DotRecast.Core.Collections
|
||||||
|
@ -45,11 +45,5 @@ namespace DotRecast.Core.Collections
|
||||||
(list[k], list[n]) = (list[n], list[k]);
|
(list[k], list[n]) = (list[n], list[k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddRange<T>(this IList<T> list, Span<T> span)
|
|
||||||
{
|
|
||||||
foreach (var i in span)
|
|
||||||
list.Add(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,153 +0,0 @@
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -27,12 +27,12 @@ namespace DotRecast.Core.Collections
|
||||||
{
|
{
|
||||||
private bool _dirty;
|
private bool _dirty;
|
||||||
private readonly List<T> _items;
|
private readonly List<T> _items;
|
||||||
private readonly Comparison<T> _comparison;
|
private readonly Comparer<T> _comparer;
|
||||||
|
|
||||||
public RcSortedQueue(Comparison<T> comp)
|
public RcSortedQueue(Comparison<T> comp)
|
||||||
{
|
{
|
||||||
_items = new List<T>();
|
_items = new List<T>();
|
||||||
_comparison = (x, y) => comp(x, y) * -1;
|
_comparer = Comparer<T>.Create((x, y) => comp.Invoke(x, y) * -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Count()
|
public int Count()
|
||||||
|
@ -55,7 +55,7 @@ namespace DotRecast.Core.Collections
|
||||||
{
|
{
|
||||||
if (_dirty)
|
if (_dirty)
|
||||||
{
|
{
|
||||||
_items.Sort(_comparison); // reverse
|
_items.Sort(_comparer); // reverse
|
||||||
_dirty = false;
|
_dirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ namespace DotRecast.Core.Collections
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//int idx = _items.BinarySearch(item, _comparer); // don't use this! Because reference types can be reused externally.
|
//int idx = _items.BinarySearch(item, _comparer); // don't use this! Because reference types can be reused externally.
|
||||||
int idx = _items.LastIndexOf(item);
|
int idx = _items.FindLastIndex(x => item.Equals(x));
|
||||||
if (0 > idx)
|
if (0 > idx)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -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,14 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Core",
|
|
||||||
"rootNamespace": "DotRecast.Core",
|
|
||||||
"references": [],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
namespace DotRecast.Core
|
namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
public interface IRcRand
|
public interface IRcRand
|
||||||
{
|
{
|
||||||
float Next();
|
float Next();
|
||||||
double NextDouble();
|
|
||||||
int NextInt32();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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
|
||||||
|
@ -50,19 +49,6 @@ 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()
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
namespace DotRecast.Core.Numerics
|
|
||||||
{
|
|
||||||
public struct RcVec3i
|
|
||||||
{
|
|
||||||
public int X;
|
|
||||||
public int Y;
|
|
||||||
public int Z;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +1,20 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DotRecast.Core.Numerics
|
namespace DotRecast.Core.Numerics
|
||||||
{
|
{
|
||||||
public static class RcVec
|
public static class RcVecUtils
|
||||||
{
|
{
|
||||||
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(Span<float> values, int n)
|
public static RcVec3f Create(float[] values)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
}
|
}
|
||||||
|
@ -37,73 +42,10 @@ namespace DotRecast.Core.Numerics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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 Equal(RcVec3f p0, RcVec3f p1)
|
|
||||||
{
|
|
||||||
float d = RcVec3f.DistanceSquared(p0, p1);
|
|
||||||
return d < EQUAL_THRESHOLD;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static float Dot2(RcVec3f a, RcVec3f b)
|
public static RcVec3f Scale(this RcVec3f v, float scale)
|
||||||
{
|
{
|
||||||
return a.X * b.X + a.Z * b.Z;
|
return v * scale;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[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)
|
||||||
|
@ -120,6 +62,46 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -137,11 +119,19 @@ namespace DotRecast.Core.Numerics
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Copy(Span<float> @out, int n, Span<float> @in, int m)
|
public static float Dot(float[] v1, float[] v2)
|
||||||
{
|
{
|
||||||
@out[n + 0] = @in[m + 0];
|
return v1[0] * v2[0] +
|
||||||
@out[n + 1] = @in[m + 1];
|
v1[1] * v2[1] +
|
||||||
@out[n + 2] = @in[m + 2];
|
v1[2] * v2[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.
|
||||||
|
@ -177,6 +167,26 @@ 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)]
|
||||||
|
@ -192,10 +202,6 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -205,7 +211,7 @@ namespace DotRecast.Core.Numerics
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static float Dist2DSqr(RcVec3f p, Span<float> verts, int i)
|
public static float Dist2DSqr(RcVec3f p, float[] verts, int i)
|
||||||
{
|
{
|
||||||
float dx = verts[i] - p.X;
|
float dx = verts[i] - p.X;
|
||||||
float dz = verts[i + 2] - p.Z;
|
float dz = verts[i + 2] - p.Z;
|
||||||
|
@ -256,7 +262,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(Span<float> verts, int v1, int v2, float t)
|
public static RcVec3f Lerp(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,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,165 +0,0 @@
|
||||||
/*
|
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -29,11 +29,5 @@ 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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
|
||||||
{
|
{
|
||||||
|
@ -6,13 +6,9 @@ namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
private readonly Random _r;
|
private readonly Random _r;
|
||||||
|
|
||||||
public RcRand() : this(new Random())
|
public RcRand()
|
||||||
{
|
{
|
||||||
}
|
_r = new Random();
|
||||||
|
|
||||||
public RcRand(Random r)
|
|
||||||
{
|
|
||||||
_r = r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RcRand(long seed)
|
public RcRand(long seed)
|
||||||
|
@ -25,11 +21,6 @@ namespace DotRecast.Core
|
||||||
return (float)_r.NextDouble();
|
return (float)_r.NextDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double NextDouble()
|
|
||||||
{
|
|
||||||
return _r.NextDouble();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int NextInt32()
|
public int NextInt32()
|
||||||
{
|
{
|
||||||
return _r.Next();
|
return _r.Next();
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
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,36 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace DotRecast.Core
|
|
||||||
{
|
|
||||||
public static class RcSpans
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static void Copy<T>(Span<T> src, Span<T> dst)
|
|
||||||
{
|
|
||||||
src.CopyTo(dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static void Copy<T>(Span<T> src, int srcIdx, Span<T> dst, int dstIdx, int length)
|
|
||||||
{
|
|
||||||
var slicedSrc = src.Slice(srcIdx, length);
|
|
||||||
var slicedDst = dst.Slice(dstIdx);
|
|
||||||
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,12 +15,6 @@ 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,17 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Detour.Crowd",
|
|
||||||
"rootNamespace": "DotRecast.Detour.Crowd",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Core",
|
|
||||||
"DotRecast.Detour"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -20,9 +20,8 @@ freely, subject to the following restrictions:
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Threading.Tasks;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Buffers;
|
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
|
@ -121,16 +120,15 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// @ingroup crowd
|
/// @ingroup crowd
|
||||||
public class DtCrowd
|
public class DtCrowd
|
||||||
{
|
{
|
||||||
private readonly RcAtomicInteger _agentIdx;
|
private readonly RcAtomicInteger _agentId = new RcAtomicInteger();
|
||||||
private readonly Dictionary<int, DtCrowdAgent> _agents;
|
private readonly List<DtCrowdAgent> _agents;
|
||||||
private readonly List<DtCrowdAgent> _activeAgents;
|
|
||||||
|
|
||||||
private readonly DtPathQueue _pathQ;
|
private readonly DtPathQueue _pathQ;
|
||||||
|
|
||||||
private readonly DtObstacleAvoidanceParams[] _obstacleQueryParams;
|
private readonly DtObstacleAvoidanceParams[] _obstacleQueryParams;
|
||||||
private readonly DtObstacleAvoidanceQuery _obstacleQuery;
|
private readonly DtObstacleAvoidanceQuery _obstacleQuery;
|
||||||
|
|
||||||
private readonly DtProximityGrid _grid;
|
private DtProximityGrid _grid;
|
||||||
|
|
||||||
private int _maxPathResult;
|
private int _maxPathResult;
|
||||||
private readonly RcVec3f _agentPlacementHalfExtents;
|
private readonly RcVec3f _agentPlacementHalfExtents;
|
||||||
|
@ -172,10 +170,7 @@ 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);
|
||||||
_agentIdx = new RcAtomicInteger(0);
|
_agents = new List<DtCrowdAgent>();
|
||||||
_agents = new Dictionary<int, DtCrowdAgent>();
|
|
||||||
_activeAgents = new List<DtCrowdAgent>();
|
|
||||||
_grid = new DtProximityGrid(_config.maxAgentRadius * 3);
|
|
||||||
|
|
||||||
// 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);
|
||||||
|
@ -240,10 +235,11 @@ 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 = _agentIdx.GetAndIncrement();
|
int idx = _agentId.GetAndIncrement();
|
||||||
DtCrowdAgent ag = new DtCrowdAgent(idx);
|
DtCrowdAgent ag = new DtCrowdAgent(idx);
|
||||||
ag.corridor.Init(_maxPathResult);
|
ag.corridor.Init(_maxPathResult);
|
||||||
AddAgent(ag);
|
_agents.Add(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.
|
||||||
|
@ -260,7 +256,6 @@ 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;
|
||||||
|
@ -283,27 +278,15 @@ 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)
|
||||||
{
|
{
|
||||||
if (_agents.Remove(agent.idx))
|
_agents.Remove(agent);
|
||||||
{
|
|
||||||
_activeAgents.Remove(agent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool RequestMoveTargetReplan(DtCrowdAgent ag, long refs, RcVec3f pos)
|
private bool RequestMoveTargetReplan(DtCrowdAgent ag, long refs, RcVec3f pos)
|
||||||
|
@ -375,7 +358,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
*/
|
*/
|
||||||
public IList<DtCrowdAgent> GetActiveAgents()
|
public IList<DtCrowdAgent> GetActiveAgents()
|
||||||
{
|
{
|
||||||
return _activeAgents;
|
return _agents;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RcVec3f GetQueryExtents()
|
public RcVec3f GetQueryExtents()
|
||||||
|
@ -566,18 +549,14 @@ namespace DotRecast.Detour.Crowd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly RcSortedQueue<DtCrowdAgent> UpdateMoveRequest_queue = new RcSortedQueue<DtCrowdAgent>((a1, a2) => a2.targetReplanTime.CompareTo(a1.targetReplanTime));
|
|
||||||
private readonly List<long> UpdateMoveRequest_reqPath = new List<long>();
|
|
||||||
private void UpdateMoveRequest(IList<DtCrowdAgent> agents, float dt)
|
private void UpdateMoveRequest(IList<DtCrowdAgent> agents, float dt)
|
||||||
{
|
{
|
||||||
using var timer = _telemetry.ScopedTimer(DtCrowdTimerLabel.UpdateMoveRequest);
|
using var timer = _telemetry.ScopedTimer(DtCrowdTimerLabel.UpdateMoveRequest);
|
||||||
|
|
||||||
RcSortedQueue<DtCrowdAgent> queue = UpdateMoveRequest_queue;
|
RcSortedQueue<DtCrowdAgent> queue = new RcSortedQueue<DtCrowdAgent>((a1, a2) => a2.targetReplanTime.CompareTo(a1.targetReplanTime));
|
||||||
queue.Clear();
|
|
||||||
|
|
||||||
// Fire off new requests.
|
// Fire off new requests.
|
||||||
List<long> reqPath = UpdateMoveRequest_reqPath;
|
List<long> reqPath = new List<long>();
|
||||||
reqPath.Clear();
|
|
||||||
for (var i = 0; i < agents.Count; i++)
|
for (var i = 0; i < agents.Count; i++)
|
||||||
{
|
{
|
||||||
var ag = agents[i];
|
var ag = agents[i];
|
||||||
|
@ -610,7 +589,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, path.Count, ref reqPath);
|
status = _navQuery.FinalizeSlicedFindPathPartial(path, ref reqPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -870,7 +849,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
using var timer = _telemetry.ScopedTimer(DtCrowdTimerLabel.BuildProximityGrid);
|
using var timer = _telemetry.ScopedTimer(DtCrowdTimerLabel.BuildProximityGrid);
|
||||||
|
|
||||||
_grid.Clear();
|
_grid = new DtProximityGrid(_config.maxAgentRadius * 3);
|
||||||
|
|
||||||
for (var i = 0; i < agents.Count; i++)
|
for (var i = 0; i < agents.Count; i++)
|
||||||
{
|
{
|
||||||
|
@ -896,7 +875,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 (RcVec.Dist2DSqr(ag.npos, ag.boundary.GetCenter()) > RcMath.Sqr(updateThr)
|
if (RcVecUtils.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,
|
||||||
|
@ -904,66 +883,21 @@ namespace DotRecast.Detour.Crowd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query neighbour agents
|
// Query neighbour agents
|
||||||
ag.nneis = GetNeighbours(ag.npos, ag.option.height, ag.option.collisionQueryRange, ag, ag.neis, DtCrowdConst.DT_CROWDAGENT_MAX_NEIGHBOURS, _grid);
|
GetNeighbours(ag.npos, ag.option.height, ag.option.collisionQueryRange, ag, ref ag.neis, _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)
|
||||||
{
|
{
|
||||||
// Insert neighbour based on the distance.
|
result.Clear();
|
||||||
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 = GetAgent(ids[i]);
|
var ag = ids[i];
|
||||||
if (ag == skip)
|
if (ag == skip)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -983,10 +917,11 @@ namespace DotRecast.Detour.Crowd
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = AddNeighbour(ag, distSqr, result, n, maxResult);
|
result.Add(new DtCrowdNeighbour(ag, distSqr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return n;
|
result.Sort((o1, o2) => o1.dist.CompareTo(o2.dist));
|
||||||
|
return result.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FindCorners(IList<DtCrowdAgent> agents, DtCrowdAgentDebugInfo debug)
|
private void FindCorners(IList<DtCrowdAgent> agents, DtCrowdAgentDebugInfo debug)
|
||||||
|
@ -1009,13 +944,13 @@ namespace DotRecast.Detour.Crowd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find corners for steering
|
// Find corners for steering
|
||||||
ag.ncorners = ag.corridor.FindCorners(ag.corners, DtCrowdConst.DT_CROWDAGENT_MAX_CORNERS, _navQuery, _filters[ag.option.queryFilterType]);
|
ag.corridor.FindCorners(ref 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.ncorners > 0)
|
if ((ag.option.updateFlags & DtCrowdAgentUpdateFlags.DT_CROWD_OPTIMIZE_VIS) != 0 && ag.corners.Count > 0)
|
||||||
{
|
{
|
||||||
RcVec3f target = ag.corners[Math.Min(1, ag.ncorners - 1)].pos;
|
RcVec3f target = ag.corners[Math.Min(1, ag.corners.Count - 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]);
|
||||||
|
|
||||||
|
@ -1057,7 +992,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check
|
// Check
|
||||||
float triggerRadius = ag.option.radius * 0.25f;//todo make parameterizable
|
float triggerRadius = ag.option.radius * 2.25f;
|
||||||
if (ag.OverOffmeshConnection(triggerRadius))
|
if (ag.OverOffmeshConnection(triggerRadius))
|
||||||
{
|
{
|
||||||
// Prepare to off-mesh connection.
|
// Prepare to off-mesh connection.
|
||||||
|
@ -1065,18 +1000,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.ncorners - 1].refs, refs, ref anim.startPos,
|
if (ag.corridor.MoveOverOffmeshConnection(ag.corners[ag.corners.Count - 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 = (RcVec.Dist2D(anim.startPos, anim.endPos) / ag.option.maxSpeed) * 0.5f;
|
anim.tmax = (RcVecUtils.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.ncorners = 0;
|
ag.corners.Clear();
|
||||||
ag.nneis = 0;
|
ag.neis.Clear();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1128,7 +1063,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 * (ag.desiredSpeed * speedScale);
|
dvel = dvel.Scale(ag.desiredSpeed * speedScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Separation
|
// Separation
|
||||||
|
@ -1141,7 +1076,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.nneis; ++j)
|
for (int j = 0; j < ag.neis.Count; ++j)
|
||||||
{
|
{
|
||||||
DtCrowdAgent nei = ag.neis[j].agent;
|
DtCrowdAgent nei = ag.neis[j].agent;
|
||||||
|
|
||||||
|
@ -1162,20 +1097,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 = RcVec.Mad(disp, diff, weight / dist);
|
disp = RcVecUtils.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 = RcVec.Mad(dvel, disp, 1.0f / w);
|
dvel = RcVecUtils.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 * (desiredSqr / speedSqr);
|
dvel = dvel.Scale(desiredSqr / speedSqr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1203,12 +1138,9 @@ namespace DotRecast.Detour.Crowd
|
||||||
_obstacleQuery.Reset();
|
_obstacleQuery.Reset();
|
||||||
|
|
||||||
// Add neighbours as obstacles.
|
// Add neighbours as obstacles.
|
||||||
for (int j = 0; j < ag.nneis; ++j)
|
for (int j = 0; j < ag.neis.Count; ++j)
|
||||||
{
|
{
|
||||||
DtCrowdAgent nei = ag.neis[j].agent;
|
DtCrowdAgent nei = ag.neis[j].agent;
|
||||||
if(!nei.option.contributeObstacleAvoidance || nei.option.obstacleAvoidanceWeight < ag.option.obstacleAvoidanceWeight)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
_obstacleQuery.AddCircle(nei.npos, nei.option.radius, nei.vel, nei.dvel);
|
_obstacleQuery.AddCircle(nei.npos, nei.option.radius, nei.vel, nei.dvel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1294,7 +1226,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
|
|
||||||
float w = 0;
|
float w = 0;
|
||||||
|
|
||||||
for (int j = 0; j < ag.nneis; ++j)
|
for (int j = 0; j < ag.neis.Count; ++j)
|
||||||
{
|
{
|
||||||
DtCrowdAgent nei = ag.neis[j].agent;
|
DtCrowdAgent nei = ag.neis[j].agent;
|
||||||
long idx1 = nei.idx;
|
long idx1 = nei.idx;
|
||||||
|
@ -1328,7 +1260,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 = RcVec.Mad(ag.disp, diff, pen);
|
ag.disp = RcVecUtils.Mad(ag.disp, diff, pen);
|
||||||
|
|
||||||
w += 1.0f;
|
w += 1.0f;
|
||||||
}
|
}
|
||||||
|
@ -1336,7 +1268,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 * iw;
|
ag.disp = ag.disp.Scale(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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -28,7 +28,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// @ingroup crowd
|
/// @ingroup crowd
|
||||||
public class DtCrowdAgent
|
public class DtCrowdAgent
|
||||||
{
|
{
|
||||||
public readonly int idx;
|
public readonly long 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,19 +37,16 @@ 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 readonly DtPathCorridor corridor;
|
public DtPathCorridor corridor;
|
||||||
|
|
||||||
/// The local boundary data for the agent.
|
/// The local boundary data for the agent.
|
||||||
public readonly DtLocalBoundary boundary;
|
public 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 readonly DtCrowdNeighbour[] neis = new DtCrowdNeighbour[DtCrowdConst.DT_CROWDAGENT_MAX_NEIGHBOURS];
|
public List<DtCrowdNeighbour> neis = new List<DtCrowdNeighbour>();
|
||||||
|
|
||||||
/// The number of neighbors.
|
|
||||||
public int nneis;
|
|
||||||
|
|
||||||
/// The desired speed.
|
/// The desired speed.
|
||||||
public float desiredSpeed;
|
public float desiredSpeed;
|
||||||
|
@ -64,10 +61,7 @@ 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 DtStraightPath[] corners = new DtStraightPath[DtCrowdConst.DT_CROWDAGENT_MAX_CORNERS];
|
public List<DtStraightPath> corners = new List<DtStraightPath>();
|
||||||
|
|
||||||
/// 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.
|
||||||
|
@ -94,28 +88,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 * (maxDelta / ds);
|
dv = dv.Scale(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 = RcVec.Mad(npos, vel, dt);
|
npos = RcVecUtils.Mad(npos, vel, dt);
|
||||||
else
|
else
|
||||||
vel = RcVec3f.Zero;
|
vel = RcVec3f.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool OverOffmeshConnection(float radius)
|
public bool OverOffmeshConnection(float radius)
|
||||||
{
|
{
|
||||||
if (0 == ncorners)
|
if (0 == corners.Count)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool offMeshConnection = ((corners[ncorners - 1].flags
|
bool offMeshConnection = ((corners[corners.Count - 1].flags
|
||||||
& DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
& DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
||||||
? true
|
? true
|
||||||
: false;
|
: false;
|
||||||
if (offMeshConnection)
|
if (offMeshConnection)
|
||||||
{
|
{
|
||||||
float distSq = RcVec.Dist2DSqr(npos, corners[ncorners - 1].pos);
|
float distSq = RcVecUtils.Dist2DSqr(npos, corners[corners.Count - 1].pos);
|
||||||
if (distSq < radius * radius)
|
if (distSq < radius * radius)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -125,12 +119,12 @@ namespace DotRecast.Detour.Crowd
|
||||||
|
|
||||||
public float GetDistanceToGoal(float range)
|
public float GetDistanceToGoal(float range)
|
||||||
{
|
{
|
||||||
if (0 == ncorners)
|
if (0 == corners.Count)
|
||||||
return range;
|
return range;
|
||||||
|
|
||||||
bool endOfPath = ((corners[ncorners - 1].flags & DtStraightPathFlags.DT_STRAIGHTPATH_END) != 0) ? true : false;
|
bool endOfPath = ((corners[corners.Count - 1].flags & DtStraightPathFlags.DT_STRAIGHTPATH_END) != 0) ? true : false;
|
||||||
if (endOfPath)
|
if (endOfPath)
|
||||||
return Math.Min(RcVec.Dist2D(npos, corners[ncorners - 1].pos), range);
|
return Math.Min(RcVecUtils.Dist2D(npos, corners[corners.Count - 1].pos), range);
|
||||||
|
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
@ -138,10 +132,10 @@ namespace DotRecast.Detour.Crowd
|
||||||
public RcVec3f CalcSmoothSteerDirection()
|
public RcVec3f CalcSmoothSteerDirection()
|
||||||
{
|
{
|
||||||
RcVec3f dir = new RcVec3f();
|
RcVec3f dir = new RcVec3f();
|
||||||
if (0 < ncorners)
|
if (0 < corners.Count)
|
||||||
{
|
{
|
||||||
int ip0 = 0;
|
int ip0 = 0;
|
||||||
int ip1 = Math.Min(1, ncorners - 1);
|
int ip1 = Math.Min(1, corners.Count - 1);
|
||||||
var p0 = corners[ip0].pos;
|
var p0 = corners[ip0].pos;
|
||||||
var p1 = corners[ip1].pos;
|
var p1 = corners[ip1].pos;
|
||||||
|
|
||||||
|
@ -153,7 +147,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 * (1.0f / len1);
|
dir1 = dir1.Scale(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;
|
||||||
|
@ -167,7 +161,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
public RcVec3f CalcStraightSteerDirection()
|
public RcVec3f CalcStraightSteerDirection()
|
||||||
{
|
{
|
||||||
RcVec3f dir = new RcVec3f();
|
RcVec3f dir = new RcVec3f();
|
||||||
if (0 < ncorners)
|
if (0 < corners.Count)
|
||||||
{
|
{
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -24,15 +24,23 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// @ingroup crowd
|
/// @ingroup crowd
|
||||||
public class DtCrowdAgentParams
|
public class DtCrowdAgentParams
|
||||||
{
|
{
|
||||||
public float radius; // < Agent radius. [Limit: >= 0]
|
/// < Agent radius. [Limit: >= 0]
|
||||||
public float height; // < Agent height. [Limit: > 0]
|
public float radius;
|
||||||
public float maxAcceleration; // < Maximum allowed acceleration. [Limit: >= 0]
|
|
||||||
public float maxSpeed; // < Maximum allowed speed. [Limit: >= 0]
|
/// < Agent height. [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;
|
||||||
|
|
||||||
public float pathOptimizationRange; // < The path visibility optimization range. [Limit: > 0]
|
/// < 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;
|
||||||
|
@ -45,9 +53,6 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// [Limits: 0 <= value < #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS]
|
/// [Limits: 0 <= value < #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS]
|
||||||
public int obstacleAvoidanceType;
|
public int obstacleAvoidanceType;
|
||||||
|
|
||||||
public bool contributeObstacleAvoidance;
|
|
||||||
public float obstacleAvoidanceWeight;
|
|
||||||
|
|
||||||
/// The index of the query filter used by this agent.
|
/// The index of the query filter used by this agent.
|
||||||
public int queryFilterType;
|
public int queryFilterType;
|
||||||
|
|
||||||
|
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
public static class DtCrowdConst
|
public static class DtCrowdConst
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
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; // < The index of the neighbor in the crowd.
|
public readonly DtCrowdAgent agent;
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -18,7 +18,6 @@ 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;
|
||||||
|
@ -91,8 +90,6 @@ 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();
|
||||||
|
@ -107,17 +104,18 @@ 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];
|
|
||||||
int nsegs = 0;
|
var segmentVerts = new List<RcSegmentVert>();
|
||||||
|
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], filter, segs, null, ref nsegs, MAX_SEGS_PER_POLY);
|
var result = navquery.GetPolyWallSegments(m_polys[j], false, filter, ref segmentVerts, ref segmentRefs);
|
||||||
if (result.Succeeded())
|
if (result.Succeeded())
|
||||||
{
|
{
|
||||||
for (int k = 0; k < nsegs; ++k)
|
for (int k = 0; k < segmentRefs.Count; ++k)
|
||||||
{
|
{
|
||||||
ref RcSegmentVert s = ref segs[k];
|
RcSegmentVert s = segmentVerts[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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
public class DtObstacleAvoidanceParams
|
public class DtObstacleAvoidanceParams
|
||||||
{
|
{
|
||||||
|
@ -8,11 +8,18 @@ namespace DotRecast.Detour.Crowd
|
||||||
public float weightSide;
|
public float weightSide;
|
||||||
public float weightToi;
|
public float weightToi;
|
||||||
public float horizTime;
|
public float horizTime;
|
||||||
public int gridSize; // < grid
|
public int gridSize;
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -19,7 +19,6 @@ freely, subject to the following restrictions:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
|
@ -28,9 +27,11 @@ namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
public class DtObstacleAvoidanceQuery
|
public class DtObstacleAvoidanceQuery
|
||||||
{
|
{
|
||||||
public const int DT_MAX_PATTERN_DIVS = 32; // < Max numver of adaptive divs.
|
public const int DT_MAX_PATTERN_DIVS = 32;
|
||||||
|
|
||||||
|
/// < 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;
|
||||||
|
@ -186,16 +187,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 = RcVec.Perp2D(u, v);
|
float d = RcVecUtils.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 = RcVec.Perp2D(v, w) * d;
|
t = RcVecUtils.Perp2D(v, w) * d;
|
||||||
if (t < 0 || t > 1)
|
if (t < 0 || t > 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
float s = RcVec.Perp2D(u, w) * d;
|
float s = RcVecUtils.Perp2D(u, w) * d;
|
||||||
if (s < 0 || s > 1)
|
if (s < 0 || s > 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -216,8 +217,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 * (RcVec.Dist2D(vcand, dvel) * m_invVmax);
|
float vpen = m_params.weightDesVel * (RcVecUtils.Dist2D(vcand, dvel) * m_invVmax);
|
||||||
float vcpen = m_params.weightCurVel * (RcVec.Dist2D(vcand, vel) * m_invVmax);
|
float vcpen = m_params.weightCurVel * (RcVecUtils.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)
|
||||||
|
@ -236,7 +237,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
DtObstacleCircle cir = m_circles[i];
|
DtObstacleCircle cir = m_circles[i];
|
||||||
|
|
||||||
// RVO
|
// RVO
|
||||||
RcVec3f vab = vcand * 2;
|
RcVec3f vab = vcand.Scale(2);
|
||||||
vab = RcVec3f.Subtract(vab, vel);
|
vab = RcVec3f.Subtract(vab, vel);
|
||||||
vab = RcVec3f.Subtract(vab, cir.vel);
|
vab = RcVec3f.Subtract(vab, cir.vel);
|
||||||
|
|
||||||
|
@ -361,8 +362,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
}
|
}
|
||||||
|
|
||||||
// vector normalization that ignores the y-component.
|
// vector normalization that ignores the y-component.
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
void DtNormalize2D(float[] v)
|
||||||
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)
|
||||||
|
@ -373,8 +373,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
}
|
}
|
||||||
|
|
||||||
// vector normalization that ignores the y-component.
|
// vector normalization that ignores the y-component.
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
RcVec3f DtRotate2D(float[] v, float ang)
|
||||||
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,6 +384,7 @@ 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,
|
||||||
|
@ -402,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.
|
||||||
Span<float> pat = stackalloc float[(DT_MAX_PATTERN_DIVS * DT_MAX_PATTERN_RINGS + 1) * 2];
|
float[] pat = new 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;
|
||||||
|
@ -416,7 +416,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
float sa = MathF.Sin(da);
|
float sa = MathF.Sin(da);
|
||||||
|
|
||||||
// desired direction
|
// desired direction
|
||||||
Span<float> ddir = stackalloc float[6];
|
float[] ddir = new 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -20,6 +20,7 @@ freely, subject to the following restrictions:
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
|
@ -33,8 +34,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
private RcVec3f m_pos;
|
private RcVec3f m_pos;
|
||||||
private RcVec3f m_target;
|
private RcVec3f m_target;
|
||||||
|
|
||||||
private List<long> m_path = new List<long>();
|
private List<long> m_path;
|
||||||
private int m_npath;
|
|
||||||
private int m_maxPath;
|
private int m_maxPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,9 +89,7 @@ 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)
|
||||||
{
|
{
|
||||||
if (m_path.Capacity < maxPath)
|
m_path = new List<long>();
|
||||||
m_path.Capacity = maxPath;
|
|
||||||
m_npath = 0;
|
|
||||||
m_maxPath = maxPath;
|
m_maxPath = maxPath;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +108,6 @@ 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -134,42 +131,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(Span<DtStraightPath> corners, int maxCorners, DtNavMeshQuery navquery, IDtQueryFilter filter)
|
public int FindCorners(ref List<DtStraightPath> corners, int maxCorners, DtNavMeshQuery navquery, IDtQueryFilter filter)
|
||||||
{
|
{
|
||||||
const float MIN_TARGET_DIST = 0.01f;
|
const float MIN_TARGET_DIST = 0.01f;
|
||||||
|
|
||||||
int ncorners = 0;
|
var result = navquery.FindStraightPath(m_pos, m_target, m_path, ref corners, maxCorners, 0);
|
||||||
navquery.FindStraightPath(m_pos, m_target, m_path, m_npath, corners, out ncorners, maxCorners, 0);
|
if (result.Succeeded())
|
||||||
|
{
|
||||||
// Prune points in the beginning of the path which are too close.
|
// Prune points in the beginning of the path which are too close.
|
||||||
while (0 < ncorners)
|
int start = 0;
|
||||||
|
foreach (DtStraightPath spi in corners)
|
||||||
{
|
{
|
||||||
if ((corners[0].flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0 ||
|
if ((spi.flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0
|
||||||
RcVec.Dist2DSqr(corners[0].pos, m_pos) > RcMath.Sqr(MIN_TARGET_DIST))
|
|| RcVecUtils.Dist2DSqr(spi.pos, m_pos) > RcMath.Sqr(MIN_TARGET_DIST))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ncorners--;
|
start++;
|
||||||
if (0 < ncorners)
|
|
||||||
{
|
|
||||||
RcSpans.Move(corners, 1, 0, 3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int end = corners.Count;
|
||||||
// Prune points after an off-mesh connection.
|
// Prune points after an off-mesh connection.
|
||||||
for (int i = 0; i < ncorners; ++i)
|
for (int i = start; i < corners.Count; i++)
|
||||||
{
|
{
|
||||||
if ((corners[i].flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
DtStraightPath spi = corners[i];
|
||||||
|
if ((spi.flags & DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
||||||
{
|
{
|
||||||
ncorners = i + 1;
|
end = i + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
corners = corners.GetRange(start, end - start);
|
||||||
|
}
|
||||||
|
|
||||||
return ncorners;
|
return corners.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -198,7 +195,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 = RcVec.Dist2D(m_pos, next);
|
float dist = RcVecUtils.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)
|
||||||
|
@ -211,7 +208,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 = RcVec.Mad(m_pos, delta, pathOptimizationRange / dist);
|
RcVec3f goal = RcVecUtils.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);
|
||||||
|
@ -219,7 +216,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
if (res.Count > 1 && t > 0.99f)
|
if (res.Count > 1 && t > 0.99f)
|
||||||
{
|
{
|
||||||
m_npath = DtPathUtils.MergeCorridorStartShortcut(m_path, m_npath, m_maxPath, res, res.Count);
|
m_path = DtPathUtils.MergeCorridorStartShortcut(m_path, m_path.Count, m_maxPath, res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,7 +236,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_npath < 3)
|
if (m_path.Count < 3)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -247,11 +244,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, m_npath, ref res);
|
var status = navquery.FinalizeSlicedFindPathPartial(m_path, ref res);
|
||||||
|
|
||||||
if (status.Succeeded() && res.Count > 0)
|
if (status.Succeeded() && res.Count > 0)
|
||||||
{
|
{
|
||||||
m_npath = DtPathUtils.MergeCorridorStartShortcut(m_path, m_npath, m_maxPath, res, res.Count);
|
m_path = DtPathUtils.MergeCorridorStartShortcut(m_path, m_path.Count, m_maxPath, res);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,23 +260,21 @@ 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_npath && polyRef != offMeshConRef)
|
while (npos < m_path.Count && polyRef != offMeshConRef)
|
||||||
{
|
{
|
||||||
prevRef = polyRef;
|
prevRef = polyRef;
|
||||||
polyRef = m_path[npos];
|
polyRef = m_path[npos];
|
||||||
npos++;
|
npos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (npos == m_npath)
|
if (npos == m_path.Count)
|
||||||
{
|
{
|
||||||
// Could not find offMeshConRef
|
// Could not find offMeshConRef
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prune path
|
// Prune path
|
||||||
m_path.RemoveRange(0, npos);
|
m_path = m_path.GetRange(npos, m_path.Count - npos);
|
||||||
m_npath -= npos;
|
|
||||||
|
|
||||||
refs[0] = prevRef;
|
refs[0] = prevRef;
|
||||||
refs[1] = polyRef;
|
refs[1] = polyRef;
|
||||||
|
|
||||||
|
@ -318,12 +313,11 @@ 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.
|
||||||
const int MAX_VISITED = 16;
|
var visited = new List<long>();
|
||||||
Span<long> visited = stackalloc long[MAX_VISITED];
|
var status = navquery.MoveAlongSurface(m_path[0], m_pos, npos, filter, out var result, ref 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_npath = DtPathUtils.MergeCorridorStartMoved(m_path, m_npath, m_maxPath, visited, nvisited);
|
DtPathUtils.MergeCorridorStartMoved(m_path, m_path.Count, m_maxPath, visited);
|
||||||
|
|
||||||
// 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;
|
||||||
|
@ -361,14 +355,11 @@ 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.
|
||||||
const int MAX_VISITED = 16;
|
var visited = new List<long>();
|
||||||
Span<long> visited = stackalloc long[MAX_VISITED];
|
var status = navquery.MoveAlongSurface(m_path[^1], m_target, npos, filter, out var result, ref 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_npath = DtPathUtils.MergeCorridorEndMoved(m_path, m_npath, m_maxPath, visited, nvisited);
|
m_path = DtPathUtils.MergeCorridorEndMoved(m_path, m_path.Count, m_maxPath, visited);
|
||||||
|
|
||||||
// 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.
|
||||||
/*
|
/*
|
||||||
|
@ -395,32 +386,25 @@ namespace DotRecast.Detour.Crowd
|
||||||
public void SetCorridor(RcVec3f target, List<long> path)
|
public void SetCorridor(RcVec3f target, List<long> path)
|
||||||
{
|
{
|
||||||
m_target = target;
|
m_target = target;
|
||||||
if(path != m_path)
|
m_path = new List<long>(path);
|
||||||
{
|
|
||||||
m_path.Clear();
|
|
||||||
m_path.AddRange(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_npath < 3 && m_npath > 0)
|
if (m_path.Count < 3 && m_path.Count > 0)
|
||||||
{
|
{
|
||||||
long p = m_path[m_npath - 1];
|
long p = m_path[m_path.Count - 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,12 +412,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_npath && navquery.IsValidPolyRef(m_path[n], filter))
|
while (n < m_path.Count && navquery.IsValidPolyRef(m_path[n], filter))
|
||||||
{
|
{
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_npath == n)
|
if (m_path.Count == n)
|
||||||
{
|
{
|
||||||
// All valid, no need to fix.
|
// All valid, no need to fix.
|
||||||
return true;
|
return true;
|
||||||
|
@ -441,20 +425,18 @@ 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 = new RcVec3f(safePos);
|
m_pos = RcVecUtils.Create(safePos);
|
||||||
m_path.Clear();
|
m_path.Clear();
|
||||||
m_path.Add(safeRef);
|
m_path.Add(safeRef);
|
||||||
m_npath = 1;
|
|
||||||
}
|
}
|
||||||
else if (n < m_npath)
|
else if (n < m_path.Count)
|
||||||
{
|
{
|
||||||
// The path is partially usable.
|
// The path is partially usable.
|
||||||
m_path.RemoveRange(n, m_path.Count - 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_npath - 1], m_target, out m_target);
|
navquery.ClosestPointOnPolyBoundary(m_path[m_path.Count - 1], m_target, out m_target);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,7 +452,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_npath, maxLookAhead);
|
int n = Math.Min(m_path.Count, 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))
|
||||||
|
@ -500,14 +482,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_npath ? 0 : m_path[0];
|
return 0 == m_path.Count ? 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_npath ? 0 : m_path[m_npath - 1];
|
return 0 == m_path.Count ? 0 : m_path[m_path.Count - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The corridor's path.
|
/// The corridor's path.
|
||||||
|
@ -521,7 +503,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_npath;
|
return m_path.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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -22,7 +22,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using DotRecast.Core.Buffers;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour.Crowd
|
namespace DotRecast.Detour.Crowd
|
||||||
{
|
{
|
||||||
|
@ -31,14 +30,12 @@ namespace DotRecast.Detour.Crowd
|
||||||
private readonly float _cellSize;
|
private readonly float _cellSize;
|
||||||
private readonly float _invCellSize;
|
private readonly float _invCellSize;
|
||||||
private readonly Dictionary<long, List<DtCrowdAgent>> _items;
|
private readonly Dictionary<long, List<DtCrowdAgent>> _items;
|
||||||
private readonly RcObjectPool<List<DtCrowdAgent>> _listPool;
|
|
||||||
|
|
||||||
public DtProximityGrid(float cellSize)
|
public DtProximityGrid(float cellSize)
|
||||||
{
|
{
|
||||||
_cellSize = cellSize;
|
_cellSize = cellSize;
|
||||||
_invCellSize = 1.0f / cellSize;
|
_invCellSize = 1.0f / cellSize;
|
||||||
_items = new Dictionary<long, List<DtCrowdAgent>>();
|
_items = new Dictionary<long, List<DtCrowdAgent>>();
|
||||||
_listPool = new RcObjectPool<List<DtCrowdAgent>>(() => new List<DtCrowdAgent>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
@ -60,8 +57,6 @@ namespace DotRecast.Detour.Crowd
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
foreach (var pair in _items)
|
|
||||||
_listPool.Return(pair.Value);
|
|
||||||
_items.Clear();
|
_items.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,8 +74,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
long key = CombineKey(x, y);
|
long key = CombineKey(x, y);
|
||||||
if (!_items.TryGetValue(key, out var ids))
|
if (!_items.TryGetValue(key, out var ids))
|
||||||
{
|
{
|
||||||
ids = _listPool.Get();
|
ids = new List<DtCrowdAgent>();
|
||||||
ids.Clear();
|
|
||||||
_items.Add(key, ids);
|
_items.Add(key, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +83,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int QueryItems(float minx, float miny, float maxx, float maxy, Span<int> ids, int maxIds)
|
public int QueryItems(float minx, float miny, float maxx, float maxy, DtCrowdAgent[] 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);
|
||||||
|
@ -116,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.idx)
|
while (i != end && ids[i] != item)
|
||||||
{
|
{
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
@ -124,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.idx;
|
ids[n++] = item;
|
||||||
|
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Detour.Dynamic",
|
|
||||||
"rootNamespace": "DotRecast.Detour.Dynamic",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Detour",
|
|
||||||
"DotRecast.Recast",
|
|
||||||
"DotRecast.Core"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": true
|
|
||||||
}
|
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -23,7 +23,6 @@ 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;
|
||||||
|
@ -41,7 +40,7 @@ namespace DotRecast.Detour.Dynamic
|
||||||
private readonly BlockingCollection<IDtDaynmicTileJob> updateQueue = new BlockingCollection<IDtDaynmicTileJob>();
|
private readonly BlockingCollection<IDtDaynmicTileJob> updateQueue = new BlockingCollection<IDtDaynmicTileJob>();
|
||||||
private readonly RcAtomicLong currentColliderId = new RcAtomicLong(0);
|
private readonly RcAtomicLong currentColliderId = new RcAtomicLong(0);
|
||||||
private DtNavMesh _navMesh;
|
private DtNavMesh _navMesh;
|
||||||
private bool _dirty = true;
|
private bool dirty = true;
|
||||||
|
|
||||||
public DtDynamicNavMesh(DtVoxelFile voxelFile)
|
public DtDynamicNavMesh(DtVoxelFile voxelFile)
|
||||||
{
|
{
|
||||||
|
@ -63,8 +62,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.useTiles ? voxelFile.cellSize * voxelFile.tileSizeX : voxelFile.bounds[3] - voxelFile.bounds[0];
|
navMeshParams.tileWidth = voxelFile.cellSize * voxelFile.tileSizeX;
|
||||||
navMeshParams.tileHeight = voxelFile.useTiles ? voxelFile.cellSize * voxelFile.tileSizeZ : voxelFile.bounds[5] - voxelFile.bounds[2];
|
navMeshParams.tileHeight = voxelFile.cellSize * voxelFile.tileSizeZ;
|
||||||
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)
|
||||||
|
@ -106,6 +105,29 @@ namespace DotRecast.Detour.Dynamic
|
||||||
updateQueue.Add(new DtDynamicTileColliderRemovalJob(colliderId, GetTilesByCollider(colliderId)));
|
updateQueue.Add(new DtDynamicTileColliderRemovalJob(colliderId, GetTilesByCollider(colliderId)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform full build of the nav mesh
|
||||||
|
*/
|
||||||
|
public void Build()
|
||||||
|
{
|
||||||
|
ProcessQueue();
|
||||||
|
Rebuild(_tiles.Values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform incremental update of the nav mesh
|
||||||
|
*/
|
||||||
|
public bool Update()
|
||||||
|
{
|
||||||
|
return Rebuild(ProcessQueue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Rebuild(ICollection<DtDynamicTile> stream)
|
||||||
|
{
|
||||||
|
foreach (var dynamicTile in stream)
|
||||||
|
Rebuild(dynamicTile);
|
||||||
|
return UpdateNavMesh();
|
||||||
|
}
|
||||||
|
|
||||||
private HashSet<DtDynamicTile> ProcessQueue()
|
private HashSet<DtDynamicTile> ProcessQueue()
|
||||||
{
|
{
|
||||||
|
@ -137,49 +159,27 @@ namespace DotRecast.Detour.Dynamic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform full build of the navmesh
|
/**
|
||||||
public void Build()
|
* Perform full build concurrently using the given {@link ExecutorService}
|
||||||
{
|
*/
|
||||||
ProcessQueue();
|
public Task<bool> Build(TaskFactory executor)
|
||||||
Rebuild(_tiles.Values);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform full build concurrently using the given {@link ExecutorService}
|
|
||||||
public bool Build(TaskFactory executor)
|
|
||||||
{
|
{
|
||||||
ProcessQueue();
|
ProcessQueue();
|
||||||
return Rebuild(_tiles.Values, executor);
|
return Rebuild(_tiles.Values, executor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
// Perform incremental update of the navmesh
|
* Perform incremental update concurrently using the given {@link ExecutorService}
|
||||||
public bool Update()
|
*/
|
||||||
{
|
public Task<bool> Update(TaskFactory executor)
|
||||||
return Rebuild(ProcessQueue());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform incremental update concurrently using the given {@link ExecutorService}
|
|
||||||
public bool Update(TaskFactory executor)
|
|
||||||
{
|
{
|
||||||
return Rebuild(ProcessQueue(), executor);
|
return Rebuild(ProcessQueue(), executor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Rebuild(ICollection<DtDynamicTile> tiles)
|
private Task<bool> Rebuild(ICollection<DtDynamicTile> tiles, TaskFactory executor)
|
||||||
{
|
{
|
||||||
foreach (var tile in tiles)
|
var tasks = tiles.Select(tile => executor.StartNew(() => Rebuild(tile))).ToArray();
|
||||||
Rebuild(tile);
|
return Task.WhenAll(tasks).ContinueWith(k => UpdateNavMesh());
|
||||||
|
|
||||||
return UpdateNavMesh();
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool Rebuild(ICollection<DtDynamicTile> tiles, TaskFactory executor)
|
|
||||||
{
|
|
||||||
var tasks = tiles
|
|
||||||
.Select(tile => executor.StartNew(() => Rebuild(tile)))
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
Task.WaitAll(tasks);
|
|
||||||
return UpdateNavMesh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ICollection<DtDynamicTile> GetTiles(float[] bounds)
|
private ICollection<DtDynamicTile> GetTiles(float[] bounds)
|
||||||
|
@ -189,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) - 1;
|
int minx = (int)MathF.Floor((bounds[0] - navMeshParams.orig.X) / navMeshParams.tileWidth);
|
||||||
int minz = (int)MathF.Floor((bounds[2] - navMeshParams.orig.Z) / navMeshParams.tileHeight) - 1;
|
int minz = (int)MathF.Floor((bounds[2] - navMeshParams.orig.Z) / navMeshParams.tileHeight);
|
||||||
int maxx = (int)MathF.Floor((bounds[3] - navMeshParams.orig.X) / navMeshParams.tileWidth) + 1;
|
int maxx = (int)MathF.Floor((bounds[3] - navMeshParams.orig.X) / navMeshParams.tileWidth);
|
||||||
int maxz = (int)MathF.Floor((bounds[5] - navMeshParams.orig.Z) / navMeshParams.tileHeight) + 1;
|
int maxz = (int)MathF.Floor((bounds[5] - navMeshParams.orig.Z) / navMeshParams.tileHeight);
|
||||||
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 && IntersectsXZ(tile, bounds))
|
if (tile != null)
|
||||||
{
|
{
|
||||||
tiles.Add(tile);
|
tiles.Add(tile);
|
||||||
}
|
}
|
||||||
|
@ -209,12 +209,6 @@ 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,24 +218,19 @@ namespace DotRecast.Detour.Dynamic
|
||||||
{
|
{
|
||||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||||
option.walkableHeight = config.walkableHeight;
|
option.walkableHeight = config.walkableHeight;
|
||||||
_dirty = _dirty | tile.Build(builder, config, _context);
|
dirty = dirty | tile.Build(builder, config, _context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool UpdateNavMesh()
|
private bool UpdateNavMesh()
|
||||||
{
|
{
|
||||||
if (_dirty)
|
if (dirty)
|
||||||
{
|
{
|
||||||
_dirty = false;
|
DtNavMesh navMesh = new DtNavMesh(navMeshParams, MAX_VERTS_PER_POLY);
|
||||||
|
|
||||||
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;
|
this._navMesh = navMesh;
|
||||||
|
dirty = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,21 +258,5 @@ 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -100,7 +100,7 @@ namespace DotRecast.Detour.Dynamic
|
||||||
Math.Min(DtDynamicNavMesh.MAX_VERTS_PER_POLY, config.vertsPerPoly),
|
Math.Min(DtDynamicNavMesh.MAX_VERTS_PER_POLY, config.vertsPerPoly),
|
||||||
config.detailSampleDistance, config.detailSampleMaxError,
|
config.detailSampleDistance, config.detailSampleMaxError,
|
||||||
true, true, true, default, true);
|
true, true, true, default, true);
|
||||||
RcBuilderResult r = builder.Build(context, vt.tileX, vt.tileZ, null, rcConfig, heightfield, false);
|
RcBuilderResult r = builder.Build(context, vt.tileX, vt.tileZ, null, rcConfig, heightfield);
|
||||||
if (config.keepIntermediateResults)
|
if (config.keepIntermediateResults)
|
||||||
{
|
{
|
||||||
recastResult = r;
|
recastResult = r;
|
||||||
|
@ -132,8 +132,8 @@ namespace DotRecast.Detour.Dynamic
|
||||||
private DtNavMeshCreateParams NavMeshCreateParams(int tilex, int tileZ, float cellSize, float cellHeight,
|
private DtNavMeshCreateParams NavMeshCreateParams(int tilex, int tileZ, float cellSize, float cellHeight,
|
||||||
DtDynamicNavMeshConfig config, RcBuilderResult rcResult)
|
DtDynamicNavMeshConfig config, RcBuilderResult rcResult)
|
||||||
{
|
{
|
||||||
RcPolyMesh m_pmesh = rcResult.Mesh;
|
RcPolyMesh m_pmesh = rcResult.GetMesh();
|
||||||
RcPolyMeshDetail m_dmesh = rcResult.MeshDetail;
|
RcPolyMeshDetail m_dmesh = rcResult.GetMeshDetail();
|
||||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||||
for (int i = 0; i < m_pmesh.npolys; ++i)
|
for (int i = 0; i < m_pmesh.npolys; ++i)
|
||||||
{
|
{
|
||||||
|
@ -168,12 +168,12 @@ namespace DotRecast.Detour.Dynamic
|
||||||
option.buildBvTree = true;
|
option.buildBvTree = true;
|
||||||
|
|
||||||
option.offMeshConCount = 0;
|
option.offMeshConCount = 0;
|
||||||
option.offMeshConVerts = Array.Empty<float>();
|
option.offMeshConVerts = new float[0];
|
||||||
option.offMeshConRad = Array.Empty<float>();
|
option.offMeshConRad = new float[0];
|
||||||
option.offMeshConDir = Array.Empty<int>();
|
option.offMeshConDir = new int[0];
|
||||||
option.offMeshConAreas = Array.Empty<int>();
|
option.offMeshConAreas = new int[0];
|
||||||
option.offMeshConFlags = Array.Empty<int>();
|
option.offMeshConFlags = new int[0];
|
||||||
option.offMeshConUserID = Array.Empty<int>();
|
option.offMeshConUserID = new int[0];
|
||||||
return option;
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ namespace DotRecast.Detour.Dynamic
|
||||||
{
|
{
|
||||||
if (meshData != null)
|
if (meshData != null)
|
||||||
{
|
{
|
||||||
navMesh.AddTile(meshData, 0, 0, out var id);
|
id = navMesh.AddTile(meshData, 0, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -189,10 +189,5 @@ 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -78,7 +78,7 @@ namespace DotRecast.Detour.Dynamic.Io
|
||||||
walkbableAreaMod, buildMeshDetail);
|
walkbableAreaMod, buildMeshDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DtVoxelFile From(RcConfig config, IList<RcBuilderResult> results)
|
public static DtVoxelFile From(RcConfig config, List<RcBuilderResult> results)
|
||||||
{
|
{
|
||||||
DtVoxelFile f = new DtVoxelFile();
|
DtVoxelFile f = new DtVoxelFile();
|
||||||
f.version = 1;
|
f.version = 1;
|
||||||
|
@ -109,14 +109,13 @@ 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.GetSolidHeightfield()));
|
||||||
f.tiles.Add(new DtVoxelTile(r.TileX, r.TileZ, r.SolidHeightfiled));
|
f.bounds[0] = Math.Min(f.bounds[0], r.GetSolidHeightfield().bmin.X);
|
||||||
f.bounds[0] = Math.Min(f.bounds[0], r.SolidHeightfiled.bmin.X + pad);
|
f.bounds[1] = Math.Min(f.bounds[1], r.GetSolidHeightfield().bmin.Y);
|
||||||
f.bounds[1] = Math.Min(f.bounds[1], r.SolidHeightfiled.bmin.Y);
|
f.bounds[2] = Math.Min(f.bounds[2], r.GetSolidHeightfield().bmin.Z);
|
||||||
f.bounds[2] = Math.Min(f.bounds[2], r.SolidHeightfiled.bmin.Z + pad);
|
f.bounds[3] = Math.Max(f.bounds[3], r.GetSolidHeightfield().bmax.X);
|
||||||
f.bounds[3] = Math.Max(f.bounds[3], r.SolidHeightfiled.bmax.X - pad);
|
f.bounds[4] = Math.Max(f.bounds[4], r.GetSolidHeightfield().bmax.Y);
|
||||||
f.bounds[4] = Math.Max(f.bounds[4], r.SolidHeightfiled.bmax.Y);
|
f.bounds[5] = Math.Max(f.bounds[5], r.GetSolidHeightfield().bmax.Z);
|
||||||
f.bounds[5] = Math.Max(f.bounds[5], r.SolidHeightfiled.bmax.Z - pad);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
|
@ -156,13 +155,12 @@ 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));
|
||||||
float pad = vt.borderSize * vt.cellSize;
|
f.bounds[0] = Math.Min(f.bounds[0], vt.boundsMin.X);
|
||||||
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 + pad);
|
f.bounds[2] = Math.Min(f.bounds[2], vt.boundsMin.Z);
|
||||||
f.bounds[3] = Math.Max(f.bounds[3], vt.boundsMax.X - pad);
|
f.bounds[3] = Math.Max(f.bounds[3], vt.boundsMax.X);
|
||||||
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 - pad);
|
f.bounds[5] = Math.Max(f.bounds[5], vt.boundsMax.Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -35,12 +35,12 @@ namespace DotRecast.Detour.Dynamic.Io
|
||||||
|
|
||||||
public DtVoxelFile Read(BinaryReader stream)
|
public DtVoxelFile Read(BinaryReader stream)
|
||||||
{
|
{
|
||||||
RcByteBuffer buf = RcIO.ToByteBuffer(stream);
|
RcByteBuffer buf = IOUtils.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 = RcIO.SwapEndianness(magic);
|
magic = IOUtils.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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -19,11 +19,12 @@ 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
|
public class DtVoxelFileWriter : DtWriter
|
||||||
{
|
{
|
||||||
private readonly IRcCompressor _compressor;
|
private readonly IRcCompressor _compressor;
|
||||||
|
|
||||||
|
@ -39,34 +40,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)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, DtVoxelFile.MAGIC, byteOrder);
|
Write(stream, DtVoxelFile.MAGIC, byteOrder);
|
||||||
RcIO.Write(stream, DtVoxelFile.VERSION_EXPORTER_RECAST4J | (compression ? DtVoxelFile.VERSION_COMPRESSION_LZ4 : 0), byteOrder);
|
Write(stream, DtVoxelFile.VERSION_EXPORTER_RECAST4J | (compression ? DtVoxelFile.VERSION_COMPRESSION_LZ4 : 0), byteOrder);
|
||||||
RcIO.Write(stream, f.walkableRadius, byteOrder);
|
Write(stream, f.walkableRadius, byteOrder);
|
||||||
RcIO.Write(stream, f.walkableHeight, byteOrder);
|
Write(stream, f.walkableHeight, byteOrder);
|
||||||
RcIO.Write(stream, f.walkableClimb, byteOrder);
|
Write(stream, f.walkableClimb, byteOrder);
|
||||||
RcIO.Write(stream, f.walkableSlopeAngle, byteOrder);
|
Write(stream, f.walkableSlopeAngle, byteOrder);
|
||||||
RcIO.Write(stream, f.cellSize, byteOrder);
|
Write(stream, f.cellSize, byteOrder);
|
||||||
RcIO.Write(stream, f.maxSimplificationError, byteOrder);
|
Write(stream, f.maxSimplificationError, byteOrder);
|
||||||
RcIO.Write(stream, f.maxEdgeLen, byteOrder);
|
Write(stream, f.maxEdgeLen, byteOrder);
|
||||||
RcIO.Write(stream, f.minRegionArea, byteOrder);
|
Write(stream, f.minRegionArea, byteOrder);
|
||||||
RcIO.Write(stream, f.regionMergeArea, byteOrder);
|
Write(stream, f.regionMergeArea, byteOrder);
|
||||||
RcIO.Write(stream, f.vertsPerPoly, byteOrder);
|
Write(stream, f.vertsPerPoly, byteOrder);
|
||||||
RcIO.Write(stream, f.buildMeshDetail);
|
Write(stream, f.buildMeshDetail);
|
||||||
RcIO.Write(stream, f.detailSampleDistance, byteOrder);
|
Write(stream, f.detailSampleDistance, byteOrder);
|
||||||
RcIO.Write(stream, f.detailSampleMaxError, byteOrder);
|
Write(stream, f.detailSampleMaxError, byteOrder);
|
||||||
RcIO.Write(stream, f.useTiles);
|
Write(stream, f.useTiles);
|
||||||
RcIO.Write(stream, f.tileSizeX, byteOrder);
|
Write(stream, f.tileSizeX, byteOrder);
|
||||||
RcIO.Write(stream, f.tileSizeZ, byteOrder);
|
Write(stream, f.tileSizeZ, byteOrder);
|
||||||
RcIO.Write(stream, f.rotation.X, byteOrder);
|
Write(stream, f.rotation.X, byteOrder);
|
||||||
RcIO.Write(stream, f.rotation.Y, byteOrder);
|
Write(stream, f.rotation.Y, byteOrder);
|
||||||
RcIO.Write(stream, f.rotation.Z, byteOrder);
|
Write(stream, f.rotation.Z, byteOrder);
|
||||||
RcIO.Write(stream, f.bounds[0], byteOrder);
|
Write(stream, f.bounds[0], byteOrder);
|
||||||
RcIO.Write(stream, f.bounds[1], byteOrder);
|
Write(stream, f.bounds[1], byteOrder);
|
||||||
RcIO.Write(stream, f.bounds[2], byteOrder);
|
Write(stream, f.bounds[2], byteOrder);
|
||||||
RcIO.Write(stream, f.bounds[3], byteOrder);
|
Write(stream, f.bounds[3], byteOrder);
|
||||||
RcIO.Write(stream, f.bounds[4], byteOrder);
|
Write(stream, f.bounds[4], byteOrder);
|
||||||
RcIO.Write(stream, f.bounds[5], byteOrder);
|
Write(stream, f.bounds[5], byteOrder);
|
||||||
RcIO.Write(stream, f.tiles.Count, byteOrder);
|
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);
|
||||||
|
@ -75,26 +76,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)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, tile.tileX, byteOrder);
|
Write(stream, tile.tileX, byteOrder);
|
||||||
RcIO.Write(stream, tile.tileZ, byteOrder);
|
Write(stream, tile.tileZ, byteOrder);
|
||||||
RcIO.Write(stream, tile.width, byteOrder);
|
Write(stream, tile.width, byteOrder);
|
||||||
RcIO.Write(stream, tile.depth, byteOrder);
|
Write(stream, tile.depth, byteOrder);
|
||||||
RcIO.Write(stream, tile.borderSize, byteOrder);
|
Write(stream, tile.borderSize, byteOrder);
|
||||||
RcIO.Write(stream, tile.boundsMin.X, byteOrder);
|
Write(stream, tile.boundsMin.X, byteOrder);
|
||||||
RcIO.Write(stream, tile.boundsMin.Y, byteOrder);
|
Write(stream, tile.boundsMin.Y, byteOrder);
|
||||||
RcIO.Write(stream, tile.boundsMin.Z, byteOrder);
|
Write(stream, tile.boundsMin.Z, byteOrder);
|
||||||
RcIO.Write(stream, tile.boundsMax.X, byteOrder);
|
Write(stream, tile.boundsMax.X, byteOrder);
|
||||||
RcIO.Write(stream, tile.boundsMax.Y, byteOrder);
|
Write(stream, tile.boundsMax.Y, byteOrder);
|
||||||
RcIO.Write(stream, tile.boundsMax.Z, byteOrder);
|
Write(stream, tile.boundsMax.Z, byteOrder);
|
||||||
RcIO.Write(stream, tile.cellSize, byteOrder);
|
Write(stream, tile.cellSize, byteOrder);
|
||||||
RcIO.Write(stream, tile.cellHeight, byteOrder);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
RcIO.Write(stream, bytes.Length, byteOrder);
|
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -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 = RcVec.Create(data.verts, data.polys[i].verts[0] * 3);
|
RcVec3f bmin = RcVecUtils.Create(data.verts, data.polys[i].verts[0] * 3);
|
||||||
RcVec3f bmax = RcVec.Create(data.verts, data.polys[i].verts[0] * 3);
|
RcVec3f bmax = RcVecUtils.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 = RcVec3f.Min(bmin, RcVec.Create(data.verts, data.polys[i].verts[j] * 3));
|
bmin = RcVecUtils.Min(bmin, data.verts, data.polys[i].verts[j] * 3);
|
||||||
bmax = RcVec3f.Max(bmax, RcVec.Create(data.verts, data.polys[i].verts[j] * 3));
|
bmax = RcVecUtils.Max(bmax, data.verts, data.polys[i].verts[j] * 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
it.bmin.X = Math.Clamp((int)((bmin.X - data.header.bmin.X) * quantFactor), 0, 0x7fffffff);
|
it.bmin[0] = Math.Clamp((int)((bmin.X - data.header.bmin.X) * quantFactor), 0, 0x7fffffff);
|
||||||
it.bmin.Y = Math.Clamp((int)((bmin.Y - data.header.bmin.Y) * quantFactor), 0, 0x7fffffff);
|
it.bmin[1] = Math.Clamp((int)((bmin.Y - data.header.bmin.Y) * quantFactor), 0, 0x7fffffff);
|
||||||
it.bmin.Z = Math.Clamp((int)((bmin.Z - data.header.bmin.Z) * quantFactor), 0, 0x7fffffff);
|
it.bmin[2] = Math.Clamp((int)((bmin.Z - data.header.bmin.Z) * quantFactor), 0, 0x7fffffff);
|
||||||
it.bmax.X = Math.Clamp((int)((bmax.X - data.header.bmin.X) * quantFactor), 0, 0x7fffffff);
|
it.bmax[0] = Math.Clamp((int)((bmax.X - data.header.bmin.X) * quantFactor), 0, 0x7fffffff);
|
||||||
it.bmax.Y = Math.Clamp((int)((bmax.Y - data.header.bmin.Y) * quantFactor), 0, 0x7fffffff);
|
it.bmax[1] = Math.Clamp((int)((bmax.Y - data.header.bmin.Y) * quantFactor), 0, 0x7fffffff);
|
||||||
it.bmax.Z = Math.Clamp((int)((bmax.Z - data.header.bmin.Z) * quantFactor), 0, 0x7fffffff);
|
it.bmax[2] = 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,18 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Detour.Extras",
|
|
||||||
"rootNamespace": "DotRecast.Detour.Extras",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Core",
|
|
||||||
"DotRecast.Detour",
|
|
||||||
"DotRecast.Recast"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": true
|
|
||||||
}
|
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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(RcVec.Dist2DSqr(es.start.p, es.start.q));
|
float dist = MathF.Sqrt(RcVecUtils.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,18 +1,17 @@
|
||||||
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 : ITrajectory
|
public class ClimbTrajectory : Trajectory
|
||||||
{
|
{
|
||||||
public RcVec3f Apply(RcVec3f start, RcVec3f end, float u)
|
public override RcVec3f Apply(RcVec3f start, RcVec3f end, float u)
|
||||||
{
|
{
|
||||||
return new RcVec3f()
|
return new RcVec3f()
|
||||||
{
|
{
|
||||||
X = RcMath.Lerp(start.X, end.X, Math.Min(2f * u, 1f)),
|
X = Lerp(start.X, end.X, Math.Min(2f * u, 1f)),
|
||||||
Y = RcMath.Lerp(start.Y, end.Y, Math.Max(0f, 2f * u - 1f)),
|
Y = Lerp(start.Y, end.Y, Math.Max(0f, 2f * u - 1f)),
|
||||||
Z = RcMath.Lerp(start.Z, end.Z, Math.Min(2f * u, 1f))
|
Z = 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)
|
||||||
|
|
|
@ -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 ITrajectory trajectory;
|
public readonly Trajectory 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, ITrajectory trajectory)
|
public EdgeSampler(JumpEdge edge, Trajectory 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
|
||||||
{
|
{
|
||||||
public class EdgeSamplerFactory
|
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;
|
public RcVec3f p = new RcVec3f();
|
||||||
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;
|
public RcVec3f p = new RcVec3f();
|
||||||
public RcVec3f q;
|
public RcVec3f q = new RcVec3f();
|
||||||
public GroundSample[] gsamples;
|
public GroundSample[] gsamples;
|
||||||
public float height;
|
public float height;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
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 ITrajectory trajectory;
|
public Trajectory trajectory;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,7 +21,7 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
public JumpLinkBuilder(IList<RcBuilderResult> results)
|
public JumpLinkBuilder(IList<RcBuilderResult> results)
|
||||||
{
|
{
|
||||||
this.results = results;
|
this.results = results;
|
||||||
edges = results.Select(r => edgeExtractor.ExtractEdges(r.Mesh)).ToList();
|
edges = results.Select(r => edgeExtractor.ExtractEdges(r.GetMesh())).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<JumpLink> Build(JumpLinkBuilderConfig acfg, JumpLinkType type)
|
public List<JumpLink> Build(JumpLinkBuilderConfig acfg, JumpLinkType type)
|
||||||
|
@ -43,7 +43,7 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
{
|
{
|
||||||
EdgeSampler es = edgeSamplerFactory.Get(acfg, type, edge);
|
EdgeSampler es = edgeSamplerFactory.Get(acfg, type, edge);
|
||||||
groundSampler.Sample(acfg, result, es);
|
groundSampler.Sample(acfg, result, es);
|
||||||
trajectorySampler.Sample(acfg, result.SolidHeightfiled, es);
|
trajectorySampler.Sample(acfg, result.GetSolidHeightfield(), es);
|
||||||
JumpSegment[] jumpSegments = jumpSegmentBuilder.Build(acfg, es);
|
JumpSegment[] jumpSegments = jumpSegmentBuilder.Build(acfg, es);
|
||||||
return BuildJumpLinks(acfg, es, jumpSegments);
|
return BuildJumpLinks(acfg, es, jumpSegments);
|
||||||
}
|
}
|
||||||
|
@ -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(RcVec.Dist2DSqr(sp, sq), RcVec.Dist2DSqr(ep, eq));
|
float d = Math.Min(RcVecUtils.Dist2DSqr(sp, sq), RcVecUtils.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
|
||||||
{
|
{
|
||||||
public class JumpSegmentBuilder
|
class JumpSegmentBuilder
|
||||||
{
|
{
|
||||||
public JumpSegment[] Build(JumpLinkBuilderConfig acfg, EdgeSampler es)
|
public JumpSegment[] Build(JumpLinkBuilderConfig acfg, EdgeSampler es)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
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 : ITrajectory
|
public class JumpTrajectory : Trajectory
|
||||||
{
|
{
|
||||||
private readonly float jumpHeight;
|
private readonly float jumpHeight;
|
||||||
|
|
||||||
|
@ -13,13 +12,13 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
this.jumpHeight = jumpHeight;
|
this.jumpHeight = jumpHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RcVec3f Apply(RcVec3f start, RcVec3f end, float u)
|
public override RcVec3f Apply(RcVec3f start, RcVec3f end, float u)
|
||||||
{
|
{
|
||||||
return new RcVec3f
|
return new RcVec3f
|
||||||
{
|
{
|
||||||
X = RcMath.Lerp(start.X, end.X, u),
|
X = Lerp(start.X, end.X, u),
|
||||||
Y = InterpolateHeight(start.Y, end.Y, u),
|
Y = InterpolateHeight(start.Y, end.Y, u),
|
||||||
Z = RcMath.Lerp(start.Z, end.Z, u)
|
Z = Lerp(start.Z, end.Z, u)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
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
|
||||||
{
|
{
|
||||||
public class NavMeshGroundSampler : AbstractGroundSampler
|
class NavMeshGroundSampler : AbstractGroundSampler
|
||||||
{
|
{
|
||||||
public override void Sample(JumpLinkBuilderConfig acfg, RcBuilderResult result, EdgeSampler es)
|
public override void Sample(JumpLinkBuilderConfig acfg, RcBuilderResult result, EdgeSampler es)
|
||||||
{
|
{
|
||||||
|
@ -15,34 +16,27 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
private DtNavMeshQuery CreateNavMesh(RcBuilderResult r, float agentRadius, float agentHeight, float agentClimb)
|
private DtNavMeshQuery CreateNavMesh(RcBuilderResult r, float agentRadius, float agentHeight, float agentClimb)
|
||||||
{
|
{
|
||||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||||
option.verts = r.Mesh.verts;
|
option.verts = r.GetMesh().verts;
|
||||||
option.vertCount = r.Mesh.nverts;
|
option.vertCount = r.GetMesh().nverts;
|
||||||
option.polys = r.Mesh.polys;
|
option.polys = r.GetMesh().polys;
|
||||||
option.polyAreas = r.Mesh.areas;
|
option.polyAreas = r.GetMesh().areas;
|
||||||
option.polyFlags = r.Mesh.flags;
|
option.polyFlags = r.GetMesh().flags;
|
||||||
option.polyCount = r.Mesh.npolys;
|
option.polyCount = r.GetMesh().npolys;
|
||||||
option.nvp = r.Mesh.nvp;
|
option.nvp = r.GetMesh().nvp;
|
||||||
option.detailMeshes = r.MeshDetail.meshes;
|
option.detailMeshes = r.GetMeshDetail().meshes;
|
||||||
option.detailVerts = r.MeshDetail.verts;
|
option.detailVerts = r.GetMeshDetail().verts;
|
||||||
option.detailVertsCount = r.MeshDetail.nverts;
|
option.detailVertsCount = r.GetMeshDetail().nverts;
|
||||||
option.detailTris = r.MeshDetail.tris;
|
option.detailTris = r.GetMeshDetail().tris;
|
||||||
option.detailTriCount = r.MeshDetail.ntris;
|
option.detailTriCount = r.GetMeshDetail().ntris;
|
||||||
option.walkableRadius = agentRadius;
|
option.walkableRadius = agentRadius;
|
||||||
option.walkableHeight = agentHeight;
|
option.walkableHeight = agentHeight;
|
||||||
option.walkableClimb = agentClimb;
|
option.walkableClimb = agentClimb;
|
||||||
option.bmin = r.Mesh.bmin;
|
option.bmin = r.GetMesh().bmin;
|
||||||
option.bmax = r.Mesh.bmax;
|
option.bmax = r.GetMesh().bmax;
|
||||||
option.cs = r.Mesh.cs;
|
option.cs = r.GetMesh().cs;
|
||||||
option.ch = r.Mesh.ch;
|
option.ch = r.GetMesh().ch;
|
||||||
option.buildBvTree = true;
|
option.buildBvTree = true;
|
||||||
var mesh = new DtNavMesh();
|
return new DtNavMeshQuery(new DtNavMesh(DtNavMeshBuilder.CreateNavMeshData(option), option.nvp, 0));
|
||||||
var status = mesh.Init(DtNavMeshBuilder.CreateNavMeshData(option), option.nvp, 0);
|
|
||||||
if (status.Failed())
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new DtNavMeshQuery(mesh);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,12 +46,25 @@ namespace DotRecast.Detour.Extras.Jumplink
|
||||||
|
|
||||||
RcVec3f halfExtents = new RcVec3f { X = cs, Y = heightRange, Z = cs };
|
RcVec3f halfExtents = new RcVec3f { X = cs, Y = heightRange, Z = cs };
|
||||||
float maxHeight = pt.Y + heightRange;
|
float maxHeight = pt.Y + heightRange;
|
||||||
var query = new DtHeightSamplePolyQuery(navMeshQuery, pt, pt.Y, maxHeight);
|
RcAtomicBoolean found = new RcAtomicBoolean();
|
||||||
navMeshQuery.QueryPolygons(pt, halfExtents, DtQueryNoOpFilter.Shared, ref query);
|
RcAtomicFloat minHeight = new RcAtomicFloat(pt.Y);
|
||||||
|
|
||||||
if (query.Found)
|
navMeshQuery.QueryPolygons(pt, halfExtents, DtQueryNoOpFilter.Shared, new PolyQueryInvoker((tile, poly, refs) =>
|
||||||
{
|
{
|
||||||
height = query.MinHeight;
|
var status = navMeshQuery.GetPolyHeight(refs, pt, out var h);
|
||||||
|
if (status.Succeeded())
|
||||||
|
{
|
||||||
|
if (h > minHeight.Get() && h < maxHeight)
|
||||||
|
{
|
||||||
|
minHeight.Exchange(h);
|
||||||
|
found.Set(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (found.Get())
|
||||||
|
{
|
||||||
|
height = minHeight.Get();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
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
|
||||||
{
|
{
|
||||||
public class TrajectorySampler
|
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, ITrajectory tra)
|
private bool SampleTrajectory(JumpLinkBuilderConfig acfg, RcHeightfield solid, RcVec3f pa, RcVec3f pb, Trajectory tra)
|
||||||
{
|
{
|
||||||
float cs = Math.Min(acfg.cellSize, acfg.cellHeight);
|
float cs = Math.Min(acfg.cellSize, acfg.cellHeight);
|
||||||
float d = RcVec.Dist2D(pa, pb) + MathF.Abs(pa.Y - pb.Y);
|
float d = RcVecUtils.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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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
|
||||||
|
@ -23,8 +22,6 @@ 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;
|
||||||
|
@ -79,7 +76,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 = Array.Empty<float>();
|
float[] detailVerts = new float[0];
|
||||||
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;
|
||||||
|
@ -101,9 +98,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;
|
||||||
byte vertCount = 0;
|
int vertCount = 0;
|
||||||
int triBase = i;
|
int triBase = i;
|
||||||
byte triCount = 1;
|
int 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;
|
||||||
|
@ -119,15 +116,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 = DT_NAVMESH_MAGIC;
|
header.magic = DtNavMesh.DT_NAVMESH_MAGIC;
|
||||||
header.version = DT_NAVMESH_VERSION;
|
header.version = DtNavMesh.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; // needed by Recast, not needed by recast4j, needed by DotRecast
|
header.maxLinkCount = nodeCount * 3 * 2; // XXX: Needed by Recast, not needed by recast4j
|
||||||
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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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,8 +21,6 @@ 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
|
||||||
|
@ -68,19 +65,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)] = DT_EXT_LINK;
|
node.neis[DtPolyUtils.FindEdge(node, tile, neighbourTile.header.bmin.X, 0)] = DtNavMesh.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)] = DT_EXT_LINK | 4;
|
node.neis[DtPolyUtils.FindEdge(node, tile, tile.header.bmin.X, 0)] = DtNavMesh.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)] = DT_EXT_LINK | 2;
|
node.neis[DtPolyUtils.FindEdge(node, tile, neighbourTile.header.bmin.Z, 2)] = DtNavMesh.DT_EXT_LINK | 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node.neis[DtPolyUtils.FindEdge(node, tile, tile.header.bmin.Z, 2)] = DT_EXT_LINK | 6;
|
node.neis[DtPolyUtils.FindEdge(node, tile, tile.header.bmin.Z, 2)] = DtNavMesh.DT_EXT_LINK | 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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
|
||||||
|
@ -66,11 +65,10 @@ 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();
|
DtNavMesh mesh = new DtNavMesh(option, 3);
|
||||||
mesh.Init(option, 3);
|
|
||||||
foreach (DtMeshData t in graphMeshData.tiles)
|
foreach (DtMeshData t in graphMeshData.tiles)
|
||||||
{
|
{
|
||||||
mesh.AddTile(t, 0, 0, out _);
|
mesh.AddTile(t, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,7 +31,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 = RcIO.ToByteBuffer(br);
|
RcByteBuffer buffer = IOUtils.ToByteBuffer(br);
|
||||||
buffer.Order(RcByteOrder.LITTLE_ENDIAN);
|
buffer.Order(RcByteOrder.LITTLE_ENDIAN);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Detour.TileCache",
|
|
||||||
"rootNamespace": "DotRecast.Detour.TileCache",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Core",
|
|
||||||
"DotRecast.Detour",
|
|
||||||
"DotRecast.Recast"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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,9 +7,8 @@ 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 byte[] neis = new byte[DT_LAYER_MAX_NEIS];
|
public List<int> neis = new List<int>(DT_LAYER_MAX_NEIS);
|
||||||
public byte nneis;
|
public int regId;
|
||||||
public byte regId;
|
public int areaId;
|
||||||
public byte areaId;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,10 +0,0 @@
|
||||||
using DotRecast.Core.Numerics;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache
|
|
||||||
{
|
|
||||||
public class DtObstacleBox
|
|
||||||
{
|
|
||||||
public RcVec3f bmin;
|
|
||||||
public RcVec3f bmax;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
using DotRecast.Core.Numerics;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache
|
|
||||||
{
|
|
||||||
public class DtObstacleCylinder
|
|
||||||
{
|
|
||||||
public RcVec3f pos;
|
|
||||||
public float radius;
|
|
||||||
public float height;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -26,8 +26,6 @@ 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).
|
||||||
|
@ -53,6 +51,9 @@ 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;
|
||||||
|
@ -159,7 +160,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 = ComputeTileHash(tx, ty, m_tileLutMask);
|
int h = DtNavMesh.ComputeTileHash(tx, ty, m_tileLutMask);
|
||||||
DtCompressedTile tile = m_posLookup[h];
|
DtCompressedTile tile = m_posLookup[h];
|
||||||
while (tile != null)
|
while (tile != null)
|
||||||
{
|
{
|
||||||
|
@ -177,7 +178,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 = ComputeTileHash(tx, ty, m_tileLutMask);
|
int h = DtNavMesh.ComputeTileHash(tx, ty, m_tileLutMask);
|
||||||
DtCompressedTile tile = m_posLookup[h];
|
DtCompressedTile tile = m_posLookup[h];
|
||||||
while (tile != null)
|
while (tile != null)
|
||||||
{
|
{
|
||||||
|
@ -242,7 +243,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 = DtTileCacheLayerHeaderReader.Read(buf, m_storageParams.Compatibility);
|
DtTileCacheLayerHeader header = tileReader.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)
|
||||||
{
|
{
|
||||||
|
@ -265,7 +266,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert tile into the position lut.
|
// Insert tile into the position lut.
|
||||||
int h = ComputeTileHash(header.tx, header.ty, m_tileLutMask);
|
int h = DtNavMesh.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;
|
||||||
|
|
||||||
|
@ -304,7 +305,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove tile from hash lookup.
|
// Remove tile from hash lookup.
|
||||||
int h = ComputeTileHash(tile.header.tx, tile.header.ty, m_tileLutMask);
|
int h = DtNavMesh.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)
|
||||||
|
@ -348,11 +349,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.DT_OBSTACLE_CYLINDER;
|
ob.type = DtTileCacheObstacleType.CYLINDER;
|
||||||
|
|
||||||
ob.cylinder.pos = pos;
|
ob.pos = pos;
|
||||||
ob.cylinder.radius = radius;
|
ob.radius = radius;
|
||||||
ob.cylinder.height = height;
|
ob.height = height;
|
||||||
|
|
||||||
return AddObstacleRequest(ob).refs;
|
return AddObstacleRequest(ob).refs;
|
||||||
}
|
}
|
||||||
|
@ -361,10 +362,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.DT_OBSTACLE_BOX;
|
ob.type = DtTileCacheObstacleType.BOX;
|
||||||
|
|
||||||
ob.box.bmin = bmin;
|
ob.bmin = bmin;
|
||||||
ob.box.bmax = bmax;
|
ob.bmax = bmax;
|
||||||
|
|
||||||
return AddObstacleRequest(ob).refs;
|
return AddObstacleRequest(ob).refs;
|
||||||
}
|
}
|
||||||
|
@ -373,13 +374,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.DT_OBSTACLE_ORIENTED_BOX;
|
ob.type = DtTileCacheObstacleType.ORIENTED_BOX;
|
||||||
ob.orientedBox.center = center;
|
ob.center = center;
|
||||||
ob.orientedBox.extents = extents;
|
ob.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.orientedBox.rotAux[0] = coshalf * sinhalf;
|
ob.rotAux[0] = coshalf * sinhalf;
|
||||||
ob.orientedBox.rotAux[1] = coshalf * coshalf - 0.5f;
|
ob.rotAux[1] = coshalf * coshalf - 0.5f;
|
||||||
return AddObstacleRequest(ob).refs;
|
return AddObstacleRequest(ob).refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,26 +613,26 @@ namespace DotRecast.Detour.TileCache
|
||||||
|
|
||||||
if (Contains(ob.touched, refs))
|
if (Contains(ob.touched, refs))
|
||||||
{
|
{
|
||||||
if (ob.type == DtTileCacheObstacleType.DT_OBSTACLE_CYLINDER)
|
if (ob.type == DtTileCacheObstacleType.CYLINDER)
|
||||||
{
|
{
|
||||||
DtTileCacheBuilder.MarkCylinderArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.cylinder.pos, ob.cylinder.radius, ob.cylinder.height, 0);
|
builder.MarkCylinderArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.pos, ob.radius, ob.height, 0);
|
||||||
}
|
}
|
||||||
else if (ob.type == DtTileCacheObstacleType.DT_OBSTACLE_BOX)
|
else if (ob.type == DtTileCacheObstacleType.BOX)
|
||||||
{
|
{
|
||||||
DtTileCacheBuilder.MarkBoxArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.box.bmin, ob.box.bmax, 0);
|
builder.MarkBoxArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.bmin, ob.bmax, 0);
|
||||||
}
|
}
|
||||||
else if (ob.type == DtTileCacheObstacleType.DT_OBSTACLE_ORIENTED_BOX)
|
else if (ob.type == DtTileCacheObstacleType.ORIENTED_BOX)
|
||||||
{
|
{
|
||||||
DtTileCacheBuilder.MarkBoxArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.orientedBox.center, ob.orientedBox.extents, ob.orientedBox.rotAux, 0);
|
builder.MarkBoxArea(layer, tile.header.bmin, m_params.cs, m_params.ch, ob.center, ob.extents, ob.rotAux, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build navmesh
|
// Build navmesh
|
||||||
DtTileCacheBuilder.BuildTileCacheRegions(layer, walkableClimbVx);
|
builder.BuildTileCacheRegions(layer, walkableClimbVx);
|
||||||
DtTileCacheContourSet lcset = DtTileCacheBuilder.BuildTileCacheContours(layer, walkableClimbVx, m_params.maxSimplificationError);
|
DtTileCacheContourSet lcset = builder.BuildTileCacheContours(layer, walkableClimbVx,
|
||||||
DtTileCachePolyMesh polyMesh = DtTileCacheBuilder.BuildTileCachePolyMesh(lcset, m_navmesh.GetMaxVertsPerPoly());
|
m_params.maxSimplificationError);
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
|
@ -669,13 +670,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, out var result);
|
m_navmesh.AddTile(meshData, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtTileCacheLayer DecompressTile(DtCompressedTile tile)
|
public DtTileCacheLayer DecompressTile(DtCompressedTile tile)
|
||||||
{
|
{
|
||||||
DtTileCacheLayer layer = DtTileCacheBuilder.DecompressTileCacheLayer(m_tcomp, tile.data, m_storageParams.Order, m_storageParams.Compatibility);
|
DtTileCacheLayer layer = builder.DecompressTileCacheLayer(m_tcomp, tile.data, m_storageParams.Order, m_storageParams.Compatibility);
|
||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -692,29 +693,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.DT_OBSTACLE_CYLINDER)
|
if (ob.type == DtTileCacheObstacleType.CYLINDER)
|
||||||
{
|
{
|
||||||
bmin.X = ob.cylinder.pos.X - ob.cylinder.radius;
|
bmin.X = ob.pos.X - ob.radius;
|
||||||
bmin.Y = ob.cylinder.pos.Y;
|
bmin.Y = ob.pos.Y;
|
||||||
bmin.Z = ob.cylinder.pos.Z - ob.cylinder.radius;
|
bmin.Z = ob.pos.Z - ob.radius;
|
||||||
bmax.X = ob.cylinder.pos.X + ob.cylinder.radius;
|
bmax.X = ob.pos.X + ob.radius;
|
||||||
bmax.Y = ob.cylinder.pos.Y + ob.cylinder.height;
|
bmax.Y = ob.pos.Y + ob.height;
|
||||||
bmax.Z = ob.cylinder.pos.Z + ob.cylinder.radius;
|
bmax.Z = ob.pos.Z + ob.radius;
|
||||||
}
|
}
|
||||||
else if (ob.type == DtTileCacheObstacleType.DT_OBSTACLE_BOX)
|
else if (ob.type == DtTileCacheObstacleType.BOX)
|
||||||
{
|
{
|
||||||
bmin = ob.box.bmin;
|
bmin = ob.bmin;
|
||||||
bmax = ob.box.bmax;
|
bmax = ob.bmax;
|
||||||
}
|
}
|
||||||
else if (ob.type == DtTileCacheObstacleType.DT_OBSTACLE_ORIENTED_BOX)
|
else if (ob.type == DtTileCacheObstacleType.ORIENTED_BOX)
|
||||||
{
|
{
|
||||||
float maxr = 1.41f * Math.Max(ob.orientedBox.extents.X, ob.orientedBox.extents.Z);
|
float maxr = 1.41f * Math.Max(ob.extents.X, ob.extents.Z);
|
||||||
bmin.X = ob.orientedBox.center.X - maxr;
|
bmin.X = ob.center.X - maxr;
|
||||||
bmax.X = ob.orientedBox.center.X + maxr;
|
bmax.X = ob.center.X + maxr;
|
||||||
bmin.Y = ob.orientedBox.center.Y - ob.orientedBox.extents.Y;
|
bmin.Y = ob.center.Y - ob.extents.Y;
|
||||||
bmax.Y = ob.orientedBox.center.Y + ob.orientedBox.extents.Y;
|
bmax.Y = ob.center.Y + ob.extents.Y;
|
||||||
bmin.Z = ob.orientedBox.center.Z - maxr;
|
bmin.Z = ob.center.Z - maxr;
|
||||||
bmax.Z = ob.orientedBox.center.Z + maxr;
|
bmax.Z = ob.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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -29,21 +29,22 @@ using DotRecast.Recast;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache
|
namespace DotRecast.Detour.TileCache
|
||||||
{
|
{
|
||||||
public static class DtTileCacheBuilder
|
public class DtTileCacheBuilder
|
||||||
{
|
{
|
||||||
public const byte DT_TILECACHE_NULL_AREA = 0;
|
public const int DT_TILECACHE_NULL_AREA = 0;
|
||||||
public const byte DT_TILECACHE_WALKABLE_AREA = 63;
|
public const int 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 };
|
||||||
|
|
||||||
public static void BuildTileCacheRegions(DtTileCacheLayer layer, int walkableClimb)
|
private readonly DtTileCacheLayerHeaderReader reader = new DtTileCacheLayerHeaderReader();
|
||||||
|
|
||||||
|
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, (byte)0xFF);
|
Array.Fill(layer.regs, (short)0x00FF);
|
||||||
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++)
|
||||||
|
@ -52,14 +53,14 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
|
|
||||||
// Partition walkable area into monotone regions.
|
// Partition walkable area into monotone regions.
|
||||||
Span<byte> prevCount = stackalloc byte[256];
|
int[] prevCount = new int[256];
|
||||||
byte regId = 0;
|
int regId = 0;
|
||||||
|
|
||||||
for (int y = 0; y < h; ++y)
|
for (int y = 0; y < h; ++y)
|
||||||
{
|
{
|
||||||
if (regId > 0)
|
if (regId > 0)
|
||||||
{
|
{
|
||||||
RcSpans.Fill<byte>(prevCount, 0, 0, regId);
|
Array.Fill(prevCount, 0, 0, regId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Memset(prevCount,0,Sizeof(char)*regId);
|
// Memset(prevCount,0,Sizeof(char)*regId);
|
||||||
|
@ -92,7 +93,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))
|
||||||
{
|
{
|
||||||
byte nr = layer.regs[yidx];
|
int nr = layer.regs[yidx];
|
||||||
if (nr != 0xff)
|
if (nr != 0xff)
|
||||||
{
|
{
|
||||||
// Set neighbour when first valid neighbour is
|
// Set neighbour when first valid neighbour is
|
||||||
|
@ -146,12 +147,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] = sweeps[layer.regs[idx]].id;
|
layer.regs[idx] = (short)sweeps[layer.regs[idx]].id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate and init layer regions.
|
// Allocate and init layer regions.
|
||||||
byte nregs = regId;
|
int 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)
|
||||||
|
@ -166,7 +167,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;
|
||||||
byte ri = layer.regs[idx];
|
int ri = layer.regs[idx];
|
||||||
if (ri == 0xff)
|
if (ri == 0xff)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -178,17 +179,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))
|
||||||
{
|
{
|
||||||
byte rai = layer.regs[ymi];
|
int rai = layer.regs[ymi];
|
||||||
if (rai != 0xff && rai != ri)
|
if (rai != 0xff && rai != ri)
|
||||||
{
|
{
|
||||||
AddUniqueLast(regs[ri].neis, ref regs[ri].nneis, rai);
|
AddUniqueLast(regs[ri].neis, rai);
|
||||||
AddUniqueLast(regs[rai].neis, ref regs[rai].nneis, ri);
|
AddUniqueLast(regs[rai].neis, ri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (byte i = 0; i < nregs; ++i)
|
for (int 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)
|
||||||
|
@ -197,9 +198,8 @@ namespace DotRecast.Detour.TileCache
|
||||||
|
|
||||||
int merge = -1;
|
int merge = -1;
|
||||||
int mergea = 0;
|
int mergea = 0;
|
||||||
for (int j = 0; j < reg.nneis; ++j)
|
foreach (int nei in reg.neis)
|
||||||
{
|
{
|
||||||
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;
|
||||||
byte newId = regs[merge].regId;
|
int 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.
|
||||||
Span<byte> remap = stackalloc byte[256];
|
int[] remap = new int[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,20 +243,19 @@ 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] = regs[layer.regs[i]].regId;
|
layer.regs[i] = (short)regs[layer.regs[i]].regId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddUniqueLast(byte[] a, ref byte an, byte v)
|
void AddUniqueLast(List<int> a, int v)
|
||||||
{
|
{
|
||||||
int n = an;
|
int n = a.Count;
|
||||||
if (n > 0 && a[n - 1] == v)
|
if (n > 0 && a[n - 1] == v)
|
||||||
return;
|
return;
|
||||||
a[an] = v;
|
a.Add(v);
|
||||||
an++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsConnected(DtTileCacheLayer layer, int ia, int ib, int walkableClimb)
|
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;
|
||||||
|
@ -265,7 +264,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool CanMerge(int oldRegId, int newRegId, DtLayerMonotoneRegion[] regs, int nregs)
|
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)
|
||||||
|
@ -273,11 +272,9 @@ 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[reg.neis[j]].regId == newRegId)
|
if (regs[nei].regId == newRegId)
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,7 +282,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return count == 1;
|
return count == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AppendVertex(DtTempContour cont, int x, int y, int z, int r)
|
private 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)
|
||||||
|
@ -319,7 +316,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
cont.nverts++;
|
cont.nverts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetNeighbourReg(DtTileCacheLayer layer, int ax, int ay, int dir)
|
private 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;
|
||||||
|
@ -342,17 +339,17 @@ namespace DotRecast.Detour.TileCache
|
||||||
return layer.regs[ib];
|
return layer.regs[ib];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetDirOffsetX(int dir)
|
private int GetDirOffsetX(int dir)
|
||||||
{
|
{
|
||||||
return DirOffsetX[dir & 0x03];
|
return DirOffsetX[dir & 0x03];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetDirOffsetY(int dir)
|
private int GetDirOffsetY(int dir)
|
||||||
{
|
{
|
||||||
return DirOffsetY[dir & 0x03];
|
return DirOffsetY[dir & 0x03];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void WalkContour(DtTileCacheLayer layer, int x, int y, DtTempContour cont)
|
private 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;
|
||||||
|
@ -437,7 +434,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
cont.nverts--;
|
cont.nverts--;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float DistancePtSeg(int x, int z, int px, int pz, int qx, int qz)
|
private 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;
|
||||||
|
@ -458,7 +455,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return dx * dx + dz * dz;
|
return dx * dx + dz * dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SimplifyContour(DtTempContour cont, float maxError)
|
private void SimplifyContour(DtTempContour cont, float maxError)
|
||||||
{
|
{
|
||||||
cont.poly.Clear();
|
cont.poly.Clear();
|
||||||
|
|
||||||
|
@ -587,7 +584,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetCornerHeight(DtTileCacheLayer layer, int x, int y, int z, int walkableClimb, out bool shouldRemove)
|
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;
|
||||||
|
@ -637,7 +634,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 static DtTileCacheContourSet BuildTileCacheContours(DtTileCacheLayer layer, int walkableClimb, float maxError)
|
public 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;
|
||||||
|
@ -659,7 +656,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;
|
||||||
byte ri = layer.regs[idx];
|
int ri = layer.regs[idx];
|
||||||
if (ri == 0xff)
|
if (ri == 0xff)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -714,7 +711,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
|
|
||||||
const uint VERTEX_BUCKET_COUNT2 = (1 << 8);
|
const uint VERTEX_BUCKET_COUNT2 = (1 << 8);
|
||||||
|
|
||||||
public static int ComputeVertexHash2(int x, int y, int z)
|
private 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
|
||||||
|
@ -723,7 +720,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return (int)(n & (VERTEX_BUCKET_COUNT2 - 1));
|
return (int)(n & (VERTEX_BUCKET_COUNT2 - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int AddVertex(int x, int y, int z, int[] verts, int[] firstVert, int[] nextVert, int nv)
|
private 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];
|
||||||
|
@ -746,7 +743,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void BuildMeshAdjacency(int[] polys, int npolys, int[] verts, int nverts, DtTileCacheContourSet lcset,
|
private 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:
|
||||||
|
@ -957,22 +954,22 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool OverlapRangeExl(int amin, int amax, int bmin, int bmax)
|
private bool OverlapRangeExl(int amin, int amax, int bmin, int bmax)
|
||||||
{
|
{
|
||||||
return (amin >= bmax || amax <= bmin) ? false : true;
|
return (amin >= bmax || amax <= bmin) ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int Prev(int i, int n)
|
private int Prev(int i, int n)
|
||||||
{
|
{
|
||||||
return i - 1 >= 0 ? i - 1 : n - 1;
|
return i - 1 >= 0 ? i - 1 : n - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int Next(int i, int n)
|
private int Next(int i, int n)
|
||||||
{
|
{
|
||||||
return i + 1 < n ? i + 1 : 0;
|
return i + 1 < n ? i + 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int Area2(int[] verts, int a, int b, int c)
|
private 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]);
|
||||||
|
@ -980,17 +977,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.
|
||||||
public static bool Left(int[] verts, int a, int b, int c)
|
private bool Left(int[] verts, int a, int b, int c)
|
||||||
{
|
{
|
||||||
return Area2(verts, a, b, c) < 0;
|
return Area2(verts, a, b, c) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool LeftOn(int[] verts, int a, int b, int c)
|
private bool LeftOn(int[] verts, int a, int b, int c)
|
||||||
{
|
{
|
||||||
return Area2(verts, a, b, c) <= 0;
|
return Area2(verts, a, b, c) <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool Collinear(int[] verts, int a, int b, int c)
|
private bool Collinear(int[] verts, int a, int b, int c)
|
||||||
{
|
{
|
||||||
return Area2(verts, a, b, c) == 0;
|
return Area2(verts, a, b, c) == 0;
|
||||||
}
|
}
|
||||||
|
@ -998,7 +995,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.
|
||||||
public static bool IntersectProp(int[] verts, int a, int b, int c, int d)
|
private 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)
|
||||||
|
@ -1010,7 +1007,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.
|
||||||
public static bool Between(int[] verts, int a, int b, int c)
|
private 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;
|
||||||
|
@ -1024,7 +1021,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.
|
||||||
public static bool Intersect(int[] verts, int a, int b, int c, int d)
|
private 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;
|
||||||
|
@ -1035,14 +1032,14 @@ namespace DotRecast.Detour.TileCache
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool Vequal(int[] verts, int a, int b)
|
private 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*.
|
||||||
public static bool Diagonalie(int i, int j, int n, int[] verts, int[] indices)
|
private 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;
|
||||||
|
@ -1070,7 +1067,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.
|
||||||
public static bool InCone(int i, int j, int n, int[] verts, int[] indices)
|
private 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;
|
||||||
|
@ -1087,12 +1084,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.
|
||||||
public static bool Diagonal(int i, int j, int n, int[] verts, int[] indices)
|
private 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int Triangulate(int n, int[] verts, int[] indices, int[] tris)
|
private int Triangulate(int n, int[] verts, int[] indices, int[] tris)
|
||||||
{
|
{
|
||||||
int ntris = 0;
|
int ntris = 0;
|
||||||
int dst = 0; // tris;
|
int dst = 0; // tris;
|
||||||
|
@ -1177,7 +1174,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return ntris;
|
return ntris;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int CountPolyVerts(int[] polys, int p, int maxVertsPerPoly)
|
private 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)
|
||||||
|
@ -1185,13 +1182,13 @@ namespace DotRecast.Detour.TileCache
|
||||||
return maxVertsPerPoly;
|
return maxVertsPerPoly;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool Uleft(int[] verts, int a, int b, int c)
|
private 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetPolyMergeValue(int[] polys, int pa, int pb, int[] verts, out int ea, out int eb, int maxVertsPerPoly)
|
private 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;
|
||||||
|
@ -1262,7 +1259,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return (dx * dx) + (dy * dy);
|
return (dx * dx) + (dy * dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void MergePolys(int[] polys, int pa, int pb, int ea, int eb, int maxVertsPerPoly)
|
private 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];
|
||||||
|
|
||||||
|
@ -1281,19 +1278,19 @@ namespace DotRecast.Detour.TileCache
|
||||||
RcArrays.Copy(tmp, 0, polys, pa, maxVertsPerPoly);
|
RcArrays.Copy(tmp, 0, polys, pa, maxVertsPerPoly);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int PushFront(int v, List<int> arr)
|
private int PushFront(int v, List<int> arr)
|
||||||
{
|
{
|
||||||
arr.Insert(0, v);
|
arr.Insert(0, v);
|
||||||
return arr.Count;
|
return arr.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int PushBack(int v, List<int> arr)
|
private int PushBack(int v, List<int> arr)
|
||||||
{
|
{
|
||||||
arr.Add(v);
|
arr.Add(v);
|
||||||
return arr.Count;
|
return arr.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool CanRemoveVertex(DtTileCachePolyMesh mesh, int rem)
|
private 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;
|
||||||
|
@ -1391,7 +1388,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RemoveVertex(DtTileCachePolyMesh mesh, int rem, int maxTris)
|
private 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;
|
||||||
|
@ -1630,7 +1627,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DtTileCachePolyMesh BuildTileCachePolyMesh(DtTileCacheContourSet lcset, int maxVertsPerPoly)
|
public DtTileCachePolyMesh BuildTileCachePolyMesh(DtTileCacheContourSet lcset, int maxVertsPerPoly)
|
||||||
{
|
{
|
||||||
int maxVertices = 0;
|
int maxVertices = 0;
|
||||||
int maxTris = 0;
|
int maxTris = 0;
|
||||||
|
@ -1804,7 +1801,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void MarkCylinderArea(DtTileCacheLayer layer, RcVec3f orig, float cs, float ch, RcVec3f pos, float radius, float height, byte areaId)
|
public void MarkCylinderArea(DtTileCacheLayer layer, RcVec3f orig, float cs, float ch, RcVec3f pos, float radius, float height, int areaId)
|
||||||
{
|
{
|
||||||
RcVec3f bmin = new RcVec3f();
|
RcVec3f bmin = new RcVec3f();
|
||||||
RcVec3f bmax = new RcVec3f();
|
RcVec3f bmax = new RcVec3f();
|
||||||
|
@ -1860,12 +1857,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] = areaId;
|
layer.areas[x + z * w] = (short)areaId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void MarkBoxArea(DtTileCacheLayer layer, RcVec3f orig, float cs, float ch, RcVec3f bmin, RcVec3f bmax, byte areaId)
|
public void MarkBoxArea(DtTileCacheLayer layer, RcVec3f orig, float cs, float ch, RcVec3f bmin, RcVec3f bmax, int areaId)
|
||||||
{
|
{
|
||||||
int w = layer.header.width;
|
int w = layer.header.width;
|
||||||
int h = layer.header.height;
|
int h = layer.header.height;
|
||||||
|
@ -1904,12 +1901,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] = areaId;
|
layer.areas[x + z * w] = (short)areaId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] CompressTileCacheLayer(IRcCompressor comp, DtTileCacheLayer layer, RcByteOrder order, bool cCompatibility)
|
public 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);
|
||||||
|
@ -1936,7 +1933,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] CompressTileCacheLayer(DtTileCacheLayerHeader header, int[] heights, int[] areas, int[] cons, RcByteOrder order, bool cCompatibility, IRcCompressor comp)
|
public 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);
|
||||||
|
@ -1963,14 +1960,14 @@ namespace DotRecast.Detour.TileCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DtTileCacheLayer DecompressTileCacheLayer(IRcCompressor comp, byte[] compressed, RcByteOrder order, bool cCompatibility)
|
public 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 = DtTileCacheLayerHeaderReader.Read(buf, cCompatibility);
|
layer.header = reader.Read(buf, cCompatibility);
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
|
@ -1979,22 +1976,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 byte[gridSize];
|
layer.heights = new short[gridSize];
|
||||||
layer.areas = new byte[gridSize];
|
layer.areas = new short[gridSize];
|
||||||
layer.cons = new byte[gridSize];
|
layer.cons = new short[gridSize];
|
||||||
layer.regs = new byte[gridSize];
|
layer.regs = new short[gridSize];
|
||||||
for (int i = 0; i < gridSize; i++)
|
for (int i = 0; i < gridSize; i++)
|
||||||
{
|
{
|
||||||
layer.heights[i] = (byte)(grids[i] & 0xFF);
|
layer.heights[i] = (short)(grids[i] & 0xFF);
|
||||||
layer.areas[i] = (byte)(grids[i + gridSize] & 0xFF);
|
layer.areas[i] = (short)(grids[i + gridSize] & 0xFF);
|
||||||
layer.cons[i] = (byte)(grids[i + gridSize * 2] & 0xFF);
|
layer.cons[i] = (short)(grids[i + gridSize * 2] & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void MarkBoxArea(DtTileCacheLayer layer, RcVec3f orig, float cs, float ch, RcVec3f center, RcVec3f extents,
|
public void MarkBoxArea(DtTileCacheLayer layer, RcVec3f orig, float cs, float ch, RcVec3f center, RcVec3f extents,
|
||||||
float[] rotAux, byte areaId)
|
float[] rotAux, int areaId)
|
||||||
{
|
{
|
||||||
int w = layer.header.width;
|
int w = layer.header.width;
|
||||||
int h = layer.header.height;
|
int h = layer.header.height;
|
||||||
|
@ -2047,7 +2044,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] = areaId;
|
layer.areas[x + z * w] = (short)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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -24,7 +24,7 @@ namespace DotRecast.Detour.TileCache
|
||||||
{
|
{
|
||||||
public int nverts;
|
public int nverts;
|
||||||
public int[] verts;
|
public int[] verts;
|
||||||
public byte reg;
|
public int reg;
|
||||||
public byte area;
|
public int 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -23,10 +23,13 @@ namespace DotRecast.Detour.TileCache
|
||||||
public class DtTileCacheLayer
|
public class DtTileCacheLayer
|
||||||
{
|
{
|
||||||
public DtTileCacheLayerHeader header;
|
public DtTileCacheLayerHeader header;
|
||||||
public byte regCount; // < Region count.
|
public int regCount;
|
||||||
public byte[] heights; // unsigned char
|
|
||||||
public byte[] areas; // unsigned char
|
/// < Region count.
|
||||||
public byte[] cons; // unsigned char
|
public short[] heights; // 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -100,6 +100,7 @@ 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];
|
||||||
|
@ -127,7 +128,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 = DtTileCacheBuilder.CompressTileCacheLayer(header, layer.heights, layer.areas, layer.cons, storageParams.Order, storageParams.Compatibility, comp);
|
var bytes = builder.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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -19,28 +19,32 @@ 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 DtObstacleCylinder cylinder = new DtObstacleCylinder();
|
public RcVec3f pos = new RcVec3f();
|
||||||
public DtObstacleBox box = new DtObstacleBox();
|
public RcVec3f bmin = new RcVec3f();
|
||||||
public DtObstacleOrientedBox orientedBox = new DtObstacleOrientedBox();
|
public RcVec3f bmax = new RcVec3f();
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
this.index = index;
|
|
||||||
salt = 1;
|
salt = 1;
|
||||||
|
this.index = index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
namespace DotRecast.Detour.TileCache
|
namespace DotRecast.Detour.TileCache
|
||||||
{
|
{
|
||||||
public enum DtTileCacheObstacleType
|
public enum DtTileCacheObstacleType
|
||||||
{
|
{
|
||||||
DT_OBSTACLE_CYLINDER,
|
CYLINDER,
|
||||||
DT_OBSTACLE_BOX, // AABB
|
BOX,
|
||||||
DT_OBSTACLE_ORIENTED_BOX // OBB
|
ORIENTED_BOX
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -23,13 +23,24 @@ namespace DotRecast.Detour.TileCache
|
||||||
public class DtTileCachePolyMesh
|
public class DtTileCachePolyMesh
|
||||||
{
|
{
|
||||||
public int nvp;
|
public int nvp;
|
||||||
public int nverts; // < Number of vertices.
|
public int nverts;
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -23,9 +23,9 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache.Io
|
namespace DotRecast.Detour.TileCache.Io
|
||||||
{
|
{
|
||||||
public static class DtTileCacheLayerHeaderReader
|
public class DtTileCacheLayerHeaderReader
|
||||||
{
|
{
|
||||||
public static DtTileCacheLayerHeader Read(RcByteBuffer data, bool cCompatibility)
|
public 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -24,34 +24,34 @@ using DotRecast.Detour.Io;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache.Io
|
namespace DotRecast.Detour.TileCache.Io
|
||||||
{
|
{
|
||||||
public class DtTileCacheLayerHeaderWriter
|
public class DtTileCacheLayerHeaderWriter : DtWriter
|
||||||
{
|
{
|
||||||
public void Write(BinaryWriter stream, DtTileCacheLayerHeader header, RcByteOrder order, bool cCompatibility)
|
public void Write(BinaryWriter stream, DtTileCacheLayerHeader header, RcByteOrder order, bool cCompatibility)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, header.magic, order);
|
Write(stream, header.magic, order);
|
||||||
RcIO.Write(stream, header.version, order);
|
Write(stream, header.version, order);
|
||||||
RcIO.Write(stream, header.tx, order);
|
Write(stream, header.tx, order);
|
||||||
RcIO.Write(stream, header.ty, order);
|
Write(stream, header.ty, order);
|
||||||
RcIO.Write(stream, header.tlayer, order);
|
Write(stream, header.tlayer, order);
|
||||||
|
|
||||||
RcIO.Write(stream, header.bmin.X, order);
|
Write(stream, header.bmin.X, order);
|
||||||
RcIO.Write(stream, header.bmin.Y, order);
|
Write(stream, header.bmin.Y, order);
|
||||||
RcIO.Write(stream, header.bmin.Z, order);
|
Write(stream, header.bmin.Z, order);
|
||||||
RcIO.Write(stream, header.bmax.X, order);
|
Write(stream, header.bmax.X, order);
|
||||||
RcIO.Write(stream, header.bmax.Y, order);
|
Write(stream, header.bmax.Y, order);
|
||||||
RcIO.Write(stream, header.bmax.Z, order);
|
Write(stream, header.bmax.Z, order);
|
||||||
|
|
||||||
RcIO.Write(stream, (short)header.hmin, order);
|
Write(stream, (short)header.hmin, order);
|
||||||
RcIO.Write(stream, (short)header.hmax, order);
|
Write(stream, (short)header.hmax, order);
|
||||||
RcIO.Write(stream, (byte)header.width);
|
Write(stream, (byte)header.width);
|
||||||
RcIO.Write(stream, (byte)header.height);
|
Write(stream, (byte)header.height);
|
||||||
RcIO.Write(stream, (byte)header.minx);
|
Write(stream, (byte)header.minx);
|
||||||
RcIO.Write(stream, (byte)header.maxx);
|
Write(stream, (byte)header.maxx);
|
||||||
RcIO.Write(stream, (byte)header.miny);
|
Write(stream, (byte)header.miny);
|
||||||
RcIO.Write(stream, (byte)header.maxy);
|
Write(stream, (byte)header.maxy);
|
||||||
if (cCompatibility)
|
if (cCompatibility)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, (short)0, order); // C struct padding
|
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -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 = RcIO.ToByteBuffer(@is);
|
RcByteBuffer bb = IOUtils.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 = RcIO.SwapEndianness(header.magic);
|
header.magic = IOUtils.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,8 +69,7 @@ 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();
|
DtNavMesh mesh = new DtNavMesh(header.meshParams, maxVertPerPoly);
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -25,9 +25,10 @@ using DotRecast.Detour.TileCache.Io.Compress;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache.Io
|
namespace DotRecast.Detour.TileCache.Io
|
||||||
{
|
{
|
||||||
public class DtTileCacheWriter
|
public class DtTileCacheWriter : DtWriter
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
@ -38,8 +39,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)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, DtTileCacheSetHeader.TILECACHESET_MAGIC, order);
|
Write(stream, DtTileCacheSetHeader.TILECACHESET_MAGIC, order);
|
||||||
RcIO.Write(stream, cCompatibility
|
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;
|
||||||
|
@ -51,7 +52,7 @@ namespace DotRecast.Detour.TileCache.Io
|
||||||
numTiles++;
|
numTiles++;
|
||||||
}
|
}
|
||||||
|
|
||||||
RcIO.Write(stream, numTiles, order);
|
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++)
|
||||||
|
@ -59,32 +60,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;
|
||||||
RcIO.Write(stream, (int)cache.GetTileRef(tile), order);
|
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 = DtTileCacheBuilder.CompressTileCacheLayer(comp, layer, order, cCompatibility);
|
data = builder.CompressTileCacheLayer(comp, layer, order, cCompatibility);
|
||||||
RcIO.Write(stream, data.Length, order);
|
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)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, option.orig.X, order);
|
Write(stream, option.orig.X, order);
|
||||||
RcIO.Write(stream, option.orig.Y, order);
|
Write(stream, option.orig.Y, order);
|
||||||
RcIO.Write(stream, option.orig.Z, order);
|
Write(stream, option.orig.Z, order);
|
||||||
|
|
||||||
RcIO.Write(stream, option.cs, order);
|
Write(stream, option.cs, order);
|
||||||
RcIO.Write(stream, option.ch, order);
|
Write(stream, option.ch, order);
|
||||||
RcIO.Write(stream, option.width, order);
|
Write(stream, option.width, order);
|
||||||
RcIO.Write(stream, option.height, order);
|
Write(stream, option.height, order);
|
||||||
RcIO.Write(stream, option.walkableHeight, order);
|
Write(stream, option.walkableHeight, order);
|
||||||
RcIO.Write(stream, option.walkableRadius, order);
|
Write(stream, option.walkableRadius, order);
|
||||||
RcIO.Write(stream, option.walkableClimb, order);
|
Write(stream, option.walkableClimb, order);
|
||||||
RcIO.Write(stream, option.maxSimplificationError, order);
|
Write(stream, option.maxSimplificationError, order);
|
||||||
RcIO.Write(stream, option.maxTiles, order);
|
Write(stream, option.maxTiles, order);
|
||||||
RcIO.Write(stream, option.maxObstacles, order);
|
Write(stream, option.maxObstacles, order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,9 @@
|
||||||
using DotRecast.Core.Numerics;
|
namespace DotRecast.Detour
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
|
||||||
{
|
{
|
||||||
public class BVItem
|
public class BVItem
|
||||||
{
|
{
|
||||||
public RcVec3i bmin;
|
public readonly int[] bmin = new int[3];
|
||||||
public RcVec3i bmax;
|
public readonly int[] bmax = new int[3];
|
||||||
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.X.CompareTo(b.bmin.X);
|
return a.bmin[0].CompareTo(b.bmin[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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.Y.CompareTo(b.bmin.Y);
|
return a.bmin[1].CompareTo(b.bmin[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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.Z.CompareTo(b.bmin.Z);
|
return a.bmin[2].CompareTo(b.bmin[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Detour",
|
|
||||||
"rootNamespace": "DotRecast.Detour",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Core"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -18,17 +18,23 @@ 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;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/// Bounding volume node.
|
/**
|
||||||
/// @note This structure is rarely if ever used by the end user.
|
* Bounding volume node.
|
||||||
/// @see dtMeshTile
|
*
|
||||||
|
* @note This structure is rarely if ever used by the end user.
|
||||||
|
* @see MeshTile
|
||||||
|
*/
|
||||||
public class DtBVNode
|
public class DtBVNode
|
||||||
{
|
{
|
||||||
public RcVec3i bmin; //< Minimum bounds of the node's AABB. [(x, y, z)]
|
/** Minimum bounds of the node's AABB. [(x, y, z)] */
|
||||||
public RcVec3i bmax; //< Maximum bounds of the node's AABB. [(x, y, z)]
|
public int[] bmin = new int[3];
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,22 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
|
||||||
{
|
|
||||||
public struct DtCallbackPolyQuery : IDtPolyQuery
|
|
||||||
{
|
|
||||||
private readonly Action<DtMeshTile, DtPoly, long> _callback;
|
|
||||||
|
|
||||||
public DtCallbackPolyQuery(Action<DtMeshTile, DtPoly, long> callback)
|
|
||||||
{
|
|
||||||
_callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Process(DtMeshTile tile, Span<DtPoly> poly, Span<long> refs, int count)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
_callback?.Invoke(tile, poly[i], refs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
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, Span<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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -18,20 +18,23 @@ 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 const float EPSILON = 0.0001f;
|
private static readonly float EPSILON = 0.0001f;
|
||||||
|
|
||||||
public static Span<float> Intersect(Span<float> p, Span<float> q, Span<float> buffer)
|
public static float[] Intersect(float[] p, float[] q)
|
||||||
{
|
{
|
||||||
int n = p.Length / 3;
|
int n = p.Length / 3;
|
||||||
int m = q.Length / 3;
|
int m = q.Length / 3;
|
||||||
Span<float> inters = stackalloc float[Math.Max(m, n) * 3 * 3];
|
float[] inters = new 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();
|
||||||
|
@ -51,10 +54,10 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
a = RcVec.Create(p, 3 * (ai % n));
|
a = RcVecUtils.Create(p, 3 * (ai % n));
|
||||||
b = RcVec.Create(q, 3 * (bi % m));
|
b = RcVecUtils.Create(q, 3 * (bi % m));
|
||||||
a1 = RcVec.Create(p, 3 * ((ai + n - 1) % n)); // prev a
|
a1 = RcVecUtils.Create(p, 3 * ((ai + n - 1) % n)); // prev a
|
||||||
b1 = RcVec.Create(q, 3 * ((bi + m - 1) % m)); // prev b
|
b1 = RcVecUtils.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);
|
||||||
|
@ -95,7 +98,7 @@ namespace DotRecast.Detour
|
||||||
/* Special case: A & B parallel and separated. */
|
/* Special case: A & B parallel and separated. */
|
||||||
if (parallel && aHB < 0f && bHA < 0f)
|
if (parallel && aHB < 0f && bHA < 0f)
|
||||||
{
|
{
|
||||||
return Span<float>.Empty;
|
return null;
|
||||||
}
|
}
|
||||||
/* Special case: A & B collinear. */
|
/* Special case: A & B collinear. */
|
||||||
else if (parallel && MathF.Abs(aHB) < EPSILON && MathF.Abs(bHA) < EPSILON)
|
else if (parallel && MathF.Abs(aHB) < EPSILON && MathF.Abs(bHA) < EPSILON)
|
||||||
|
@ -168,12 +171,12 @@ namespace DotRecast.Detour
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Span<float> result = buffer.Slice(0, ii);
|
float[] copied = new float[ii];
|
||||||
inters.Slice(0, ii).CopyTo(result);
|
RcArrays.Copy(inters, copied, ii);
|
||||||
return result;
|
return copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int AddVertex(Span<float> inters, int ii, RcVec3f p)
|
private static int AddVertex(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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
public static class DtDetailTriEdgeFlags
|
public static class DtDetailTriEdgeFlags
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,184 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,38 +3,31 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
public struct DtFindNearestPolyQuery : IDtPolyQuery
|
public class DtFindNearestPolyQuery : IDtPolyQuery
|
||||||
{
|
{
|
||||||
private readonly DtNavMeshQuery _query;
|
private readonly DtNavMeshQuery _query;
|
||||||
private readonly RcVec3f _center;
|
private readonly RcVec3f _center;
|
||||||
private float _nearestDistanceSqr;
|
|
||||||
private long _nearestRef;
|
private long _nearestRef;
|
||||||
private RcVec3f _nearestPoint;
|
private RcVec3f _nearestPt;
|
||||||
private bool _overPoly;
|
private bool _overPoly;
|
||||||
|
private float _nearestDistanceSqr;
|
||||||
|
|
||||||
public DtFindNearestPolyQuery(DtNavMeshQuery query, RcVec3f center)
|
public DtFindNearestPolyQuery(DtNavMeshQuery query, RcVec3f center)
|
||||||
{
|
{
|
||||||
_query = query;
|
this._query = query;
|
||||||
_center = center;
|
this._center = center;
|
||||||
_nearestDistanceSqr = float.MaxValue;
|
_nearestDistanceSqr = float.MaxValue;
|
||||||
_nearestPoint = center;
|
_nearestPt = center;
|
||||||
|
|
||||||
_nearestRef = default;
|
|
||||||
_overPoly = default;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Process(DtMeshTile tile, Span<DtPoly> poly, Span<long> refs, int count)
|
public void Process(DtMeshTile tile, DtPoly poly, long refs)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
long polyRef = refs[i];
|
|
||||||
float d;
|
|
||||||
|
|
||||||
// Find nearest polygon amongst the nearby polygons.
|
// Find nearest polygon amongst the nearby polygons.
|
||||||
_query.ClosestPointOnPoly(polyRef, _center, out var closestPtPoly, out var posOverPoly);
|
_query.ClosestPointOnPoly(refs, _center, out var closestPtPoly, out var posOverPoly);
|
||||||
|
|
||||||
// If a point is directly over a polygon and closer than
|
// If a point is directly over a polygon and closer than
|
||||||
// climb height, favor that instead of straight line nearest point.
|
// climb height, favor that instead of straight line nearest point.
|
||||||
|
float d = 0;
|
||||||
RcVec3f diff = RcVec3f.Subtract(_center, closestPtPoly);
|
RcVec3f diff = RcVec3f.Subtract(_center, closestPtPoly);
|
||||||
if (posOverPoly)
|
if (posOverPoly)
|
||||||
{
|
{
|
||||||
|
@ -48,13 +41,12 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
if (d < _nearestDistanceSqr)
|
if (d < _nearestDistanceSqr)
|
||||||
{
|
{
|
||||||
_nearestPoint = closestPtPoly;
|
_nearestPt = closestPtPoly;
|
||||||
_nearestDistanceSqr = d;
|
_nearestDistanceSqr = d;
|
||||||
_nearestRef = polyRef;
|
_nearestRef = refs;
|
||||||
_overPoly = posOverPoly;
|
_overPoly = posOverPoly;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public long NearestRef()
|
public long NearestRef()
|
||||||
{
|
{
|
||||||
|
@ -63,7 +55,7 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
public RcVec3f NearestPt()
|
public RcVec3f NearestPt()
|
||||||
{
|
{
|
||||||
return _nearestPoint;
|
return _nearestPt;
|
||||||
}
|
}
|
||||||
|
|
||||||
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,45 +0,0 @@
|
||||||
using System;
|
|
||||||
using DotRecast.Core;
|
|
||||||
using DotRecast.Core.Numerics;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
|
||||||
{
|
|
||||||
public struct DtHeightSamplePolyQuery : IDtPolyQuery
|
|
||||||
{
|
|
||||||
private readonly DtNavMeshQuery _navMeshQuery;
|
|
||||||
private readonly RcVec3f _pt;
|
|
||||||
private readonly float _maxHeight;
|
|
||||||
public float MinHeight { get; private set; }
|
|
||||||
public bool Found { get; private set; }
|
|
||||||
|
|
||||||
public DtHeightSamplePolyQuery(DtNavMeshQuery navMeshQuery, RcVec3f pt, float minHeight, float maxHeight)
|
|
||||||
{
|
|
||||||
_navMeshQuery = navMeshQuery;
|
|
||||||
_pt = pt;
|
|
||||||
MinHeight = minHeight;
|
|
||||||
_maxHeight = maxHeight;
|
|
||||||
Found = default;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Process(DtMeshTile tile, Span<DtPoly> poly, Span<long> refs, int count)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
ProcessSingle(refs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ProcessSingle(long refs)
|
|
||||||
{
|
|
||||||
var status = _navMeshQuery.GetPolyHeight(refs, _pt, out var h);
|
|
||||||
if (!status.Succeeded())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!(h > MinHeight) || !(h < _maxHeight))
|
|
||||||
return;
|
|
||||||
|
|
||||||
MinHeight = h;
|
|
||||||
Found = 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -18,20 +18,32 @@ 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.
|
/**
|
||||||
/// @note This structure is rarely if ever used by the end user.
|
* Defines a link between polygons.
|
||||||
/// @see dtMeshTile
|
*
|
||||||
|
* @note This structure is rarely if ever used by the end user.
|
||||||
|
* @see MeshTile
|
||||||
|
*/
|
||||||
public class DtLink
|
public class DtLink
|
||||||
{
|
{
|
||||||
public long refs; //< Neighbour reference. (The neighbor that is linked to.)
|
/** Neighbour reference. (The neighbor that is linked to.) */
|
||||||
public int next; //< Index of the next link.
|
public long refs;
|
||||||
public byte edge; //< Index of the polygon edge that owns this link.
|
|
||||||
public byte side; //< If a boundary link, defines on which side the link is.
|
/** Index of the next link. */
|
||||||
public byte bmin; //< If a boundary link, defines the minimum sub-edge area.
|
public int next;
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -18,29 +18,37 @@ 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
|
||||||
{
|
{
|
||||||
[Serializable]
|
|
||||||
public class DtMeshData
|
public class DtMeshData
|
||||||
{
|
{
|
||||||
public DtMeshHeader header; //< The tile header.
|
/** The tile header. */
|
||||||
public DtPoly[] polys; //< The tile polygons. [Size: dtMeshHeader::polyCount]
|
public DtMeshHeader header;
|
||||||
public float[] verts; //< The tile vertices. [(x, y, z) * dtMeshHeader::vertCount]
|
|
||||||
public DtPolyDetail[] detailMeshes; //< The tile's detail sub-meshes. [Size: dtMeshHeader::detailMeshCount]
|
|
||||||
|
|
||||||
/// The detail mesh's unique vertices. [(x, y, z) * dtMeshHeader::detailVertCount]
|
/** The tile vertices. [Size: MeshHeader::vertCount] */
|
||||||
|
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].
|
/**
|
||||||
/// See dtDetailTriEdgeFlags and dtGetDetailTriEdgeFlags.
|
* The detail mesh's triangles. [(vertA, vertB, vertC) * MeshHeader::detailTriCount] See DetailTriEdgeFlags and
|
||||||
|
* NavMesh::getDetailTriEdgeFlags.
|
||||||
|
*/
|
||||||
public int[] detailTris;
|
public int[] detailTris;
|
||||||
|
|
||||||
/// The tile bounding volume nodes. [Size: dtMeshHeader::bvNodeCount]
|
/**
|
||||||
/// (Will be null if bounding volumes are disabled.)
|
* The tile bounding volume nodes. [Size: MeshHeader::bvNodeCount] (Will be null if bounding volumes are disabled.)
|
||||||
|
*/
|
||||||
public DtBVNode[] bvTree;
|
public DtBVNode[] bvTree;
|
||||||
|
|
||||||
public DtOffMeshConnection[] offMeshCons; //< The tile off-mesh connections. [Size: dtMeshHeader::offMeshConCount]
|
/** The tile off-mesh connections. [Size: MeshHeader::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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -18,13 +18,11 @@ 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;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/** Provides high level information related to a dtMeshTile object. */
|
/** Provides high level information related to a dtMeshTile object. */
|
||||||
[Serializable]
|
|
||||||
public class DtMeshHeader
|
public class DtMeshHeader
|
||||||
{
|
{
|
||||||
/** Tile magic number. (Used to identify the data format.) */
|
/** Tile magic number. (Used to identify the data format.) */
|
||||||
|
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -18,22 +18,33 @@ 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; // DtNavMesh.m_tiles array index
|
public readonly int 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]
|
|
||||||
|
|
||||||
public int flags; //< Tile flags. (See: #dtTileFlags)
|
/** Counter describing modifications to the tile. */
|
||||||
public DtMeshTile next; //< The next free tile, or the next tile in the spatial grid.
|
public int salt;
|
||||||
|
|
||||||
|
/** 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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -25,66 +25,99 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
using static DtDetour;
|
|
||||||
|
|
||||||
/// A navigation mesh based on tiles of convex polygons.
|
|
||||||
/// @ingroup detour
|
|
||||||
public class DtNavMesh
|
public class DtNavMesh
|
||||||
{
|
{
|
||||||
private DtNavMeshParams m_params; //< Current initialization params. TODO: do not store this info twice.
|
/** A magic number used to detect compatibility of navigation tile data. */
|
||||||
private RcVec3f m_orig; // < Origin of the tile (0,0)
|
public const int DT_NAVMESH_MAGIC = 'D' << 24 | 'N' << 16 | 'A' << 8 | 'V';
|
||||||
private float m_tileWidth; // < Dimensions of each tile.
|
|
||||||
private float m_tileHeight; // < Dimensions of each tile.
|
|
||||||
private int m_maxTiles; // < Max number of tiles.
|
|
||||||
private int m_tileLutSize; //< Tile hash lookup size (must be pot).
|
|
||||||
private int m_tileLutMask; // < Tile hash lookup mask.
|
|
||||||
|
|
||||||
private DtMeshTile[] m_posLookup; //< Tile hash lookup.
|
/** A version number used to detect compatibility of navigation tile data. */
|
||||||
private DtMeshTile m_nextFree; //< Freelist of tiles.
|
public const int DT_NAVMESH_VERSION = 7;
|
||||||
private DtMeshTile[] m_tiles; //< List of tiles.
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
|
||||||
|
private readonly DtNavMeshParams m_params;
|
||||||
|
|
||||||
|
/// < Current initialization params. TODO: do not store this info twice.
|
||||||
|
private readonly RcVec3f m_orig;
|
||||||
|
|
||||||
|
/// < Origin of the tile (0,0)
|
||||||
|
// float m_orig[3]; ///< Origin of the tile (0,0)
|
||||||
|
private float m_tileWidth;
|
||||||
|
|
||||||
|
private float m_tileHeight;
|
||||||
|
|
||||||
|
/// < Dimensions of each tile.
|
||||||
|
int m_maxTiles;
|
||||||
|
|
||||||
|
/// < Max number of tiles.
|
||||||
|
private readonly int m_tileLutMask;
|
||||||
|
|
||||||
|
/// < Tile hash lookup mask.
|
||||||
|
private readonly Dictionary<int, List<DtMeshTile>> posLookup = new Dictionary<int, List<DtMeshTile>>();
|
||||||
|
|
||||||
|
private readonly LinkedList<DtMeshTile> availableTiles = new LinkedList<DtMeshTile>();
|
||||||
|
private readonly DtMeshTile[] m_tiles;
|
||||||
|
|
||||||
|
/// < List of tiles.
|
||||||
/** The maximum number of vertices per navigation polygon. */
|
/** The maximum number of vertices per navigation polygon. */
|
||||||
private int m_maxVertPerPoly;
|
private readonly int m_maxVertPerPoly;
|
||||||
|
|
||||||
private int m_tileCount;
|
private int m_tileCount;
|
||||||
|
|
||||||
public DtStatus Init(DtNavMeshParams param, int maxVertsPerPoly)
|
public DtNavMesh(DtMeshData data, int maxVertsPerPoly, int flags)
|
||||||
|
: this(GetNavMeshParams(data), maxVertsPerPoly)
|
||||||
{
|
{
|
||||||
m_params = param;
|
AddTile(data, flags, 0);
|
||||||
m_orig = param.orig;
|
}
|
||||||
m_tileWidth = param.tileWidth;
|
|
||||||
m_tileHeight = param.tileHeight;
|
|
||||||
|
|
||||||
|
public DtNavMesh(DtNavMeshParams option, int maxVertsPerPoly)
|
||||||
|
{
|
||||||
|
m_params = option;
|
||||||
|
m_orig = option.orig;
|
||||||
|
m_tileWidth = option.tileWidth;
|
||||||
|
m_tileHeight = option.tileHeight;
|
||||||
// Init tiles
|
// Init tiles
|
||||||
|
m_maxTiles = option.maxTiles;
|
||||||
m_maxVertPerPoly = maxVertsPerPoly;
|
m_maxVertPerPoly = maxVertsPerPoly;
|
||||||
m_maxTiles = param.maxTiles;
|
m_tileLutMask = Math.Max(1, DtUtils.NextPow2(option.maxTiles)) - 1;
|
||||||
m_tileLutSize = DtUtils.NextPow2(param.maxTiles);
|
|
||||||
if (0 == m_tileLutSize)
|
|
||||||
m_tileLutSize = 1;
|
|
||||||
m_tileLutMask = m_tileLutSize - 1;
|
|
||||||
|
|
||||||
m_tiles = new DtMeshTile[m_maxTiles];
|
m_tiles = new DtMeshTile[m_maxTiles];
|
||||||
m_posLookup = new DtMeshTile[m_tileLutSize];
|
for (int i = 0; i < m_maxTiles; i++)
|
||||||
m_nextFree = null;
|
|
||||||
for (int i = m_maxTiles - 1; i >= 0; --i)
|
|
||||||
{
|
{
|
||||||
m_tiles[i] = new DtMeshTile(i);
|
m_tiles[i] = new DtMeshTile(i);
|
||||||
m_tiles[i].salt = 1;
|
m_tiles[i].salt = 1;
|
||||||
m_tiles[i].next = m_nextFree;
|
availableTiles.AddLast(m_tiles[i]);
|
||||||
m_nextFree = m_tiles[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return DtStatus.DT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DtStatus Init(DtMeshData data, int maxVertsPerPoly, int flags)
|
|
||||||
{
|
|
||||||
var option = GetNavMeshParams(data);
|
|
||||||
DtStatus status = Init(option, maxVertsPerPoly);
|
|
||||||
if (status.Failed())
|
|
||||||
return status;
|
|
||||||
|
|
||||||
return AddTile(data, flags, 0, out _);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DtNavMeshParams GetNavMeshParams(DtMeshData data)
|
private static DtNavMeshParams GetNavMeshParams(DtMeshData data)
|
||||||
|
@ -135,10 +168,76 @@ namespace DotRecast.Detour
|
||||||
return EncodePolyId(tile.salt, it, 0);
|
return EncodePolyId(tile.salt, it, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @{
|
||||||
|
/// @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
|
||||||
|
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
|
||||||
|
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
|
||||||
|
static int DecodePolyIdPoly(long refs)
|
||||||
|
{
|
||||||
|
long polyMask = (1L << DT_POLY_BITS) - 1;
|
||||||
|
return (int)(refs & polyMask);
|
||||||
|
}
|
||||||
|
|
||||||
private int AllocLink(DtMeshTile tile)
|
private int AllocLink(DtMeshTile tile)
|
||||||
{
|
{
|
||||||
if (tile.linksFreeList == DT_NULL_LINK)
|
if (tile.linksFreeList == DT_NULL_LINK)
|
||||||
return DT_NULL_LINK;
|
{
|
||||||
|
DtLink link = new DtLink();
|
||||||
|
link.next = DT_NULL_LINK;
|
||||||
|
tile.links.Add(link);
|
||||||
|
return tile.links.Count - 1;
|
||||||
|
}
|
||||||
|
|
||||||
int linkIdx = tile.linksFreeList;
|
int linkIdx = tile.linksFreeList;
|
||||||
tile.linksFreeList = tile.links[linkIdx].next;
|
tile.linksFreeList = tile.links[linkIdx].next;
|
||||||
|
@ -259,8 +358,8 @@ namespace DotRecast.Detour
|
||||||
var tbmax = tile.data.header.bmax;
|
var tbmax = tile.data.header.bmax;
|
||||||
float qfac = tile.data.header.bvQuantFactor;
|
float qfac = tile.data.header.bvQuantFactor;
|
||||||
// Calculate quantized box
|
// Calculate quantized box
|
||||||
RcVec3i bmin;
|
int[] bmin = new int[3];
|
||||||
RcVec3i bmax;
|
int[] bmax = new int[3];
|
||||||
// dtClamp query box to world box.
|
// dtClamp query box to world box.
|
||||||
float minx = Math.Clamp(qmin.X, tbmin.X, tbmax.X) - tbmin.X;
|
float minx = Math.Clamp(qmin.X, tbmin.X, tbmax.X) - tbmin.X;
|
||||||
float miny = Math.Clamp(qmin.Y, tbmin.Y, tbmax.Y) - tbmin.Y;
|
float miny = Math.Clamp(qmin.Y, tbmin.Y, tbmax.Y) - tbmin.Y;
|
||||||
|
@ -269,12 +368,12 @@ namespace DotRecast.Detour
|
||||||
float maxy = Math.Clamp(qmax.Y, tbmin.Y, tbmax.Y) - tbmin.Y;
|
float maxy = Math.Clamp(qmax.Y, tbmin.Y, tbmax.Y) - tbmin.Y;
|
||||||
float maxz = Math.Clamp(qmax.Z, tbmin.Z, tbmax.Z) - tbmin.Z;
|
float maxz = Math.Clamp(qmax.Z, tbmin.Z, tbmax.Z) - tbmin.Z;
|
||||||
// Quantize
|
// Quantize
|
||||||
bmin.X = (int)(qfac * minx) & 0x7ffffffe;
|
bmin[0] = (int)(qfac * minx) & 0x7ffffffe;
|
||||||
bmin.Y = (int)(qfac * miny) & 0x7ffffffe;
|
bmin[1] = (int)(qfac * miny) & 0x7ffffffe;
|
||||||
bmin.Z = (int)(qfac * minz) & 0x7ffffffe;
|
bmin[2] = (int)(qfac * minz) & 0x7ffffffe;
|
||||||
bmax.X = (int)(qfac * maxx + 1) | 1;
|
bmax[0] = (int)(qfac * maxx + 1) | 1;
|
||||||
bmax.Y = (int)(qfac * maxy + 1) | 1;
|
bmax[1] = (int)(qfac * maxy + 1) | 1;
|
||||||
bmax.Z = (int)(qfac * maxz + 1) | 1;
|
bmax[2] = (int)(qfac * maxz + 1) | 1;
|
||||||
|
|
||||||
// Traverse tree
|
// Traverse tree
|
||||||
long @base = GetPolyRefBase(tile);
|
long @base = GetPolyRefBase(tile);
|
||||||
|
@ -282,7 +381,7 @@ namespace DotRecast.Detour
|
||||||
while (nodeIndex < end)
|
while (nodeIndex < end)
|
||||||
{
|
{
|
||||||
DtBVNode node = tile.data.bvTree[nodeIndex];
|
DtBVNode node = tile.data.bvTree[nodeIndex];
|
||||||
bool overlap = DtUtils.OverlapQuantBounds(ref bmin, ref bmax, ref node.bmin, ref node.bmax);
|
bool overlap = DtUtils.OverlapQuantBounds(bmin, bmax, node.bmin, node.bmax);
|
||||||
bool isLeafNode = node.i >= 0;
|
bool isLeafNode = node.i >= 0;
|
||||||
|
|
||||||
if (isLeafNode && overlap)
|
if (isLeafNode && overlap)
|
||||||
|
@ -319,13 +418,13 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
// Calc polygon bounds.
|
// Calc polygon bounds.
|
||||||
int v = p.verts[0] * 3;
|
int v = p.verts[0] * 3;
|
||||||
bmin = RcVec.Create(tile.data.verts, v);
|
bmin = RcVecUtils.Create(tile.data.verts, v);
|
||||||
bmax = RcVec.Create(tile.data.verts, v);
|
bmax = RcVecUtils.Create(tile.data.verts, v);
|
||||||
for (int j = 1; j < p.vertCount; ++j)
|
for (int j = 1; j < p.vertCount; ++j)
|
||||||
{
|
{
|
||||||
v = p.verts[j] * 3;
|
v = p.verts[j] * 3;
|
||||||
bmin = RcVec3f.Min(bmin, RcVec.Create(tile.data.verts, v));
|
bmin = RcVecUtils.Min(bmin, tile.data.verts, v);
|
||||||
bmax = RcVec3f.Max(bmax, RcVec.Create(tile.data.verts, v));
|
bmax = RcVecUtils.Max(bmax, tile.data.verts, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DtUtils.OverlapBounds(qmin, qmax, bmin, bmax))
|
if (DtUtils.OverlapBounds(qmin, qmax, bmin, bmax))
|
||||||
|
@ -338,20 +437,30 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtStatus UpdateTile(DtMeshData data, int flags)
|
public long UpdateTile(DtMeshData data, int flags)
|
||||||
{
|
{
|
||||||
long refs = GetTileRefAt(data.header.x, data.header.y, data.header.layer);
|
long refs = GetTileRefAt(data.header.x, data.header.y, data.header.layer);
|
||||||
refs = RemoveTile(refs);
|
refs = RemoveTile(refs);
|
||||||
return AddTile(data, flags, refs, out _);
|
return AddTile(data, flags, refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds a tile to the navigation mesh.
|
||||||
|
/// @param[in] data Data for the new tile mesh. (See: #dtCreateNavMeshData)
|
||||||
|
/// @param[in] dataSize Data size of the new tile mesh.
|
||||||
|
/// @param[in] flags Tile flags. (See: #dtTileFlags)
|
||||||
|
/// @param[in] lastRef The desired reference for the tile. (When reloading a
|
||||||
|
/// tile.) [opt] [Default: 0]
|
||||||
|
/// @param[out] result The tile reference. (If the tile was succesfully
|
||||||
|
/// added.) [opt]
|
||||||
|
/// @return The status flags for the operation.
|
||||||
/// @par
|
/// @par
|
||||||
///
|
///
|
||||||
/// The add operation will fail if the data is in the wrong format, the allocated tile
|
/// The add operation will fail if the data is in the wrong format, the
|
||||||
|
/// allocated tile
|
||||||
/// space is full, or there is a tile already at the specified reference.
|
/// space is full, or there is a tile already at the specified reference.
|
||||||
///
|
///
|
||||||
/// The lastRef parameter is used to restore a tile with the same tile
|
/// The lastRef parameter is used to restore a tile with the same tile
|
||||||
/// reference it had previously used. In this case the #dtPolyRef's for the
|
/// reference it had previously used. In this case the #long's for the
|
||||||
/// tile will be restored to the same values they were before the tile was
|
/// tile will be restored to the same values they were before the tile was
|
||||||
/// removed.
|
/// removed.
|
||||||
///
|
///
|
||||||
|
@ -361,37 +470,30 @@ namespace DotRecast.Detour
|
||||||
/// removed from this nav mesh.
|
/// removed from this nav mesh.
|
||||||
///
|
///
|
||||||
/// @see dtCreateNavMeshData, #removeTile
|
/// @see dtCreateNavMeshData, #removeTile
|
||||||
/// Adds a tile to the navigation mesh.
|
public long AddTile(DtMeshData data, int flags, long lastRef)
|
||||||
/// @param[in] data Data for the new tile mesh. (See: #dtCreateNavMeshData)
|
|
||||||
/// @param[in] dataSize Data size of the new tile mesh.
|
|
||||||
/// @param[in] flags Tile flags. (See: #dtTileFlags)
|
|
||||||
/// @param[in] lastRef The desired reference for the tile. (When reloading a tile.) [opt] [Default: 0]
|
|
||||||
/// @param[out] result The tile reference. (If the tile was succesfully added.) [opt]
|
|
||||||
/// @return The status flags for the operation.
|
|
||||||
public DtStatus AddTile(DtMeshData data, int flags, long lastRef, out long result)
|
|
||||||
{
|
{
|
||||||
result = 0;
|
|
||||||
|
|
||||||
// Make sure the data is in right format.
|
// Make sure the data is in right format.
|
||||||
DtMeshHeader header = data.header;
|
DtMeshHeader header = data.header;
|
||||||
|
|
||||||
// Make sure the location is free.
|
// Make sure the location is free.
|
||||||
if (GetTileAt(header.x, header.y, header.layer) != null)
|
if (GetTileAt(header.x, header.y, header.layer) != null)
|
||||||
{
|
{
|
||||||
return DtStatus.DT_FAILURE | DtStatus.DT_ALREADY_OCCUPIED;
|
throw new Exception("Tile already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a tile.
|
// Allocate a tile.
|
||||||
DtMeshTile tile = null;
|
DtMeshTile tile = null;
|
||||||
if (lastRef == 0)
|
if (lastRef == 0)
|
||||||
{
|
{
|
||||||
if (null != m_nextFree)
|
// Make sure we could allocate a tile.
|
||||||
|
if (0 == availableTiles.Count)
|
||||||
{
|
{
|
||||||
tile = m_nextFree;
|
throw new Exception("Could not allocate a tile");
|
||||||
m_nextFree = tile.next;
|
|
||||||
tile.next = null;
|
|
||||||
m_tileCount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tile = availableTiles.First?.Value;
|
||||||
|
availableTiles.RemoveFirst();
|
||||||
|
m_tileCount++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -399,53 +501,33 @@ namespace DotRecast.Detour
|
||||||
int tileIndex = DecodePolyIdTile(lastRef);
|
int tileIndex = DecodePolyIdTile(lastRef);
|
||||||
if (tileIndex >= m_maxTiles)
|
if (tileIndex >= m_maxTiles)
|
||||||
{
|
{
|
||||||
return DtStatus.DT_FAILURE | DtStatus.DT_OUT_OF_MEMORY;
|
throw new Exception("Tile index too high");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to find the specific tile id from the free list.
|
// Try to find the specific tile id from the free list.
|
||||||
DtMeshTile target = m_tiles[tileIndex];
|
DtMeshTile target = m_tiles[tileIndex];
|
||||||
DtMeshTile prev = null;
|
// Remove from freelist
|
||||||
tile = m_nextFree;
|
if (!availableTiles.Remove(target))
|
||||||
|
|
||||||
while (null != tile && tile != target)
|
|
||||||
{
|
{
|
||||||
prev = tile;
|
// Could not find the correct location.
|
||||||
tile = tile.next;
|
throw new Exception("Could not find tile");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Could not find the correct location.
|
tile = target;
|
||||||
if (tile != target)
|
|
||||||
return DtStatus.DT_FAILURE | DtStatus.DT_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
// Remove from freelist
|
|
||||||
if (null == prev)
|
|
||||||
m_nextFree = tile.next;
|
|
||||||
else
|
|
||||||
prev.next = tile.next;
|
|
||||||
|
|
||||||
// Restore salt.
|
// Restore salt.
|
||||||
tile.salt = DecodePolyIdSalt(lastRef);
|
tile.salt = DecodePolyIdSalt(lastRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we could allocate a tile.
|
tile.data = data;
|
||||||
if (null == tile)
|
tile.flags = flags;
|
||||||
{
|
tile.links.Clear();
|
||||||
return DtStatus.DT_FAILURE | DtStatus.DT_OUT_OF_MEMORY;
|
tile.polyLinks = new int[data.polys.Length];
|
||||||
}
|
Array.Fill(tile.polyLinks, DtNavMesh.DT_NULL_LINK);
|
||||||
|
|
||||||
// Insert tile into the position lut.
|
// Insert tile into the position lut.
|
||||||
int h = ComputeTileHash(header.x, header.y, m_tileLutMask);
|
GetTileListByPos(header.x, header.y).Add(tile);
|
||||||
tile.next = m_posLookup[h];
|
|
||||||
m_posLookup[h] = tile;
|
|
||||||
|
|
||||||
|
|
||||||
// Patch header pointers.
|
// Patch header pointers.
|
||||||
tile.data = data;
|
|
||||||
tile.links = new DtLink[data.header.maxLinkCount];
|
|
||||||
for (int i = 0; i < tile.links.Length; ++i)
|
|
||||||
{
|
|
||||||
tile.links[i] = new DtLink();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are no items in the bvtree, reset the tree pointer.
|
// If there are no items in the bvtree, reset the tree pointer.
|
||||||
if (tile.data.bvTree != null && tile.data.bvTree.Length == 0)
|
if (tile.data.bvTree != null && tile.data.bvTree.Length == 0)
|
||||||
|
@ -453,29 +535,16 @@ namespace DotRecast.Detour
|
||||||
tile.data.bvTree = null;
|
tile.data.bvTree = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build links freelist
|
|
||||||
tile.linksFreeList = 0;
|
|
||||||
tile.links[data.header.maxLinkCount - 1].next = DT_NULL_LINK;
|
|
||||||
for (int i = 0; i < data.header.maxLinkCount - 1; ++i)
|
|
||||||
tile.links[i].next = i + 1;
|
|
||||||
|
|
||||||
// Init tile.
|
// Init tile.
|
||||||
tile.flags = flags;
|
|
||||||
|
|
||||||
ConnectIntLinks(tile);
|
ConnectIntLinks(tile);
|
||||||
|
|
||||||
// Base off-mesh connections to their starting polygons and connect connections inside the tile.
|
// Base off-mesh connections to their starting polygons and connect connections inside the tile.
|
||||||
BaseOffMeshLinks(tile);
|
BaseOffMeshLinks(tile);
|
||||||
ConnectExtOffMeshLinks(tile, tile, -1);
|
ConnectExtOffMeshLinks(tile, tile, -1);
|
||||||
|
|
||||||
// Create connections with neighbour tiles.
|
|
||||||
const int MAX_NEIS = 32;
|
|
||||||
DtMeshTile[] neis = new DtMeshTile[MAX_NEIS];
|
|
||||||
int nneis;
|
|
||||||
|
|
||||||
// Connect with layers in current tile.
|
// Connect with layers in current tile.
|
||||||
nneis = GetTilesAt(header.x, header.y, neis, MAX_NEIS);
|
List<DtMeshTile> neis = GetTilesAt(header.x, header.y);
|
||||||
for (int j = 0; j < nneis; ++j)
|
for (int j = 0; j < neis.Count; ++j)
|
||||||
{
|
{
|
||||||
if (neis[j] == tile)
|
if (neis[j] == tile)
|
||||||
{
|
{
|
||||||
|
@ -491,8 +560,8 @@ namespace DotRecast.Detour
|
||||||
// Connect with neighbour tiles.
|
// Connect with neighbour tiles.
|
||||||
for (int i = 0; i < 8; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
nneis = GetNeighbourTilesAt(header.x, header.y, i, neis, MAX_NEIS);
|
neis = GetNeighbourTilesAt(header.x, header.y, i);
|
||||||
for (int j = 0; j < nneis; ++j)
|
for (int j = 0; j < neis.Count; ++j)
|
||||||
{
|
{
|
||||||
ConnectExtLinks(tile, neis[j], i);
|
ConnectExtLinks(tile, neis[j], i);
|
||||||
ConnectExtLinks(neis[j], tile, DtUtils.OppositeTile(i));
|
ConnectExtLinks(neis[j], tile, DtUtils.OppositeTile(i));
|
||||||
|
@ -501,8 +570,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = GetTileRef(tile);
|
return GetTileRef(tile);
|
||||||
return DtStatus.DT_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes the specified tile from the navigation mesh.
|
/// Removes the specified tile from the navigation mesh.
|
||||||
|
@ -535,52 +603,39 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove tile from hash lookup.
|
// Remove tile from hash lookup.
|
||||||
int h = ComputeTileHash(tile.data.header.x, tile.data.header.y, m_tileLutMask);
|
GetTileListByPos(tile.data.header.x, tile.data.header.y).Remove(tile);
|
||||||
DtMeshTile prev = null;
|
|
||||||
DtMeshTile cur = m_posLookup[h];
|
|
||||||
while (null != cur)
|
|
||||||
{
|
|
||||||
if (cur == tile)
|
|
||||||
{
|
|
||||||
if (null != prev)
|
|
||||||
prev.next = cur.next;
|
|
||||||
else
|
|
||||||
m_posLookup[h] = cur.next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
prev = cur;
|
|
||||||
cur = cur.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove connections to neighbour tiles.
|
// Remove connections to neighbour tiles.
|
||||||
const int MAX_NEIS = 32;
|
// Create connections with neighbour tiles.
|
||||||
DtMeshTile[] neis = new DtMeshTile[MAX_NEIS];
|
|
||||||
int nneis = 0;
|
|
||||||
|
|
||||||
// Disconnect from other layers in current tile.
|
// Disconnect from other layers in current tile.
|
||||||
nneis = GetTilesAt(tile.data.header.x, tile.data.header.y, neis, MAX_NEIS);
|
List<DtMeshTile> nneis = GetTilesAt(tile.data.header.x, tile.data.header.y);
|
||||||
for (int j = 0; j < nneis; ++j)
|
foreach (DtMeshTile j in nneis)
|
||||||
{
|
{
|
||||||
if (neis[j] == tile) continue;
|
if (j == tile)
|
||||||
UnconnectLinks(neis[j], tile);
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnconnectLinks(j, tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disconnect from neighbour tiles.
|
// Disconnect from neighbour tiles.
|
||||||
for (int i = 0; i < 8; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
nneis = GetNeighbourTilesAt(tile.data.header.x, tile.data.header.y, i, neis, MAX_NEIS);
|
nneis = GetNeighbourTilesAt(tile.data.header.x, tile.data.header.y, i);
|
||||||
for (int j = 0; j < nneis; ++j)
|
foreach (DtMeshTile j in nneis)
|
||||||
{
|
{
|
||||||
UnconnectLinks(neis[j], tile);
|
UnconnectLinks(j, tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset tile.
|
// Reset tile.
|
||||||
tile.data = null;
|
tile.data = null;
|
||||||
|
|
||||||
tile.flags = 0;
|
tile.flags = 0;
|
||||||
tile.links = null;
|
tile.links.Clear();
|
||||||
tile.linksFreeList = DT_NULL_LINK;
|
tile.linksFreeList = DtNavMesh.DT_NULL_LINK;
|
||||||
|
|
||||||
// Update salt, salt should never be zero.
|
// Update salt, salt should never be zero.
|
||||||
tile.salt = (tile.salt + 1) & ((1 << DT_SALT_BITS) - 1);
|
tile.salt = (tile.salt + 1) & ((1 << DT_SALT_BITS) - 1);
|
||||||
|
@ -590,8 +645,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to free list.
|
// Add to free list.
|
||||||
tile.next = m_nextFree;
|
availableTiles.AddFirst(tile);
|
||||||
m_nextFree = tile;
|
|
||||||
m_tileCount--;
|
m_tileCount--;
|
||||||
return GetTileRef(tile);
|
return GetTileRef(tile);
|
||||||
}
|
}
|
||||||
|
@ -609,7 +663,7 @@ namespace DotRecast.Detour
|
||||||
for (int i = 0; i < tile.data.header.polyCount; ++i)
|
for (int i = 0; i < tile.data.header.polyCount; ++i)
|
||||||
{
|
{
|
||||||
DtPoly poly = tile.data.polys[i];
|
DtPoly poly = tile.data.polys[i];
|
||||||
poly.firstLink = DT_NULL_LINK;
|
tile.polyLinks[poly.index] = DT_NULL_LINK;
|
||||||
|
|
||||||
if (poly.GetPolyType() == DtPolyTypes.DT_POLYTYPE_OFFMESH_CONNECTION)
|
if (poly.GetPolyType() == DtPolyTypes.DT_POLYTYPE_OFFMESH_CONNECTION)
|
||||||
{
|
{
|
||||||
|
@ -629,17 +683,17 @@ namespace DotRecast.Detour
|
||||||
int idx = AllocLink(tile);
|
int idx = AllocLink(tile);
|
||||||
DtLink link = tile.links[idx];
|
DtLink link = tile.links[idx];
|
||||||
link.refs = @base | (long)(poly.neis[j] - 1);
|
link.refs = @base | (long)(poly.neis[j] - 1);
|
||||||
link.edge = (byte)j;
|
link.edge = j;
|
||||||
link.side = 0xff;
|
link.side = 0xff;
|
||||||
link.bmin = link.bmax = 0;
|
link.bmin = link.bmax = 0;
|
||||||
// Add to linked list.
|
// Add to linked list.
|
||||||
link.next = poly.firstLink;
|
link.next = tile.polyLinks[poly.index];
|
||||||
poly.firstLink = idx;
|
tile.polyLinks[poly.index] = idx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes external links at specified side.
|
/// Removes external links at specified side.V
|
||||||
void UnconnectLinks(DtMeshTile tile, DtMeshTile target)
|
void UnconnectLinks(DtMeshTile tile, DtMeshTile target)
|
||||||
{
|
{
|
||||||
if (tile == null || target == null)
|
if (tile == null || target == null)
|
||||||
|
@ -652,7 +706,7 @@ namespace DotRecast.Detour
|
||||||
for (int i = 0; i < tile.data.header.polyCount; ++i)
|
for (int i = 0; i < tile.data.header.polyCount; ++i)
|
||||||
{
|
{
|
||||||
DtPoly poly = tile.data.polys[i];
|
DtPoly poly = tile.data.polys[i];
|
||||||
int j = poly.firstLink;
|
int j = tile.polyLinks[poly.index];
|
||||||
int pj = DT_NULL_LINK;
|
int pj = DT_NULL_LINK;
|
||||||
while (j != DT_NULL_LINK)
|
while (j != DT_NULL_LINK)
|
||||||
{
|
{
|
||||||
|
@ -662,7 +716,7 @@ namespace DotRecast.Detour
|
||||||
int nj = tile.links[j].next;
|
int nj = tile.links[j].next;
|
||||||
if (pj == DT_NULL_LINK)
|
if (pj == DT_NULL_LINK)
|
||||||
{
|
{
|
||||||
poly.firstLink = nj;
|
tile.polyLinks[poly.index] = nj;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -722,15 +776,13 @@ namespace DotRecast.Detour
|
||||||
foreach (var connectPoly in connectPolys)
|
foreach (var connectPoly in connectPolys)
|
||||||
{
|
{
|
||||||
int idx = AllocLink(tile);
|
int idx = AllocLink(tile);
|
||||||
if (idx != DT_NULL_LINK)
|
|
||||||
{
|
|
||||||
DtLink link = tile.links[idx];
|
DtLink link = tile.links[idx];
|
||||||
link.refs = connectPoly.refs;
|
link.refs = connectPoly.refs;
|
||||||
link.edge = (byte)j;
|
link.edge = j;
|
||||||
link.side = (byte)dir;
|
link.side = dir;
|
||||||
|
|
||||||
link.next = poly.firstLink;
|
link.next = tile.polyLinks[poly.index];
|
||||||
poly.firstLink = idx;
|
tile.polyLinks[poly.index] = idx;
|
||||||
|
|
||||||
// Compress portal limits to a byte value.
|
// Compress portal limits to a byte value.
|
||||||
if (dir == 0 || dir == 4)
|
if (dir == 0 || dir == 4)
|
||||||
|
@ -746,8 +798,8 @@ namespace DotRecast.Detour
|
||||||
tmax = temp;
|
tmax = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
link.bmin = (byte)MathF.Round(Math.Clamp(tmin, 0.0f, 1.0f) * 255.0f);
|
link.bmin = (int)MathF.Round(Math.Clamp(tmin, 0.0f, 1.0f) * 255.0f);
|
||||||
link.bmax = (byte)MathF.Round(Math.Clamp(tmax, 0.0f, 1.0f) * 255.0f);
|
link.bmax = (int)MathF.Round(Math.Clamp(tmax, 0.0f, 1.0f) * 255.0f);
|
||||||
}
|
}
|
||||||
else if (dir == 2 || dir == 6)
|
else if (dir == 2 || dir == 6)
|
||||||
{
|
{
|
||||||
|
@ -762,9 +814,8 @@ namespace DotRecast.Detour
|
||||||
tmax = temp;
|
tmax = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
link.bmin = (byte)MathF.Round(Math.Clamp(tmin, 0.0f, 1.0f) * 255.0f);
|
link.bmin = (int)MathF.Round(Math.Clamp(tmin, 0.0f, 1.0f) * 255.0f);
|
||||||
link.bmax = (byte)MathF.Round(Math.Clamp(tmax, 0.0f, 1.0f) * 255.0f);
|
link.bmax = (int)MathF.Round(Math.Clamp(tmax, 0.0f, 1.0f) * 255.0f);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -794,7 +845,7 @@ namespace DotRecast.Detour
|
||||||
DtPoly targetPoly = target.data.polys[targetCon.poly];
|
DtPoly targetPoly = target.data.polys[targetCon.poly];
|
||||||
// Skip off-mesh connections which start location could not be
|
// Skip off-mesh connections which start location could not be
|
||||||
// connected at all.
|
// connected at all.
|
||||||
if (targetPoly.firstLink == DT_NULL_LINK)
|
if (target.polyLinks[targetPoly.index] == DT_NULL_LINK)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -832,11 +883,11 @@ namespace DotRecast.Detour
|
||||||
DtLink link = target.links[idx];
|
DtLink link = target.links[idx];
|
||||||
link.refs = refs;
|
link.refs = refs;
|
||||||
link.edge = 1;
|
link.edge = 1;
|
||||||
link.side = (byte)oppositeSide;
|
link.side = oppositeSide;
|
||||||
link.bmin = link.bmax = 0;
|
link.bmin = link.bmax = 0;
|
||||||
// Add to linked list.
|
// Add to linked list.
|
||||||
link.next = targetPoly.firstLink;
|
link.next = target.polyLinks[targetPoly.index];
|
||||||
targetPoly.firstLink = idx;
|
target.polyLinks[targetPoly.index] = idx;
|
||||||
|
|
||||||
// Link target poly to off-mesh connection.
|
// Link target poly to off-mesh connection.
|
||||||
if ((targetCon.flags & DT_OFFMESH_CON_BIDIR) != 0)
|
if ((targetCon.flags & DT_OFFMESH_CON_BIDIR) != 0)
|
||||||
|
@ -847,11 +898,11 @@ namespace DotRecast.Detour
|
||||||
link = tile.links[tidx];
|
link = tile.links[tidx];
|
||||||
link.refs = GetPolyRefBase(target) | (long)targetCon.poly;
|
link.refs = GetPolyRefBase(target) | (long)targetCon.poly;
|
||||||
link.edge = 0xff;
|
link.edge = 0xff;
|
||||||
link.side = (byte)(side == -1 ? 0xff : side);
|
link.side = (side == -1 ? 0xff : side);
|
||||||
link.bmin = link.bmax = 0;
|
link.bmin = link.bmax = 0;
|
||||||
// Add to linked list.
|
// Add to linked list.
|
||||||
link.next = landPoly.firstLink;
|
link.next = tile.polyLinks[landPoly.index];
|
||||||
landPoly.firstLink = tidx;
|
tile.polyLinks[landPoly.index] = tidx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -918,7 +969,59 @@ namespace DotRecast.Detour
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool OverlapSlabs(RcVec2f amin, RcVec2f amax, RcVec2f bmin, RcVec2f bmax, float px, float py)
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OverlapSlabs(RcVec2f amin, RcVec2f amax, RcVec2f bmin, RcVec2f bmax, float px, float py)
|
||||||
{
|
{
|
||||||
// Check for horizontal overlap.
|
// Check for horizontal overlap.
|
||||||
// The segment is shrunken a little so that slabs which touch
|
// The segment is shrunken a little so that slabs which touch
|
||||||
|
@ -1009,8 +1112,8 @@ namespace DotRecast.Detour
|
||||||
link.side = 0xff;
|
link.side = 0xff;
|
||||||
link.bmin = link.bmax = 0;
|
link.bmin = link.bmax = 0;
|
||||||
// Add to linked list.
|
// Add to linked list.
|
||||||
link.next = poly.firstLink;
|
link.next = tile.polyLinks[poly.index];
|
||||||
poly.firstLink = idx;
|
tile.polyLinks[poly.index] = idx;
|
||||||
|
|
||||||
// Start end-point is always connect back to off-mesh connection.
|
// Start end-point is always connect back to off-mesh connection.
|
||||||
int tidx = AllocLink(tile);
|
int tidx = AllocLink(tile);
|
||||||
|
@ -1022,8 +1125,8 @@ namespace DotRecast.Detour
|
||||||
link.side = 0xff;
|
link.side = 0xff;
|
||||||
link.bmin = link.bmax = 0;
|
link.bmin = link.bmax = 0;
|
||||||
// Add to linked list.
|
// Add to linked list.
|
||||||
link.next = landPoly.firstLink;
|
link.next = tile.polyLinks[landPoly.index];
|
||||||
landPoly.firstLink = tidx;
|
tile.polyLinks[landPoly.index] = tidx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1045,7 +1148,6 @@ namespace DotRecast.Detour
|
||||||
RcVec3f pmin = new RcVec3f();
|
RcVec3f pmin = new RcVec3f();
|
||||||
RcVec3f pmax = new RcVec3f();
|
RcVec3f pmax = new RcVec3f();
|
||||||
|
|
||||||
Span<RcVec3f> tempV = stackalloc RcVec3f[3];
|
|
||||||
if (tile.data.detailMeshes != null)
|
if (tile.data.detailMeshes != null)
|
||||||
{
|
{
|
||||||
ref DtPolyDetail pd = ref tile.data.detailMeshes[ip];
|
ref DtPolyDetail pd = ref tile.data.detailMeshes[ip];
|
||||||
|
@ -1058,7 +1160,7 @@ namespace DotRecast.Detour
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Span<RcVec3f> v = tempV;
|
RcVec3f[] v = new RcVec3f[3];
|
||||||
for (int j = 0; j < 3; ++j)
|
for (int j = 0; j < 3; ++j)
|
||||||
{
|
{
|
||||||
if (tris[ti + j] < poly.vertCount)
|
if (tris[ti + j] < poly.vertCount)
|
||||||
|
@ -1106,7 +1208,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Span<RcVec3f> v = tempV.Slice(0, 2);
|
RcVec3f[] v = new RcVec3f[2];
|
||||||
for (int j = 0; j < poly.vertCount; ++j)
|
for (int j = 0; j < poly.vertCount; ++j)
|
||||||
{
|
{
|
||||||
int k = (j + 1) % poly.vertCount;
|
int k = (j + 1) % poly.vertCount;
|
||||||
|
@ -1144,11 +1246,11 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
int ip = poly.index;
|
int ip = poly.index;
|
||||||
|
|
||||||
Span<float> verts = stackalloc float[m_maxVertPerPoly * 3];
|
float[] verts = new float[m_maxVertPerPoly * 3];
|
||||||
int nv = poly.vertCount;
|
int nv = poly.vertCount;
|
||||||
for (int i = 0; i < nv; ++i)
|
for (int i = 0; i < nv; ++i)
|
||||||
{
|
{
|
||||||
RcSpans.Copy(tile.data.verts, poly.verts[i] * 3, verts, i * 3, 3);
|
RcArrays.Copy(tile.data.verts, poly.verts[i] * 3, verts, i * 3, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DtUtils.PointInPolygon(pos, verts, nv))
|
if (!DtUtils.PointInPolygon(pos, verts, nv))
|
||||||
|
@ -1157,14 +1259,13 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find height at the location.
|
// Find height at the location.
|
||||||
Span<RcVec3f> tempV = stackalloc RcVec3f[3];
|
|
||||||
if (tile.data.detailMeshes != null)
|
if (tile.data.detailMeshes != null)
|
||||||
{
|
{
|
||||||
ref DtPolyDetail pd = ref tile.data.detailMeshes[ip];
|
ref DtPolyDetail pd = ref tile.data.detailMeshes[ip];
|
||||||
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;
|
||||||
Span<RcVec3f> v = tempV;
|
RcVec3f[] v = new RcVec3f[3];
|
||||||
for (int k = 0; k < 3; ++k)
|
for (int k = 0; k < 3; ++k)
|
||||||
{
|
{
|
||||||
if (tile.data.detailTris[t + k] < poly.vertCount)
|
if (tile.data.detailTris[t + k] < poly.vertCount)
|
||||||
|
@ -1198,7 +1299,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Span<RcVec3f> v = tempV;
|
RcVec3f[] v = new RcVec3f[3];
|
||||||
v[0].X = tile.data.verts[poly.verts[0] * 3];
|
v[0].X = tile.data.verts[poly.verts[0] * 3];
|
||||||
v[0].Y = tile.data.verts[poly.verts[0] * 3 + 1];
|
v[0].Y = tile.data.verts[poly.verts[0] * 3 + 1];
|
||||||
v[0].Z = tile.data.verts[poly.verts[0] * 3 + 2];
|
v[0].Z = tile.data.verts[poly.verts[0] * 3 + 2];
|
||||||
|
@ -1306,27 +1407,19 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
DtMeshTile GetTileAt(int x, int y, int layer)
|
DtMeshTile GetTileAt(int x, int y, int layer)
|
||||||
{
|
{
|
||||||
// Find tile based on hash.
|
foreach (DtMeshTile tile in GetTileListByPos(x, y))
|
||||||
int h = ComputeTileHash(x, y, m_tileLutMask);
|
|
||||||
DtMeshTile tile = m_posLookup[h];
|
|
||||||
while (null != tile)
|
|
||||||
{
|
{
|
||||||
if (null != tile.data &&
|
if (tile.data.header != null && tile.data.header.x == x && tile.data.header.y == y
|
||||||
null != tile.data.header &&
|
&& tile.data.header.layer == layer)
|
||||||
tile.data.header.x == x &&
|
|
||||||
tile.data.header.y == y &&
|
|
||||||
tile.data.header.layer == layer)
|
|
||||||
{
|
{
|
||||||
return tile;
|
return tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
tile = tile.next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetNeighbourTilesAt(int x, int y, int side, DtMeshTile[] tiles, int maxTiles)
|
List<DtMeshTile> GetNeighbourTilesAt(int x, int y, int side)
|
||||||
{
|
{
|
||||||
int nx = x, ny = y;
|
int nx = x, ny = y;
|
||||||
switch (side)
|
switch (side)
|
||||||
|
@ -1361,36 +1454,21 @@ namespace DotRecast.Detour
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetTilesAt(nx, ny, tiles, maxTiles);
|
return GetTilesAt(nx, ny);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetTilesAt(int x, int y, DtMeshTile[] tiles, int maxTiles)
|
public List<DtMeshTile> GetTilesAt(int x, int y)
|
||||||
{
|
{
|
||||||
return GetTilesAt(x, y, (Span<DtMeshTile>)tiles, maxTiles);
|
List<DtMeshTile> tiles = new List<DtMeshTile>();
|
||||||
|
foreach (DtMeshTile tile in GetTileListByPos(x, y))
|
||||||
|
{
|
||||||
|
if (tile.data.header != null && tile.data.header.x == x && tile.data.header.y == y)
|
||||||
|
{
|
||||||
|
tiles.Add(tile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetTilesAt(int x, int y, Span<DtMeshTile> tiles, int maxTiles)
|
return tiles;
|
||||||
{
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
// Find tile based on hash.
|
|
||||||
int h = ComputeTileHash(x, y, m_tileLutMask);
|
|
||||||
DtMeshTile tile = m_posLookup[h];
|
|
||||||
while (null != tile)
|
|
||||||
{
|
|
||||||
if (null != tile.data &&
|
|
||||||
null != tile.data.header &&
|
|
||||||
tile.data.header.x == x &&
|
|
||||||
tile.data.header.y == y)
|
|
||||||
{
|
|
||||||
if (n < maxTiles)
|
|
||||||
tiles[n++] = tile;
|
|
||||||
}
|
|
||||||
|
|
||||||
tile = tile.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetTileRefAt(int x, int y, int layer)
|
public long GetTileRefAt(int x, int y, int layer)
|
||||||
|
@ -1431,6 +1509,14 @@ namespace DotRecast.Detour
|
||||||
return EncodePolyId(tile.salt, tile.index, 0);
|
return EncodePolyId(tile.salt, tile.index, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the endpoints for an off-mesh connection, ordered by "direction of travel".
|
/// Gets the endpoints for an off-mesh connection, ordered by "direction of travel".
|
||||||
/// @param[in] prevRef The reference of the polygon before the connection.
|
/// @param[in] prevRef The reference of the polygon before the connection.
|
||||||
/// @param[in] polyRef The reference of the off-mesh connection polygon.
|
/// @param[in] polyRef The reference of the off-mesh connection polygon.
|
||||||
|
@ -1482,7 +1568,7 @@ namespace DotRecast.Detour
|
||||||
int idx0 = 0, idx1 = 1;
|
int idx0 = 0, idx1 = 1;
|
||||||
|
|
||||||
// Find link that points to first vertex.
|
// Find link that points to first vertex.
|
||||||
for (int i = poly.firstLink; i != DT_NULL_LINK; i = tile.links[i].next)
|
for (int i = tile.polyLinks[poly.index]; i != DT_NULL_LINK; i = tile.links[i].next)
|
||||||
{
|
{
|
||||||
if (tile.links[i].edge == 0)
|
if (tile.links[i].edge == 0)
|
||||||
{
|
{
|
||||||
|
@ -1496,8 +1582,8 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startPos = RcVec.Create(tile.data.verts, poly.verts[idx0] * 3);
|
startPos = RcVecUtils.Create(tile.data.verts, poly.verts[idx0] * 3);
|
||||||
endPos = RcVec.Create(tile.data.verts, poly.verts[idx1] * 3);
|
endPos = RcVecUtils.Create(tile.data.verts, poly.verts[idx1] * 3);
|
||||||
|
|
||||||
return DtStatus.DT_SUCCESS;
|
return DtStatus.DT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1512,9 +1598,9 @@ namespace DotRecast.Detour
|
||||||
return m_tileCount;
|
return m_tileCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsAvailableTileCount()
|
public int GetAvailableTileCount()
|
||||||
{
|
{
|
||||||
return null != m_nextFree;
|
return availableTiles.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtStatus SetPolyFlags(long refs, int flags)
|
public DtStatus SetPolyFlags(long refs, int flags)
|
||||||
|
@ -1672,6 +1758,32 @@ namespace DotRecast.Detour
|
||||||
return center;
|
return center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get flags for edge in detail triangle.
|
||||||
|
*
|
||||||
|
* @param triFlags
|
||||||
|
* The flags for the triangle (last component of detail vertices above).
|
||||||
|
* @param edgeIndex
|
||||||
|
* The index of the first vertex of the edge. For instance, if 0,
|
||||||
|
* @return flags for edge AB.
|
||||||
|
*/
|
||||||
|
public static int GetDetailTriEdgeFlags(int triFlags, int edgeIndex)
|
||||||
|
{
|
||||||
|
return (triFlags >> (edgeIndex * 2)) & 0x3;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<DtMeshTile> GetTileListByPos(int x, int z)
|
||||||
|
{
|
||||||
|
var tileHash = ComputeTileHash(x, z, m_tileLutMask);
|
||||||
|
if (!posLookup.TryGetValue(tileHash, out var tiles))
|
||||||
|
{
|
||||||
|
tiles = new List<DtMeshTile>();
|
||||||
|
posLookup.Add(tileHash, tiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tiles;
|
||||||
|
}
|
||||||
|
|
||||||
public void ComputeBounds(out RcVec3f bmin, out RcVec3f bmax)
|
public void ComputeBounds(out RcVec3f bmin, out RcVec3f bmax)
|
||||||
{
|
{
|
||||||
bmin = new RcVec3f(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
|
bmin = new RcVec3f(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
|
||||||
|
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -24,35 +24,42 @@ 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 void CalcExtends(BVItem[] items, int nitems, int imin, int imax, ref RcVec3i bmin, ref RcVec3i bmax)
|
private static int[][] CalcExtends(BVItem[] items, int nitems, int imin, int imax)
|
||||||
{
|
{
|
||||||
bmin = items[imin].bmin;
|
int[] bmin = new int[3];
|
||||||
bmax = items[imin].bmax;
|
int[] bmax = new int[3];
|
||||||
|
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.X < bmin.X)
|
if (it.bmin[0] < bmin[0])
|
||||||
bmin.X = it.bmin.X;
|
bmin[0] = it.bmin[0];
|
||||||
if (it.bmin.Y < bmin.Y)
|
if (it.bmin[1] < bmin[1])
|
||||||
bmin.Y = it.bmin.Y;
|
bmin[1] = it.bmin[1];
|
||||||
if (it.bmin.Z < bmin.Z)
|
if (it.bmin[2] < bmin[2])
|
||||||
bmin.Z = it.bmin.Z;
|
bmin[2] = it.bmin[2];
|
||||||
|
|
||||||
if (it.bmax.X > bmax.X)
|
if (it.bmax[0] > bmax[0])
|
||||||
bmax.X = it.bmax.X;
|
bmax[0] = it.bmax[0];
|
||||||
if (it.bmax.Y > bmax.Y)
|
if (it.bmax[1] > bmax[1])
|
||||||
bmax.Y = it.bmax.Y;
|
bmax[1] = it.bmax[1];
|
||||||
if (it.bmax.Z > bmax.Z)
|
if (it.bmax[2] > bmax[2])
|
||||||
bmax.Z = it.bmax.Z;
|
bmax[2] = it.bmax[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
@ -85,21 +92,25 @@ namespace DotRecast.Detour
|
||||||
if (inum == 1)
|
if (inum == 1)
|
||||||
{
|
{
|
||||||
// Leaf
|
// Leaf
|
||||||
node.bmin = items[imin].bmin;
|
node.bmin[0] = items[imin].bmin[0];
|
||||||
node.bmax = items[imin].bmax;
|
node.bmin[1] = items[imin].bmin[1];
|
||||||
|
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
|
||||||
CalcExtends(items, nitems, imin, imax, ref node.bmin, ref node.bmax);
|
int[][] minmax = CalcExtends(items, nitems, imin, imax);
|
||||||
|
node.bmin = minmax[0];
|
||||||
|
node.bmax = minmax[1];
|
||||||
|
|
||||||
int axis = LongestAxis(
|
int axis = LongestAxis(node.bmax[0] - node.bmin[0], node.bmax[1] - node.bmin[1],
|
||||||
node.bmax.X - node.bmin.X,
|
node.bmax[2] - node.bmin[2]);
|
||||||
node.bmax.Y - node.bmin.Y,
|
|
||||||
node.bmax.Z - node.bmin.Z
|
|
||||||
);
|
|
||||||
|
|
||||||
if (axis == 0)
|
if (axis == 0)
|
||||||
{
|
{
|
||||||
|
@ -148,29 +159,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 = RcVec.Create(option.detailVerts, dv);
|
var bmin = RcVecUtils.Create(option.detailVerts, dv);
|
||||||
var bmax = RcVec.Create(option.detailVerts, dv);
|
var bmax = RcVecUtils.Create(option.detailVerts, dv);
|
||||||
for (int j = 1; j < ndv; j++)
|
for (int j = 1; j < ndv; j++)
|
||||||
{
|
{
|
||||||
bmin = RcVec3f.Min(bmin, RcVec.Create(option.detailVerts, dv + j * 3));
|
bmin = RcVecUtils.Min(bmin, option.detailVerts, dv + j * 3);
|
||||||
bmax = RcVec3f.Max(bmax, RcVec.Create(option.detailVerts, dv + j * 3));
|
bmax = RcVecUtils.Max(bmax, option.detailVerts, dv + j * 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BV-tree uses cs for all dimensions
|
// BV-tree uses cs for all dimensions
|
||||||
it.bmin.X = Math.Clamp((int)((bmin.X - option.bmin.X) * quantFactor), 0, int.MaxValue);
|
it.bmin[0] = Math.Clamp((int)((bmin.X - option.bmin.X) * quantFactor), 0, int.MaxValue);
|
||||||
it.bmin.Y = Math.Clamp((int)((bmin.Y - option.bmin.Y) * quantFactor), 0, int.MaxValue);
|
it.bmin[1] = Math.Clamp((int)((bmin.Y - option.bmin.Y) * quantFactor), 0, int.MaxValue);
|
||||||
it.bmin.Z = Math.Clamp((int)((bmin.Z - option.bmin.Z) * quantFactor), 0, int.MaxValue);
|
it.bmin[2] = Math.Clamp((int)((bmin.Z - option.bmin.Z) * quantFactor), 0, int.MaxValue);
|
||||||
|
|
||||||
it.bmax.X = Math.Clamp((int)((bmax.X - option.bmin.X) * quantFactor), 0, int.MaxValue);
|
it.bmax[0] = Math.Clamp((int)((bmax.X - option.bmin.X) * quantFactor), 0, int.MaxValue);
|
||||||
it.bmax.Y = Math.Clamp((int)((bmax.Y - option.bmin.Y) * quantFactor), 0, int.MaxValue);
|
it.bmax[1] = Math.Clamp((int)((bmax.Y - option.bmin.Y) * quantFactor), 0, int.MaxValue);
|
||||||
it.bmax.Z = Math.Clamp((int)((bmax.Z - option.bmin.Z) * quantFactor), 0, int.MaxValue);
|
it.bmax[2] = 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.X = it.bmax.X = option.verts[option.polys[p] * 3 + 0];
|
it.bmin[0] = it.bmax[0] = option.verts[option.polys[p] * 3 + 0];
|
||||||
it.bmin.Y = it.bmax.Y = option.verts[option.polys[p] * 3 + 1];
|
it.bmin[1] = it.bmax[1] = option.verts[option.polys[p] * 3 + 1];
|
||||||
it.bmin.Z = it.bmax.Z = option.verts[option.polys[p] * 3 + 2];
|
it.bmin[2] = it.bmax[2] = option.verts[option.polys[p] * 3 + 2];
|
||||||
|
|
||||||
for (int j = 1; j < option.nvp; ++j)
|
for (int j = 1; j < option.nvp; ++j)
|
||||||
{
|
{
|
||||||
|
@ -180,24 +191,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.X)
|
if (x < it.bmin[0])
|
||||||
it.bmin.X = x;
|
it.bmin[0] = x;
|
||||||
if (y < it.bmin.Y)
|
if (y < it.bmin[1])
|
||||||
it.bmin.Y = y;
|
it.bmin[1] = y;
|
||||||
if (z < it.bmin.Z)
|
if (z < it.bmin[2])
|
||||||
it.bmin.Z = z;
|
it.bmin[2] = z;
|
||||||
|
|
||||||
if (x > it.bmax.X)
|
if (x > it.bmax[0])
|
||||||
it.bmax.X = x;
|
it.bmax[0] = x;
|
||||||
if (y > it.bmax.Y)
|
if (y > it.bmax[1])
|
||||||
it.bmax.Y = y;
|
it.bmax[1] = y;
|
||||||
if (z > it.bmax.Z)
|
if (z > it.bmax[2])
|
||||||
it.bmax.Z = z;
|
it.bmax[2] = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remap y
|
// Remap y
|
||||||
it.bmin.Y = (int)MathF.Floor(it.bmin.Y * option.ch * quantFactor);
|
it.bmin[1] = (int)MathF.Floor(it.bmin[1] * option.ch * quantFactor);
|
||||||
it.bmax.Y = (int)MathF.Ceiling(it.bmax.Y * option.ch * quantFactor);
|
it.bmax[1] = (int)MathF.Ceiling(it.bmax[1] * option.ch * quantFactor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,15 +251,14 @@ 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
|
||||||
/// The output data array is allocated using the detour allocator (dtAlloc()). The method
|
* Tile creation data.
|
||||||
/// used to free the memory will be determined by how the tile is added to the navigation
|
*
|
||||||
/// mesh.
|
* @return created tile data
|
||||||
///
|
*/
|
||||||
/// @see dtNavMesh, dtNavMesh::addTile()
|
|
||||||
public static DtMeshData CreateNavMeshData(DtNavMeshCreateParams option)
|
public static DtMeshData CreateNavMeshData(DtNavMeshCreateParams option)
|
||||||
{
|
{
|
||||||
if (option.vertCount >= 0xffff)
|
if (option.vertCount >= 0xffff)
|
||||||
|
@ -306,8 +316,8 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
for (int i = 0; i < option.offMeshConCount; ++i)
|
for (int i = 0; i < option.offMeshConCount; ++i)
|
||||||
{
|
{
|
||||||
var p0 = RcVec.Create(option.offMeshConVerts, (i * 2 + 0) * 3);
|
var p0 = RcVecUtils.Create(option.offMeshConVerts, (i * 2 + 0) * 3);
|
||||||
var p1 = RcVec.Create(option.offMeshConVerts, (i * 2 + 1) * 3);
|
var p1 = RcVecUtils.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);
|
||||||
|
@ -414,8 +424,8 @@ namespace DotRecast.Detour
|
||||||
DtOffMeshConnection[] offMeshCons = new DtOffMeshConnection[storedOffMeshConCount];
|
DtOffMeshConnection[] offMeshCons = new DtOffMeshConnection[storedOffMeshConCount];
|
||||||
|
|
||||||
// Store header
|
// Store header
|
||||||
header.magic = DT_NAVMESH_MAGIC;
|
header.magic = DtNavMesh.DT_NAVMESH_MAGIC;
|
||||||
header.version = DT_NAVMESH_VERSION;
|
header.version = DtNavMesh.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;
|
||||||
|
@ -487,13 +497,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] = DT_EXT_LINK | 4;
|
p.neis[j] = DtNavMesh.DT_EXT_LINK | 4;
|
||||||
else if (dir == 1) // Portal z+
|
else if (dir == 1) // Portal z+
|
||||||
p.neis[j] = DT_EXT_LINK | 2;
|
p.neis[j] = DtNavMesh.DT_EXT_LINK | 2;
|
||||||
else if (dir == 2) // Portal x+
|
else if (dir == 2) // Portal x+
|
||||||
p.neis[j] = DT_EXT_LINK | 0;
|
p.neis[j] = DtNavMesh.DT_EXT_LINK | 0;
|
||||||
else if (dir == 3) // Portal z-
|
else if (dir == 3) // Portal z-
|
||||||
p.neis[j] = DT_EXT_LINK | 6;
|
p.neis[j] = DtNavMesh.DT_EXT_LINK | 6;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -540,9 +550,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;
|
||||||
byte vertCount = (byte)(ndv - nv);
|
int vertCount = (ndv - nv);
|
||||||
int triBase = option.detailMeshes[i * 4 + 2];
|
int triBase = option.detailMeshes[i * 4 + 2];
|
||||||
byte triCount = (byte)option.detailMeshes[i * 4 + 3];
|
int triCount = 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.
|
||||||
|
@ -564,9 +574,9 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
int nv = navPolys[i].vertCount;
|
int nv = navPolys[i].vertCount;
|
||||||
int vertBase = 0;
|
int vertBase = 0;
|
||||||
byte vertCount = 0;
|
int vertCount = 0;
|
||||||
int triBase = tbase;
|
int triBase = tbase;
|
||||||
byte triCount = (byte)(nv - 2);
|
int triCount = (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)
|
||||||
|
@ -608,11 +618,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] = RcVec.Create(option.offMeshConVerts, endPts + (j * 3));
|
con.pos[j] = RcVecUtils.Create(option.offMeshConVerts, endPts + (j * 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
con.rad = option.offMeshConRad[i];
|
con.rad = option.offMeshConRad[i];
|
||||||
con.flags = option.offMeshConDir[i] != 0 ? DT_OFFMESH_CON_BIDIR : 0;
|
con.flags = option.offMeshConDir[i] != 0 ? DtNavMesh.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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -18,21 +18,31 @@ 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;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/// Configuration parameters used to define multi-tile navigation meshes.
|
/**
|
||||||
/// The values are used to allocate space during the initialization of a navigation mesh.
|
* Configuration parameters used to define multi-tile navigation meshes. The values are used to allocate space during
|
||||||
/// @see dtNavMesh::init()
|
* the initialization of a navigation mesh.
|
||||||
/// @ingroup detour
|
*
|
||||||
|
* @see NavMesh
|
||||||
|
*/
|
||||||
public struct DtNavMeshParams
|
public struct DtNavMeshParams
|
||||||
{
|
{
|
||||||
public RcVec3f orig; //< The world space origin of the navigation mesh's tile space. [(x, y, z)]
|
/** The world space origin of the navigation mesh's tile space. [(x, y, z)] */
|
||||||
public float tileWidth; //< The width of each tile. (Along the x-axis.)
|
public RcVec3f orig;
|
||||||
public float tileHeight; //< The height of each tile. (Along the z-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.
|
/** The width of each tile. (Along the x-axis.) */
|
||||||
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.
|
public float tileWidth;
|
||||||
|
|
||||||
|
/** 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
|
@ -1,34 +0,0 @@
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -17,7 +17,6 @@ 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;
|
||||||
|
|
||||||
|
@ -49,7 +48,6 @@ 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];
|
||||||
|
@ -60,7 +58,7 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
ref DtPolyDetail pd = ref tile.data.detailMeshes[i];
|
ref DtPolyDetail pd = ref tile.data.detailMeshes[i];
|
||||||
|
|
||||||
Span<RcVec3f> verts = tempVerts;
|
RcVec3f[] verts = new RcVec3f[3];
|
||||||
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,5 +1,4 @@
|
||||||
using System;
|
using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Core.Numerics;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
@ -11,11 +10,9 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public Span<float> Apply(Span<float> polyVerts, RcVec3f circleCenter, float radius, Span<float> resultBuffer)
|
public float[] Apply(float[] polyVerts, RcVec3f circleCenter, float radius)
|
||||||
{
|
{
|
||||||
var result = resultBuffer.Slice(0, polyVerts.Length);
|
return polyVerts;
|
||||||
polyVerts.CopyTo(result);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -18,10 +18,8 @@ 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.Linq;
|
using System.Linq;
|
||||||
using DotRecast.Core.Buffers;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
@ -29,68 +27,24 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
private readonly Dictionary<long, List<DtNode>> m_map;
|
private readonly Dictionary<long, List<DtNode>> m_map;
|
||||||
|
|
||||||
private int m_usedNodesCount;
|
private int m_nodeCount;
|
||||||
private List<DtNode[]> m_buckets;
|
private readonly List<DtNode> m_nodes;
|
||||||
private readonly int m_initialBufferCapacityBase;
|
|
||||||
private readonly RcObjectPool<List<DtNode>> m_listPool;
|
|
||||||
|
|
||||||
public DtNodePool(int initialBufferCapacityBase = 6) // initial size 64
|
public DtNodePool()
|
||||||
{
|
{
|
||||||
m_map = new Dictionary<long, List<DtNode>>();
|
m_map = new Dictionary<long, List<DtNode>>();
|
||||||
m_listPool = new RcObjectPool<List<DtNode>>(() => new List<DtNode>());
|
m_nodes = new List<DtNode>();
|
||||||
m_buckets = new List<DtNode[]>();
|
|
||||||
m_initialBufferCapacityBase = initialBufferCapacityBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddNewBucket()
|
|
||||||
{
|
|
||||||
var bucketIndex = m_buckets.Count;
|
|
||||||
var bucket = new DtNode[1 << (bucketIndex + m_initialBufferCapacityBase)];
|
|
||||||
m_buckets.Add(bucket);
|
|
||||||
FillBucket(bucketIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FillBucket(int bucketIndex)
|
|
||||||
{
|
|
||||||
var bucket = m_buckets[bucketIndex];
|
|
||||||
var startIndex = GetBucketStartIndex(bucketIndex);
|
|
||||||
for (int i = 0; i < bucket.Length; i++)
|
|
||||||
{
|
|
||||||
bucket[i] = new DtNode(startIndex + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetBucketStartIndex(int bucketIndex)
|
|
||||||
{
|
|
||||||
return ((1 << (bucketIndex + m_initialBufferCapacityBase)) - 1) ^ ((1 << m_initialBufferCapacityBase) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DtNode[] EnsureBucket(int bucketIndex)
|
|
||||||
{
|
|
||||||
if (m_buckets.Count == bucketIndex)
|
|
||||||
AddNewBucket();
|
|
||||||
else if (m_buckets.Count < bucketIndex)
|
|
||||||
throw new Exception();
|
|
||||||
return m_buckets[bucketIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetBucketIndexByElementIndex(int elementIndex)
|
|
||||||
{
|
|
||||||
return DtUtils.Ilog2((elementIndex >> m_initialBufferCapacityBase) + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
foreach (var pair in m_map)
|
|
||||||
m_listPool.Return(pair.Value);
|
|
||||||
|
|
||||||
m_map.Clear();
|
m_map.Clear();
|
||||||
m_usedNodesCount = 0;
|
m_nodeCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetNodeCount()
|
public int GetNodeCount()
|
||||||
{
|
{
|
||||||
return m_usedNodesCount;
|
return m_nodeCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int FindNodes(long id, out List<DtNode> nodes)
|
public int FindNodes(long id, out List<DtNode> nodes)
|
||||||
|
@ -130,8 +84,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nodes = m_listPool.Get();
|
nodes = new List<DtNode>();
|
||||||
nodes.Clear();
|
|
||||||
m_map.Add(id, nodes);
|
m_map.Add(id, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,10 +93,15 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
private DtNode Create(long id, int state, List<DtNode> nodes)
|
private DtNode Create(long id, int state, List<DtNode> nodes)
|
||||||
{
|
{
|
||||||
int i = m_usedNodesCount++;
|
if (m_nodes.Count <= m_nodeCount)
|
||||||
int bucketIndex = GetBucketIndexByElementIndex(i);
|
{
|
||||||
int bucketStartIndex = GetBucketStartIndex(bucketIndex);
|
var newNode = new DtNode(m_nodeCount);
|
||||||
var node = EnsureBucket(bucketIndex)[i - bucketStartIndex];
|
m_nodes.Add(newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = m_nodeCount;
|
||||||
|
m_nodeCount++;
|
||||||
|
var node = m_nodes[i];
|
||||||
node.pidx = 0;
|
node.pidx = 0;
|
||||||
node.cost = 0;
|
node.cost = 0;
|
||||||
node.total = 0;
|
node.total = 0;
|
||||||
|
@ -165,16 +123,9 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
public DtNode GetNodeAtIdx(int idx)
|
public DtNode GetNodeAtIdx(int idx)
|
||||||
{
|
{
|
||||||
if (idx == 0)
|
return idx != 0
|
||||||
return null;
|
? m_nodes[idx - 1]
|
||||||
|
: null;
|
||||||
int bucketIndex = GetBucketIndexByElementIndex(idx - 1);
|
|
||||||
if (m_buckets.Count <= bucketIndex)
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
|
|
||||||
int bucketStartIndex = GetBucketStartIndex(bucketIndex);
|
|
||||||
var node = EnsureBucket(bucketIndex)[idx - bucketStartIndex - 1];
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtNode GetNode(long refs)
|
public DtNode GetNode(long refs)
|
||||||
|
@ -184,7 +135,7 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
public IEnumerable<DtNode> AsEnumerable()
|
public IEnumerable<DtNode> AsEnumerable()
|
||||||
{
|
{
|
||||||
return m_buckets.SelectMany(x => x);
|
return m_nodes.Take(m_nodeCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -18,14 +18,12 @@ 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;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/// Defines an navigation mesh off-mesh connection within a dtMeshTile object.
|
/// Defines an navigation mesh off-mesh connection within a dtMeshTile object.
|
||||||
/// An off-mesh connection is a user defined traversable connection made up to two vertices.
|
/// An off-mesh connection is a user defined traversable connection made up to two vertices.
|
||||||
[Serializable]
|
|
||||||
public class DtOffMeshConnection
|
public class DtOffMeshConnection
|
||||||
{
|
{
|
||||||
/// The endpoints of the connection. [(ax, ay, az, bx, by, bz)]
|
/// The endpoints of the connection. [(ax, ay, az, bx, by, bz)]
|
||||||
|
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -20,31 +20,27 @@ freely, subject to the following restrictions:
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Core.Buffers;
|
using System.Linq;
|
||||||
using DotRecast.Core.Collections;
|
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using CollectionExtensions = DotRecast.Core.Collections.CollectionExtensions;
|
|
||||||
|
|
||||||
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, int pathSize,
|
List<long> path,
|
||||||
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.
|
||||||
Span<DtStraightPath> straightPath = stackalloc DtStraightPath[MAX_STEER_POINTS];
|
var straightPath = new List<DtStraightPath>(MAX_STEER_POINTS);
|
||||||
var result = navQuery.FindStraightPath(startPos, endPos, path, pathSize, straightPath, out var nsteerPath, MAX_STEER_POINTS, 0);
|
var result = navQuery.FindStraightPath(startPos, endPos, path, ref straightPath, MAX_STEER_POINTS, 0);
|
||||||
if (result.Failed())
|
if (result.Failed())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -52,7 +48,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 < nsteerPath)
|
while (ns < straightPath.Count)
|
||||||
{
|
{
|
||||||
// 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)
|
||||||
|
@ -62,7 +58,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failed to find good point to steer to.
|
// Failed to find good point to steer to.
|
||||||
if (ns >= nsteerPath)
|
if (ns >= straightPath.Count)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
steerPos = straightPath[ns].pos;
|
steerPos = straightPath[ns].pos;
|
||||||
|
@ -93,32 +89,29 @@ 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 int FixupShortcuts(ref List<long> path, int npath, DtNavMeshQuery navQuery)
|
public static List<long> FixupShortcuts(List<long> path, DtNavMeshQuery navQuery)
|
||||||
{
|
{
|
||||||
if (npath < 3)
|
if (path.Count < 3)
|
||||||
{
|
{
|
||||||
return npath;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get connected polygons
|
// Get connected polygons
|
||||||
const int maxNeis = 16;
|
List<long> neis = new List<long>();
|
||||||
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 npath;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (int k = poly.firstLink; k != DT_NULL_LINK; k = tile.links[k].next)
|
for (int k = tile.polyLinks[poly.index]; k != DtNavMesh.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)
|
||||||
{
|
{
|
||||||
if (nneis < maxNeis)
|
neis.Add(link.refs);
|
||||||
neis[nneis++] = link.refs;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,9 +119,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, npath) - 1; i > 1 && cut == 0; i--)
|
for (int i = Math.Min(maxLookAhead, path.Count) - 1; i > 1 && cut == 0; i--)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < nneis; j++)
|
for (int j = 0; j < neis.Count; j++)
|
||||||
{
|
{
|
||||||
if (path[i] == neis[j])
|
if (path[i] == neis[j])
|
||||||
{
|
{
|
||||||
|
@ -142,16 +135,14 @@ 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, npath - cut));
|
shortcut.AddRange(path.GetRange(cut, path.Count - cut));
|
||||||
|
return shortcut;
|
||||||
path = shortcut;
|
|
||||||
return shortcut.Count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return npath;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int MergeCorridorStartMoved(List<long> path, int npath, int maxPath, Span<long> visited, int nvisited)
|
public static int MergeCorridorStartMoved(List<long> path, int npath, int maxPath, List<long> visited)
|
||||||
{
|
{
|
||||||
int furthestPath = -1;
|
int furthestPath = -1;
|
||||||
int furthestVisited = -1;
|
int furthestVisited = -1;
|
||||||
|
@ -160,7 +151,7 @@ namespace DotRecast.Detour
|
||||||
for (int i = npath - 1; i >= 0; --i)
|
for (int i = npath - 1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (int j = nvisited - 1; j >= 0; --j)
|
for (int j = visited.Count - 1; j >= 0; --j)
|
||||||
{
|
{
|
||||||
if (path[i] == visited[j])
|
if (path[i] == visited[j])
|
||||||
{
|
{
|
||||||
|
@ -183,32 +174,45 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concatenate paths.
|
// Concatenate paths.
|
||||||
var endIndex = nvisited - 1;
|
|
||||||
var length1 = endIndex - furthestVisited;
|
|
||||||
var length2 = npath - furthestPath;
|
|
||||||
using var result = RcRentedArray.Rent<long>(length1 + length2);
|
|
||||||
// Adjust beginning of the buffer to include the visited.
|
// Adjust beginning of the buffer to include the visited.
|
||||||
// Store visited
|
int req = visited.Count - furthestVisited;
|
||||||
for (int i = 0; i < length1; ++i)
|
int orig = Math.Min(furthestPath + 1, npath);
|
||||||
result[i] = visited[endIndex - i];
|
int size = Math.Max(0, npath - orig);
|
||||||
|
if (req + size > maxPath)
|
||||||
|
size = maxPath - req;
|
||||||
|
|
||||||
path.CopyTo(furthestPath, result.AsArray(), length1, length2);
|
if (size > 0)
|
||||||
|
{
|
||||||
|
//memmove(path + req, path + orig, size * sizeof(dtPolyRef));
|
||||||
|
for (int i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
if (path.Count <= req + i)
|
||||||
|
path.Add(0);
|
||||||
|
|
||||||
path.Clear();
|
path[req + i] = path[orig + i];
|
||||||
CollectionExtensions.AddRange(path, result.AsSpan());
|
}
|
||||||
return result.Length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int MergeCorridorEndMoved(List<long> path, int npath, int maxPath, Span<long> visited, int nvisited)
|
// Store visited
|
||||||
|
for (int i = 0, n = Math.Min(req, maxPath); i < n; ++i)
|
||||||
|
{
|
||||||
|
path[i] = visited[(visited.Count - 1) - i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return req + size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<long> MergeCorridorEndMoved(List<long> path, int npath, int maxPath, List<long> visited)
|
||||||
{
|
{
|
||||||
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 < npath; ++i)
|
for (int i = 0; i < path.Count; ++i)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (int j = nvisited - 1; j >= 0; --j)
|
for (int j = visited.Count - 1; j >= 0; --j)
|
||||||
{
|
{
|
||||||
if (path[i] == visited[j])
|
if (path[i] == visited[j])
|
||||||
{
|
{
|
||||||
|
@ -227,31 +231,25 @@ 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 npath;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concatenate paths.
|
// Concatenate paths.
|
||||||
var length1 = furthestPath;
|
List<long> result = path.GetRange(0, furthestPath);
|
||||||
var length2 = nvisited - furthestVisited;
|
result.AddRange(visited.GetRange(furthestVisited, visited.Count - furthestVisited));
|
||||||
using var result = RcRentedArray.Rent<long>(length1 + length2);
|
return result;
|
||||||
path.CopyTo(0, result.AsArray(), 0, length1);
|
|
||||||
visited.Slice(furthestVisited, nvisited - furthestVisited).CopyTo(result.AsSpan().Slice(length1, length2));
|
|
||||||
|
|
||||||
path.Clear();
|
|
||||||
CollectionExtensions.AddRange(path, result.AsSpan());
|
|
||||||
return path.Count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int MergeCorridorStartShortcut(List<long> path, int npath, int maxPath, List<long> visited, int nvisited)
|
public static List<long> MergeCorridorStartShortcut(List<long> path, int npath, int maxPath, List<long> visited)
|
||||||
{
|
{
|
||||||
int furthestPath = -1;
|
int furthestPath = -1;
|
||||||
int furthestVisited = -1;
|
int furthestVisited = -1;
|
||||||
|
|
||||||
// Find furthest common polygon.
|
// Find furthest common polygon.
|
||||||
for (int i = npath - 1; i >= 0; --i)
|
for (int i = path.Count - 1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (int j = nvisited - 1; j >= 0; --j)
|
for (int j = visited.Count - 1; j >= 0; --j)
|
||||||
{
|
{
|
||||||
if (path[i] == visited[j])
|
if (path[i] == visited[j])
|
||||||
{
|
{
|
||||||
|
@ -270,21 +268,15 @@ 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 npath;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concatenate paths.
|
// Concatenate paths.
|
||||||
|
|
||||||
// Adjust beginning of the buffer to include the visited.
|
// Adjust beginning of the buffer to include the visited.
|
||||||
var length1 = furthestVisited;
|
List<long> result = visited.GetRange(0, furthestVisited);
|
||||||
var length2 = npath - furthestPath;
|
result.AddRange(path.GetRange(furthestPath, path.Count - furthestPath));
|
||||||
using var result = RcRentedArray.Rent<long>(length1 + length2);
|
return result;
|
||||||
visited.CopyTo(0, result.AsArray(), 0, length1);
|
|
||||||
path.CopyTo(furthestPath, result.AsArray(), length1, length2);
|
|
||||||
|
|
||||||
path.Clear();
|
|
||||||
CollectionExtensions.AddRange(path, result.AsSpan());
|
|
||||||
return path.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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -20,26 +20,21 @@ freely, subject to the following restrictions:
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/// Defines a polygon within a dtMeshTile object.
|
/** Defines a polygon within a MeshTile object. */
|
||||||
/// @ingroup detour
|
|
||||||
public class DtPoly
|
public class DtPoly
|
||||||
{
|
{
|
||||||
public readonly int index;
|
public readonly int index;
|
||||||
|
|
||||||
/// Index to first link in linked list. (Or #DT_NULL_LINK if there is no link.)
|
/** The indices of the polygon's vertices. The actual vertices are located in MeshTile::verts. */
|
||||||
public int firstLink;
|
|
||||||
|
|
||||||
/// The indices of the polygon's vertices.
|
|
||||||
/// The actual vertices are located in dtMeshTile::verts.
|
|
||||||
public readonly int[] verts;
|
public readonly int[] verts;
|
||||||
|
|
||||||
/// Packed data representing neighbor polygons references and flags for each edge.
|
/** Packed data representing neighbor polygons references and flags for each edge. */
|
||||||
public readonly int[] neis;
|
public readonly int[] neis;
|
||||||
|
|
||||||
/// The user defined polygon flags.
|
/** 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.
|
||||||
|
@ -53,25 +48,25 @@ namespace DotRecast.Detour
|
||||||
neis = new int[maxVertsPerPoly];
|
neis = new int[maxVertsPerPoly];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the user defined area id. [Limit: < #DT_MAX_AREAS]
|
/** Sets the user defined area id. [Limit: < {@link org.recast4j.detour.NavMesh#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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -20,15 +20,22 @@ 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 readonly struct DtPolyDetail
|
public readonly struct DtPolyDetail
|
||||||
{
|
{
|
||||||
public readonly int vertBase; //< The offset of the vertices in the dtMeshTile::detailVerts array.
|
/** The offset of the vertices in the MeshTile::detailVerts array. */
|
||||||
public readonly int triBase; //< The offset of the triangles in the dtMeshTile::detailTris array.
|
public readonly int vertBase;
|
||||||
public readonly byte vertCount; //< The number of vertices in the sub-mesh.
|
|
||||||
public readonly byte triCount; //< The number of triangles in the sub-mesh.
|
|
||||||
|
|
||||||
public DtPolyDetail(int vertBase, int triBase, byte vertCount, byte triCount)
|
/** The offset of the triangles in the MeshTile::detailTris array. */
|
||||||
|
public readonly int triBase;
|
||||||
|
|
||||||
|
/** The number of vertices in the sub-mesh. */
|
||||||
|
public readonly int vertCount;
|
||||||
|
|
||||||
|
/** The number of triangles in the sub-mesh. */
|
||||||
|
public readonly 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -23,8 +23,6 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
using static DtDetour;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <b>The Default Implementation</b>
|
* <b>The Default Implementation</b>
|
||||||
*
|
*
|
||||||
|
@ -52,7 +50,7 @@ namespace DotRecast.Detour
|
||||||
*/
|
*/
|
||||||
public class DtQueryDefaultFilter : IDtQueryFilter
|
public class DtQueryDefaultFilter : IDtQueryFilter
|
||||||
{
|
{
|
||||||
private readonly float[] m_areaCost = new float[DT_MAX_AREAS]; //< Cost per area type. (Used by default implementation.)
|
private readonly float[] m_areaCost = new float[DtNavMesh.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.)
|
||||||
|
|
||||||
|
@ -60,7 +58,7 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
m_includeFlags = 0xffff;
|
m_includeFlags = 0xffff;
|
||||||
m_excludeFlags = 0;
|
m_excludeFlags = 0;
|
||||||
for (int i = 0; i < DT_MAX_AREAS; ++i)
|
for (int i = 0; i < DtNavMesh.DT_MAX_AREAS; ++i)
|
||||||
{
|
{
|
||||||
m_areaCost[i] = 1.0f;
|
m_areaCost[i] = 1.0f;
|
||||||
}
|
}
|
||||||
|
@ -70,12 +68,12 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
m_includeFlags = includeFlags;
|
m_includeFlags = includeFlags;
|
||||||
m_excludeFlags = excludeFlags;
|
m_excludeFlags = excludeFlags;
|
||||||
for (int i = 0; i < Math.Min(DT_MAX_AREAS, areaCost.Length); ++i)
|
for (int i = 0; i < Math.Min(DtNavMesh.DT_MAX_AREAS, areaCost.Length); ++i)
|
||||||
{
|
{
|
||||||
m_areaCost[i] = areaCost[i];
|
m_areaCost[i] = areaCost[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = areaCost.Length; i < DT_MAX_AREAS; ++i)
|
for (int i = areaCost.Length; i < DtNavMesh.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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -38,16 +38,9 @@ namespace DotRecast.Detour
|
||||||
public int hitEdgeIndex;
|
public int hitEdgeIndex;
|
||||||
|
|
||||||
/// Pointer to an array of reference ids of the visited polygons. [opt]
|
/// Pointer to an array of reference ids of the visited polygons. [opt]
|
||||||
public long[] path;
|
public List<long> path;
|
||||||
|
|
||||||
public int pathCount;
|
|
||||||
|
|
||||||
/// The cost of the path until hit.
|
/// The cost of the path until hit.
|
||||||
public float pathCost;
|
public float pathCost;
|
||||||
|
|
||||||
public void AddPathNode(long nodeRef)
|
|
||||||
{
|
|
||||||
path[pathCount++] = nodeRef;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -25,16 +25,11 @@ 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, byte flags, long refs)
|
public DtStraightPath(RcVec3f pos, int 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 byte DT_STRAIGHTPATH_START = 0x01; //< The vertex is the start position in the path.
|
public const int DT_STRAIGHTPATH_START = 0x01; //< The vertex is the start 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_END = 0x02; //< The vertex is the end position in the path.
|
||||||
public const byte DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04; //< The vertex is the start of an off-mesh connection.
|
public const int 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,13 +1,15 @@
|
||||||
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 = CreateCircle();
|
private static readonly float[] UnitCircle = MakeUnitCircle();
|
||||||
|
|
||||||
public static readonly IDtPolygonByCircleConstraint Shared = new DtStrictDtPolygonByCircleConstraint();
|
public static readonly IDtPolygonByCircleConstraint Shared = new DtStrictDtPolygonByCircleConstraint();
|
||||||
|
|
||||||
|
@ -15,7 +17,7 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float[] CreateCircle()
|
private static float[] MakeUnitCircle()
|
||||||
{
|
{
|
||||||
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++)
|
||||||
|
@ -29,23 +31,13 @@ namespace DotRecast.Detour
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ScaleCircle(Span<float> src, RcVec3f center, float radius, Span<float> dst)
|
public float[] Apply(float[] verts, RcVec3f center, float radius)
|
||||||
{
|
|
||||||
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 Span<float> Apply(Span<float> verts, RcVec3f center, float radius, Span<float> resultBuffer)
|
|
||||||
{
|
{
|
||||||
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 (RcVec.Dist2DSqr(center, verts, pv) > radiusSqr)
|
if (RcVecUtils.Dist2DSqr(center, verts, pv) > radiusSqr)
|
||||||
{
|
{
|
||||||
outsideVertex = pv;
|
outsideVertex = pv;
|
||||||
break;
|
break;
|
||||||
|
@ -55,30 +47,32 @@ namespace DotRecast.Detour
|
||||||
if (outsideVertex == -1)
|
if (outsideVertex == -1)
|
||||||
{
|
{
|
||||||
// polygon inside circle
|
// polygon inside circle
|
||||||
var result = resultBuffer.Slice(0, verts.Length);
|
return verts;
|
||||||
verts.CopyTo(result);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Span<float> qCircle = stackalloc float[UnitCircle.Length];
|
float[] qCircle = Circle(center, radius);
|
||||||
ScaleCircle(UnitCircle, center, radius, qCircle);
|
float[] intersection = DtConvexConvexIntersections.Intersect(verts, qCircle);
|
||||||
Span<float> intersection = DtConvexConvexIntersections.Intersect(verts, qCircle, resultBuffer);
|
if (intersection == null && DtUtils.PointInPolygon(center, verts, verts.Length / 3))
|
||||||
if (intersection.IsEmpty && DtUtils.PointInPolygon(center, verts, verts.Length / 3))
|
|
||||||
{
|
{
|
||||||
// circle inside polygon
|
// circle inside polygon
|
||||||
var result = resultBuffer.Slice(0, qCircle.Length);
|
return qCircle;
|
||||||
qCircle.CopyTo(result);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!intersection.IsEmpty)
|
return intersection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private float[] Circle(RcVec3f center, float radius)
|
||||||
{
|
{
|
||||||
var result = resultBuffer.Slice(0, intersection.Length);
|
float[] circle = new float[12 * 3];
|
||||||
// No need to copy, data is already in buffer
|
for (int i = 0; i < CIRCLE_SEGMENTS * 3; i += 3)
|
||||||
return result;
|
{
|
||||||
|
circle[i] = UnitCircle[i] * radius + center.X;
|
||||||
|
circle[i + 1] = center.Y;
|
||||||
|
circle[i + 2] = UnitCircle[i + 2] * radius + center.Z;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Span<float>.Empty;
|
return circle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,13 @@
|
||||||
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--;
|
||||||
|
@ -36,6 +39,24 @@ 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)]
|
||||||
|
@ -43,12 +64,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(ref RcVec3i amin, ref RcVec3i amax, ref RcVec3i bmin, ref RcVec3i bmax)
|
public static bool OverlapQuantBounds(int[] amin, int[] amax, int[] bmin, int[] bmax)
|
||||||
{
|
{
|
||||||
bool overlap = true;
|
bool overlap = true;
|
||||||
overlap = (amin.X > bmax.X || amax.X < bmin.X) ? false : overlap;
|
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
|
||||||
overlap = (amin.Y > bmax.Y || amax.Y < bmin.Y) ? false : overlap;
|
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
|
||||||
overlap = (amin.Z > bmax.Z || amax.Z < bmin.Z) ? false : overlap;
|
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
|
||||||
return overlap;
|
return overlap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +97,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(Span<float> polya, int npolya, Span<float> polyb, int npolyb)
|
public static bool OverlapPolyPoly2D(float[] polya, int npolya, 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++)
|
||||||
|
@ -124,7 +145,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(Span<float> verts, int a, int b, int c)
|
public static float TriArea2D(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];
|
||||||
|
@ -144,7 +165,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 void RandomPointInConvexPoly(Span<float> pts, int npts, Span<float> areas, float s, float t, out RcVec3f @out)
|
public static RcVec3f RandomPointInConvexPoly(float[] pts, int npts, float[] areas, float s, float t)
|
||||||
{
|
{
|
||||||
// Calc triangle araes
|
// Calc triangle araes
|
||||||
float areasum = 0.0f;
|
float areasum = 0.0f;
|
||||||
|
@ -181,7 +202,7 @@ namespace DotRecast.Detour
|
||||||
int pb = (tri - 1) * 3;
|
int pb = (tri - 1) * 3;
|
||||||
int pc = tri * 3;
|
int pc = tri * 3;
|
||||||
|
|
||||||
@out = new RcVec3f()
|
return 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],
|
||||||
|
@ -225,13 +246,13 @@ namespace DotRecast.Detour
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RcVec2f ProjectPoly(RcVec3f axis, Span<float> poly, int npoly)
|
public static RcVec2f ProjectPoly(RcVec3f axis, float[] poly, int npoly)
|
||||||
{
|
{
|
||||||
float rmin, rmax;
|
float rmin, rmax;
|
||||||
rmin = rmax = axis.Dot2D(new RcVec3f(poly));
|
rmin = rmax = axis.Dot2D(poly, 0);
|
||||||
for (int i = 1; i < npoly; ++i)
|
for (int i = 1; i < npoly; ++i)
|
||||||
{
|
{
|
||||||
float d = axis.Dot2D(RcVec.Create(poly, i * 3));
|
float d = axis.Dot2D(poly, i * 3);
|
||||||
rmin = Math.Min(rmin, d);
|
rmin = Math.Min(rmin, d);
|
||||||
rmax = Math.Max(rmax, d);
|
rmax = Math.Max(rmax, d);
|
||||||
}
|
}
|
||||||
|
@ -246,7 +267,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, Span<float> verts, int nverts)
|
public static bool PointInPolygon(RcVec3f pt, float[] verts, int nverts)
|
||||||
{
|
{
|
||||||
// TODO: Replace pnpoly with triArea2D tests?
|
// TODO: Replace pnpoly with triArea2D tests?
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -265,7 +286,7 @@ namespace DotRecast.Detour
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool DistancePtPolyEdgesSqr(RcVec3f pt, Span<float> verts, int nverts, Span<float> ed, Span<float> et)
|
public static bool DistancePtPolyEdgesSqr(RcVec3f pt, float[] verts, int nverts, float[] ed, float[] et)
|
||||||
{
|
{
|
||||||
// TODO: Replace pnpoly with triArea2D tests?
|
// TODO: Replace pnpoly with triArea2D tests?
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -286,10 +307,10 @@ namespace DotRecast.Detour
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float DistancePtSegSqr2D(RcVec3f pt, Span<float> verts, int p, int q, out float t)
|
public static float DistancePtSegSqr2D(RcVec3f pt, float[] verts, int p, int q, out float t)
|
||||||
{
|
{
|
||||||
var vp = RcVec.Create(verts, p);
|
var vp = RcVecUtils.Create(verts, p);
|
||||||
var vq = RcVec.Create(verts, q);
|
var vq = RcVecUtils.Create(verts, q);
|
||||||
return DistancePtSegSqr2D(pt, vp, vq, out t);
|
return DistancePtSegSqr2D(pt, vp, vq, out t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,7 +342,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IntersectSegmentPoly2D(RcVec3f p0, RcVec3f p1,
|
public static bool IntersectSegmentPoly2D(RcVec3f p0, RcVec3f p1,
|
||||||
Span<RcVec3f> verts, int nverts,
|
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)
|
||||||
{
|
{
|
||||||
|
@ -341,8 +362,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 = RcVec.Perp2D(edge, diff);
|
float n = RcVecUtils.Perp2D(edge, diff);
|
||||||
float d = RcVec.Perp2D(dir, edge);
|
float d = RcVecUtils.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
|
||||||
|
@ -404,14 +425,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 = RcVec.PerpXZ(u, v);
|
float d = RcVecUtils.PerpXZ(u, v);
|
||||||
if (MathF.Abs(d) < 1e-6f)
|
if (MathF.Abs(d) < 1e-6f)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = RcVec.PerpXZ(v, w) / d;
|
s = RcVecUtils.PerpXZ(v, w) / d;
|
||||||
t = RcVec.PerpXZ(u, w) / d;
|
t = RcVecUtils.PerpXZ(u, w) / d;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,7 @@
|
||||||
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
|
||||||
{
|
{
|
||||||
/// Called for each batch of unique polygons touched by the search area in dtNavMeshQuery::queryPolygons.
|
void Process(DtMeshTile tile, DtPoly poly, long refs);
|
||||||
/// This can be called multiple times for a single query.
|
|
||||||
void Process(DtMeshTile tile, Span<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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -24,6 +24,6 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
public interface IDtPolygonByCircleConstraint
|
public interface IDtPolygonByCircleConstraint
|
||||||
{
|
{
|
||||||
Span<float> Apply(Span<float> polyVerts, RcVec3f circleCenter, float radius, Span<float> resultBuffer);
|
float[] Apply(float[] polyVerts, RcVec3f circleCenter, float radius);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -21,17 +21,13 @@ 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 = RcIO.ToByteBuffer(stream);
|
RcByteBuffer buf = IOUtils.ToByteBuffer(stream);
|
||||||
return Read(buf, maxVertPerPoly, false);
|
return Read(buf, maxVertPerPoly, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +38,7 @@ namespace DotRecast.Detour.Io
|
||||||
|
|
||||||
public DtMeshData Read32Bit(BinaryReader stream, int maxVertPerPoly)
|
public DtMeshData Read32Bit(BinaryReader stream, int maxVertPerPoly)
|
||||||
{
|
{
|
||||||
RcByteBuffer buf = RcIO.ToByteBuffer(stream);
|
RcByteBuffer buf = IOUtils.ToByteBuffer(stream);
|
||||||
return Read(buf, maxVertPerPoly, true);
|
return Read(buf, maxVertPerPoly, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,10 +53,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 != DT_NAVMESH_MAGIC)
|
if (header.magic != DtNavMesh.DT_NAVMESH_MAGIC)
|
||||||
{
|
{
|
||||||
header.magic = RcIO.SwapEndianness(header.magic);
|
header.magic = IOUtils.SwapEndianness(header.magic);
|
||||||
if (header.magic != DT_NAVMESH_MAGIC)
|
if (header.magic != DtNavMesh.DT_NAVMESH_MAGIC)
|
||||||
{
|
{
|
||||||
throw new IOException("Invalid magic");
|
throw new IOException("Invalid magic");
|
||||||
}
|
}
|
||||||
|
@ -69,16 +65,16 @@ namespace DotRecast.Detour.Io
|
||||||
}
|
}
|
||||||
|
|
||||||
header.version = buf.GetInt();
|
header.version = buf.GetInt();
|
||||||
if (header.version != DT_NAVMESH_VERSION)
|
if (header.version != DtNavMesh.DT_NAVMESH_VERSION)
|
||||||
{
|
{
|
||||||
if (header.version < DT_NAVMESH_VERSION_RECAST4J_FIRST
|
if (header.version < DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_FIRST
|
||||||
|| header.version > DT_NAVMESH_VERSION_RECAST4J_LAST)
|
|| header.version > DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_LAST)
|
||||||
{
|
{
|
||||||
throw new IOException("Invalid version " + header.version);
|
throw new IOException("Invalid version " + header.version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cCompatibility = header.version == DT_NAVMESH_VERSION;
|
bool cCompatibility = header.version == DtNavMesh.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();
|
||||||
|
@ -120,6 +116,8 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -143,7 +141,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 < DT_NAVMESH_VERSION_RECAST4J_NO_POLY_FIRSTLINK)
|
if (header.version < DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_NO_POLY_FIRSTLINK)
|
||||||
{
|
{
|
||||||
buf.GetInt(); // polys[i].firstLink
|
buf.GetInt(); // polys[i].firstLink
|
||||||
}
|
}
|
||||||
|
@ -173,8 +171,8 @@ namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
int vertBase = buf.GetInt();
|
int vertBase = buf.GetInt();
|
||||||
int triBase = buf.GetInt();
|
int triBase = buf.GetInt();
|
||||||
byte vertCount = (byte)(buf.Get() & 0xFF);
|
int vertCount = buf.Get() & 0xFF;
|
||||||
byte triCount = (byte)(buf.Get() & 0xFF);
|
int triCount = buf.Get() & 0xFF;
|
||||||
polys[i] = new DtPolyDetail(vertBase, triBase, vertCount, triCount);
|
polys[i] = new DtPolyDetail(vertBase, triBase, vertCount, triCount);
|
||||||
if (cCompatibility)
|
if (cCompatibility)
|
||||||
{
|
{
|
||||||
|
@ -202,25 +200,29 @@ 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 < DT_NAVMESH_VERSION_RECAST4J_32BIT_BVTREE)
|
if (header.version < DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_32BIT_BVTREE)
|
||||||
{
|
{
|
||||||
nodes[i].bmin.X = buf.GetShort() & 0xFFFF;
|
for (int j = 0; j < 3; j++)
|
||||||
nodes[i].bmin.Y = buf.GetShort() & 0xFFFF;
|
{
|
||||||
nodes[i].bmin.Z = buf.GetShort() & 0xFFFF;
|
nodes[i].bmin[j] = buf.GetShort() & 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
nodes[i].bmax.X = buf.GetShort() & 0xFFFF;
|
for (int j = 0; j < 3; j++)
|
||||||
nodes[i].bmax.Y = buf.GetShort() & 0xFFFF;
|
{
|
||||||
nodes[i].bmax.Z = buf.GetShort() & 0xFFFF;
|
nodes[i].bmax[j] = buf.GetShort() & 0xFFFF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nodes[i].bmin.X = buf.GetInt();
|
for (int j = 0; j < 3; j++)
|
||||||
nodes[i].bmin.Y = buf.GetInt();
|
{
|
||||||
nodes[i].bmin.Z = buf.GetInt();
|
nodes[i].bmin[j] = buf.GetInt();
|
||||||
|
}
|
||||||
|
|
||||||
nodes[i].bmax.X = buf.GetInt();
|
for (int j = 0; j < 3; j++)
|
||||||
nodes[i].bmax.Y = buf.GetInt();
|
{
|
||||||
nodes[i].bmax.Z = buf.GetInt();
|
nodes[i].bmax[j] = buf.GetInt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes[i].i = buf.GetInt();
|
nodes[i].i = buf.GetInt();
|
||||||
|
|
|
@ -21,38 +21,36 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Io
|
namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
using static DtDetour;
|
public class DtMeshDataWriter : DtWriter
|
||||||
|
|
||||||
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;
|
||||||
RcIO.Write(stream, header.magic, order);
|
Write(stream, header.magic, order);
|
||||||
RcIO.Write(stream, cCompatibility ? DT_NAVMESH_VERSION : DT_NAVMESH_VERSION_RECAST4J_LAST, order);
|
Write(stream, cCompatibility ? DtNavMesh.DT_NAVMESH_VERSION : DtNavMesh.DT_NAVMESH_VERSION_RECAST4J_LAST, order);
|
||||||
RcIO.Write(stream, header.x, order);
|
Write(stream, header.x, order);
|
||||||
RcIO.Write(stream, header.y, order);
|
Write(stream, header.y, order);
|
||||||
RcIO.Write(stream, header.layer, order);
|
Write(stream, header.layer, order);
|
||||||
RcIO.Write(stream, header.userId, order);
|
Write(stream, header.userId, order);
|
||||||
RcIO.Write(stream, header.polyCount, order);
|
Write(stream, header.polyCount, order);
|
||||||
RcIO.Write(stream, header.vertCount, order);
|
Write(stream, header.vertCount, order);
|
||||||
RcIO.Write(stream, header.maxLinkCount, order);
|
Write(stream, header.maxLinkCount, order);
|
||||||
RcIO.Write(stream, header.detailMeshCount, order);
|
Write(stream, header.detailMeshCount, order);
|
||||||
RcIO.Write(stream, header.detailVertCount, order);
|
Write(stream, header.detailVertCount, order);
|
||||||
RcIO.Write(stream, header.detailTriCount, order);
|
Write(stream, header.detailTriCount, order);
|
||||||
RcIO.Write(stream, header.bvNodeCount, order);
|
Write(stream, header.bvNodeCount, order);
|
||||||
RcIO.Write(stream, header.offMeshConCount, order);
|
Write(stream, header.offMeshConCount, order);
|
||||||
RcIO.Write(stream, header.offMeshBase, order);
|
Write(stream, header.offMeshBase, order);
|
||||||
RcIO.Write(stream, header.walkableHeight, order);
|
Write(stream, header.walkableHeight, order);
|
||||||
RcIO.Write(stream, header.walkableRadius, order);
|
Write(stream, header.walkableRadius, order);
|
||||||
RcIO.Write(stream, header.walkableClimb, order);
|
Write(stream, header.walkableClimb, order);
|
||||||
RcIO.Write(stream, header.bmin.X, order);
|
Write(stream, header.bmin.X, order);
|
||||||
RcIO.Write(stream, header.bmin.Y, order);
|
Write(stream, header.bmin.Y, order);
|
||||||
RcIO.Write(stream, header.bmin.Z, order);
|
Write(stream, header.bmin.Z, order);
|
||||||
RcIO.Write(stream, header.bmax.X, order);
|
Write(stream, header.bmax.X, order);
|
||||||
RcIO.Write(stream, header.bmax.Y, order);
|
Write(stream, header.bmax.Y, order);
|
||||||
RcIO.Write(stream, header.bmax.Z, order);
|
Write(stream, header.bmax.Z, order);
|
||||||
RcIO.Write(stream, header.bvQuantFactor, order);
|
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)
|
||||||
|
@ -72,7 +70,7 @@ namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count * 3; i++)
|
for (int i = 0; i < count * 3; i++)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, verts[i], order);
|
Write(stream, verts[i], order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,22 +80,22 @@ namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
if (cCompatibility)
|
if (cCompatibility)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, 0xFFFF, order);
|
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++)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, (short)data.polys[i].verts[j], order);
|
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++)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, (short)data.polys[i].neis[j], order);
|
Write(stream, (short)data.polys[i].neis[j], order);
|
||||||
}
|
}
|
||||||
|
|
||||||
RcIO.Write(stream, (short)data.polys[i].flags, order);
|
Write(stream, (short)data.polys[i].flags, order);
|
||||||
RcIO.Write(stream, (byte)data.polys[i].vertCount);
|
Write(stream, (byte)data.polys[i].vertCount);
|
||||||
RcIO.Write(stream, (byte)data.polys[i].areaAndtype);
|
Write(stream, (byte)data.polys[i].areaAndtype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,13 +103,13 @@ namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
for (int i = 0; i < data.header.detailMeshCount; i++)
|
for (int i = 0; i < data.header.detailMeshCount; i++)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, data.detailMeshes[i].vertBase, order);
|
Write(stream, data.detailMeshes[i].vertBase, order);
|
||||||
RcIO.Write(stream, data.detailMeshes[i].triBase, order);
|
Write(stream, data.detailMeshes[i].triBase, order);
|
||||||
RcIO.Write(stream, (byte)data.detailMeshes[i].vertCount);
|
Write(stream, (byte)data.detailMeshes[i].vertCount);
|
||||||
RcIO.Write(stream, (byte)data.detailMeshes[i].triCount);
|
Write(stream, (byte)data.detailMeshes[i].triCount);
|
||||||
if (cCompatibility)
|
if (cCompatibility)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, (short)0, order);
|
Write(stream, (short)0, order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,7 +118,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++)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, (byte)data.detailTris[i]);
|
Write(stream, (byte)data.detailTris[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,26 +128,30 @@ namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
if (cCompatibility)
|
if (cCompatibility)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, (short)data.bvTree[i].bmin.X, order);
|
for (int j = 0; j < 3; j++)
|
||||||
RcIO.Write(stream, (short)data.bvTree[i].bmin.Y, order);
|
{
|
||||||
RcIO.Write(stream, (short)data.bvTree[i].bmin.Z, order);
|
Write(stream, (short)data.bvTree[i].bmin[j], order);
|
||||||
|
}
|
||||||
|
|
||||||
RcIO.Write(stream, (short)data.bvTree[i].bmax.X, order);
|
for (int j = 0; j < 3; j++)
|
||||||
RcIO.Write(stream, (short)data.bvTree[i].bmax.Y, order);
|
{
|
||||||
RcIO.Write(stream, (short)data.bvTree[i].bmax.Z, order);
|
Write(stream, (short)data.bvTree[i].bmax[j], order);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, data.bvTree[i].bmin.X, order);
|
for (int j = 0; j < 3; j++)
|
||||||
RcIO.Write(stream, data.bvTree[i].bmin.Y, order);
|
{
|
||||||
RcIO.Write(stream, data.bvTree[i].bmin.Z, order);
|
Write(stream, data.bvTree[i].bmin[j], order);
|
||||||
|
|
||||||
RcIO.Write(stream, data.bvTree[i].bmax.X, order);
|
|
||||||
RcIO.Write(stream, data.bvTree[i].bmax.Y, order);
|
|
||||||
RcIO.Write(stream, data.bvTree[i].bmax.Z, order);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RcIO.Write(stream, data.bvTree[i].i, order);
|
for (int j = 0; j < 3; j++)
|
||||||
|
{
|
||||||
|
Write(stream, data.bvTree[i].bmax[j], order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write(stream, data.bvTree[i].i, order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,16 +161,16 @@ namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
for (int j = 0; j < 2; j++)
|
for (int j = 0; j < 2; j++)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, data.offMeshCons[i].pos[j].X, order);
|
Write(stream, data.offMeshCons[i].pos[j].X, order);
|
||||||
RcIO.Write(stream, data.offMeshCons[i].pos[j].Y, order);
|
Write(stream, data.offMeshCons[i].pos[j].Y, order);
|
||||||
RcIO.Write(stream, data.offMeshCons[i].pos[j].Z, order);
|
Write(stream, data.offMeshCons[i].pos[j].Z, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
RcIO.Write(stream, data.offMeshCons[i].rad, order);
|
Write(stream, data.offMeshCons[i].rad, order);
|
||||||
RcIO.Write(stream, (short)data.offMeshCons[i].poly, order);
|
Write(stream, (short)data.offMeshCons[i].poly, order);
|
||||||
RcIO.Write(stream, (byte)data.offMeshCons[i].flags);
|
Write(stream, (byte)data.offMeshCons[i].flags);
|
||||||
RcIO.Write(stream, (byte)data.offMeshCons[i].side);
|
Write(stream, (byte)data.offMeshCons[i].side);
|
||||||
RcIO.Write(stream, data.offMeshCons[i].userId, order);
|
Write(stream, data.offMeshCons[i].userId, order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,6 @@ 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();
|
||||||
|
@ -31,7 +29,7 @@ namespace DotRecast.Detour.Io
|
||||||
|
|
||||||
public DtNavMesh Read(BinaryReader @is, int maxVertPerPoly)
|
public DtNavMesh Read(BinaryReader @is, int maxVertPerPoly)
|
||||||
{
|
{
|
||||||
return Read(RcIO.ToByteBuffer(@is), maxVertPerPoly, false);
|
return Read(IOUtils.ToByteBuffer(@is), maxVertPerPoly, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtNavMesh Read(RcByteBuffer bb, int maxVertPerPoly)
|
public DtNavMesh Read(RcByteBuffer bb, int maxVertPerPoly)
|
||||||
|
@ -41,7 +39,7 @@ namespace DotRecast.Detour.Io
|
||||||
|
|
||||||
public DtNavMesh Read32Bit(BinaryReader @is, int maxVertPerPoly)
|
public DtNavMesh Read32Bit(BinaryReader @is, int maxVertPerPoly)
|
||||||
{
|
{
|
||||||
return Read(RcIO.ToByteBuffer(@is), maxVertPerPoly, true);
|
return Read(IOUtils.ToByteBuffer(@is), maxVertPerPoly, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtNavMesh Read32Bit(RcByteBuffer bb, int maxVertPerPoly)
|
public DtNavMesh Read32Bit(RcByteBuffer bb, int maxVertPerPoly)
|
||||||
|
@ -51,7 +49,7 @@ namespace DotRecast.Detour.Io
|
||||||
|
|
||||||
public DtNavMesh Read(BinaryReader @is)
|
public DtNavMesh Read(BinaryReader @is)
|
||||||
{
|
{
|
||||||
return Read(RcIO.ToByteBuffer(@is));
|
return Read(IOUtils.ToByteBuffer(@is));
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtNavMesh Read(RcByteBuffer bb)
|
public DtNavMesh Read(RcByteBuffer bb)
|
||||||
|
@ -68,8 +66,7 @@ namespace DotRecast.Detour.Io
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cCompatibility = header.version == NavMeshSetHeader.NAVMESHSET_VERSION;
|
bool cCompatibility = header.version == NavMeshSetHeader.NAVMESHSET_VERSION;
|
||||||
DtNavMesh mesh = new DtNavMesh();
|
DtNavMesh mesh = new DtNavMesh(header.option, header.maxVertsPerPoly);
|
||||||
mesh.Init(header.option, header.maxVertsPerPoly);
|
|
||||||
ReadTiles(bb, is32Bit, ref header, cCompatibility, mesh);
|
ReadTiles(bb, is32Bit, ref header, cCompatibility, mesh);
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
@ -80,7 +77,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 = RcIO.SwapEndianness(header.magic);
|
header.magic = IOUtils.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);
|
||||||
|
@ -134,7 +131,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, out _);
|
mesh.AddTile(data, i, tileHeader.tileRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +147,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 EncodePolyId(salt, it, ip);
|
return DtNavMesh.EncodePolyId(salt, it, ip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Io
|
namespace DotRecast.Detour.Io
|
||||||
{
|
{
|
||||||
public class DtMeshSetWriter
|
public class DtMeshSetWriter : DtWriter
|
||||||
{
|
{
|
||||||
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)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, NavMeshSetHeader.NAVMESHSET_MAGIC, order);
|
Write(stream, NavMeshSetHeader.NAVMESHSET_MAGIC, order);
|
||||||
RcIO.Write(stream, cCompatibility ? NavMeshSetHeader.NAVMESHSET_VERSION : NavMeshSetHeader.NAVMESHSET_VERSION_RECAST4J, order);
|
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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
RcIO.Write(stream, numTiles, order);
|
Write(stream, numTiles, order);
|
||||||
paramWriter.Write(stream, mesh.GetParams(), order);
|
paramWriter.Write(stream, mesh.GetParams(), order);
|
||||||
if (!cCompatibility)
|
if (!cCompatibility)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, mesh.GetMaxVertsPerPoly(), order);
|
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;
|
||||||
RcIO.Write(stream, tileHeader.tileRef, order);
|
Write(stream, tileHeader.tileRef, order);
|
||||||
RcIO.Write(stream, tileHeader.dataSize, order);
|
Write(stream, tileHeader.dataSize, order);
|
||||||
if (cCompatibility)
|
if (cCompatibility)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, 0, order); // C struct padding
|
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
|
public class DtNavMeshParamWriter : DtWriter
|
||||||
{
|
{
|
||||||
public void Write(BinaryWriter stream, DtNavMeshParams option, RcByteOrder order)
|
public void Write(BinaryWriter stream, DtNavMeshParams option, RcByteOrder order)
|
||||||
{
|
{
|
||||||
RcIO.Write(stream, option.orig.X, order);
|
Write(stream, option.orig.X, order);
|
||||||
RcIO.Write(stream, option.orig.Y, order);
|
Write(stream, option.orig.Y, order);
|
||||||
RcIO.Write(stream, option.orig.Z, order);
|
Write(stream, option.orig.Z, order);
|
||||||
RcIO.Write(stream, option.tileWidth, order);
|
Write(stream, option.tileWidth, order);
|
||||||
RcIO.Write(stream, option.tileHeight, order);
|
Write(stream, option.tileHeight, order);
|
||||||
RcIO.Write(stream, option.maxTiles, order);
|
Write(stream, option.maxTiles, order);
|
||||||
RcIO.Write(stream, option.maxPolys, order);
|
Write(stream, option.maxPolys, order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -32,7 +32,6 @@ 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;
|
||||||
|
|
||||||
|
@ -57,11 +56,6 @@ 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;
|
||||||
|
@ -92,10 +86,9 @@ namespace DotRecast.Recast.Demo
|
||||||
_changed = changed;
|
_changed = changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(DemoInputGeomProvider geom, RcConfig cfg, IList<RcBuilderResult> recastResults, DtNavMesh navMesh)
|
public void Update(DemoInputGeomProvider geom, IList<RcBuilderResult> recastResults, DtNavMesh navMesh)
|
||||||
{
|
{
|
||||||
_geom = geom;
|
_geom = geom;
|
||||||
_cfg = cfg;
|
|
||||||
_recastResults = recastResults;
|
_recastResults = recastResults;
|
||||||
_navMesh = navMesh;
|
_navMesh = navMesh;
|
||||||
SetQuery(navMesh);
|
SetQuery(navMesh);
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Recast.Demo",
|
|
||||||
"rootNamespace": "DotRecast.Recast.Demo",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Core"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [
|
|
||||||
"Android",
|
|
||||||
"Editor",
|
|
||||||
"EmbeddedLinux",
|
|
||||||
"GameCoreScarlett",
|
|
||||||
"GameCoreXboxOne",
|
|
||||||
"iOS",
|
|
||||||
"LinuxStandalone64",
|
|
||||||
"CloudRendering",
|
|
||||||
"macOSStandalone",
|
|
||||||
"PS4",
|
|
||||||
"PS5",
|
|
||||||
"QNX",
|
|
||||||
"Stadia",
|
|
||||||
"Switch",
|
|
||||||
"tvOS",
|
|
||||||
"WSA",
|
|
||||||
"VisionOS",
|
|
||||||
"WebGL",
|
|
||||||
"WindowsStandalone32",
|
|
||||||
"WindowsStandalone64",
|
|
||||||
"XboxOne"
|
|
||||||
],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [
|
|
||||||
{
|
|
||||||
"name": "Select...",
|
|
||||||
"expression": "",
|
|
||||||
"define": "USE_RECAST_DEMO"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"noEngineReferences": true
|
|
||||||
}
|
|
|
@ -20,15 +20,15 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Serilog" Version="4.1.0" />
|
<PackageReference Include="Serilog" Version="3.1.1" />
|
||||||
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.4" />
|
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.0" />
|
||||||
<PackageReference Include="Serilog.Enrichers.Thread" Version="4.0.0" />
|
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0"/>
|
||||||
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />
|
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0"/>
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0"/>
|
||||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.8" />
|
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.6"/>
|
||||||
<PackageReference Include="Silk.NET" Version="2.22.0" />
|
<PackageReference Include="Silk.NET" Version="2.20.0" />
|
||||||
<PackageReference Include="Silk.NET.OpenGL.Extensions.ImGui" Version="2.22.0" />
|
<PackageReference Include="Silk.NET.OpenGL.Extensions.ImGui" Version="2.20.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() : this(512) { }
|
public ArrayBuffer()
|
||||||
|
|
||||||
public ArrayBuffer(int capacity)
|
|
||||||
{
|
{
|
||||||
if (capacity <= 0)
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
|
|
||||||
_size = 0;
|
_size = 0;
|
||||||
_items = new T[capacity];
|
_items = Array.Empty<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
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 Span<T> AsArray()
|
public T[] AsArray()
|
||||||
{
|
{
|
||||||
return _items.AsSpan(0, _size);
|
return _items;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -326,9 +326,9 @@ public class DebugDraw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const int NUM_ARC_PTS = 8;
|
private static readonly int NUM_ARC_PTS = 8;
|
||||||
private const float PAD = 0.05f;
|
private static readonly float PAD = 0.05f;
|
||||||
private const float ARC_PTS_SCALE = (1.0f - PAD * 2) / NUM_ARC_PTS;
|
private static readonly 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(Span<float> bounds)
|
public bool FrustumTest(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(stackalloc float[] { bmin.X, bmin.Y, bmin.Z, bmax.X, bmax.Y, bmax.Z });
|
return FrustumTest(new 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -32,18 +32,15 @@ public class GLCheckerTexture
|
||||||
_gl = gl;
|
_gl = gl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void Release()
|
public void Release()
|
||||||
{
|
{
|
||||||
if (m_texId != 0)
|
if (m_texId != 0)
|
||||||
{
|
{
|
||||||
fixed (uint* p = &m_texId)
|
_gl.DeleteTextures(1, m_texId);
|
||||||
{
|
|
||||||
_gl.DeleteTextures(1, p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void Bind()
|
public void Bind()
|
||||||
{
|
{
|
||||||
if (m_texId == 0)
|
if (m_texId == 0)
|
||||||
{
|
{
|
||||||
|
@ -53,11 +50,7 @@ public class GLCheckerTexture
|
||||||
uint TSIZE = 64;
|
uint TSIZE = 64;
|
||||||
int[] data = new int[TSIZE * TSIZE];
|
int[] data = new int[TSIZE * TSIZE];
|
||||||
|
|
||||||
fixed (uint* p = &m_texId)
|
_gl.GenTextures(1, out m_texId);
|
||||||
{
|
|
||||||
_gl.GenTextures(1, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
_gl.BindTexture(GLEnum.Texture2D, m_texId);
|
_gl.BindTexture(GLEnum.Texture2D, m_texId);
|
||||||
|
|
||||||
int level = 0;
|
int level = 0;
|
||||||
|
@ -77,10 +70,8 @@ public class GLCheckerTexture
|
||||||
level++;
|
level++;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint linearMipmapNearest = (uint)GLEnum.LinearMipmapNearest;
|
_gl.TexParameterI(GLEnum.Texture2D, GLEnum.TextureMinFilter, (uint)GLEnum.LinearMipmapNearest);
|
||||||
uint linear = (uint)GLEnum.Linear;
|
_gl.TexParameterI(GLEnum.Texture2D, GLEnum.TextureMagFilter, (uint)GLEnum.Linear);
|
||||||
_gl.TexParameterI(GLEnum.Texture2D, GLEnum.TextureMinFilter, &linearMipmapNearest);
|
|
||||||
_gl.TexParameterI(GLEnum.Texture2D, GLEnum.TextureMagFilter, &linear);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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
|
||||||
|
@ -69,8 +68,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
|
||||||
Span<float> m = stackalloc float[16], A = stackalloc float[16];
|
float[] m = new float[16], A = new float[16];
|
||||||
Span<float> @in = stackalloc float[4], @out = stackalloc float[4];
|
float[] @in = new float[4], @out = new 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);
|
||||||
|
@ -93,7 +92,7 @@ public static class GLU
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MultiplyMatrices4by4OpenGL_FLOAT(Span<float> result, float[] matrix1, float[] matrix2)
|
static void MultiplyMatrices4by4OpenGL_FLOAT(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];
|
||||||
|
@ -116,7 +115,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(Span<float> resultvector, Span<float> matrix, Span<float> pvector)
|
static void MultiplyMatrixByVector4by4OpenGL_FLOAT(float[] resultvector, float[] matrix, 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];
|
||||||
|
@ -125,13 +124,15 @@ 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(Span<float> m, Span<float> @out)
|
static int GlhInvertMatrixf2(float[] m, float[] @out)
|
||||||
{
|
{
|
||||||
|
float[][] wtmp = RcArrays.Of<float>(4, 8);
|
||||||
float m0, m1, m2, m3, s;
|
float m0, m1, m2, m3, s;
|
||||||
Span<float> r0 = stackalloc float[8];
|
float[] r0, r1, r2, r3;
|
||||||
Span<float> r1 = stackalloc float[8];
|
r0 = wtmp[0];
|
||||||
Span<float> r2 = stackalloc float[8];
|
r1 = wtmp[1];
|
||||||
Span<float> r3 = stackalloc float[8];
|
r2 = wtmp[2];
|
||||||
|
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);
|
||||||
|
@ -159,28 +160,27 @@ 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]))
|
||||||
{
|
{
|
||||||
Span<float> r = r2;
|
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]))
|
||||||
{
|
{
|
||||||
Span<float> r = r2;
|
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]))
|
||||||
{
|
{
|
||||||
Span<float> r = r1;
|
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]))
|
||||||
{
|
{
|
||||||
Span<float> r = r2;
|
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]))
|
||||||
{
|
{
|
||||||
Span<float> r = r2;
|
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]))
|
||||||
{
|
{
|
||||||
Span<float> r = r2;
|
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(Span<float> m, int r, int c)
|
static float MAT(float[] m, int r, int c)
|
||||||
{
|
{
|
||||||
return m[(c) * 4 + (r)];
|
return m[(c) * 4 + (r)];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MAT(Span<float> m, int r, int c, float v)
|
static void MAT(float[] m, int r, int c, float v)
|
||||||
{
|
{
|
||||||
m[(c) * 4 + (r)] = v;
|
m[(c) * 4 + (r)] = v;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
using System.Numerics;
|
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Demo.Draw;
|
namespace DotRecast.Recast.Demo.Draw;
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
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;
|
||||||
|
@ -20,8 +19,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(512);
|
private readonly ArrayBuffer<OpenGLVertex> vertices = new();
|
||||||
private readonly ArrayBuffer<int> elements = new(512);
|
private readonly ArrayBuffer<int> elements = new();
|
||||||
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];
|
||||||
|
@ -37,42 +36,36 @@ public class ModernOpenGLDraw : IOpenGLDraw
|
||||||
|
|
||||||
public unsafe void Init()
|
public unsafe void Init()
|
||||||
{
|
{
|
||||||
const string SHADER_VERSION = "#version 400\n";
|
string SHADER_VERSION = "#version 400\n";
|
||||||
const string vertex_shader = $@"
|
string vertex_shader = SHADER_VERSION + "uniform mat4 ProjMtx;\n" //
|
||||||
{SHADER_VERSION}
|
+ "uniform mat4 ViewMtx;\n" //
|
||||||
uniform mat4 ProjMtx;
|
+ "in vec3 Position;\n" //
|
||||||
uniform mat4 ViewMtx;
|
+ "in vec2 TexCoord;\n" //
|
||||||
in vec3 Position;
|
+ "in vec4 Color;\n" //
|
||||||
in vec2 TexCoord;
|
+ "out vec2 Frag_UV;\n" //
|
||||||
in vec4 Color;
|
+ "out vec4 Frag_Color;\n" //
|
||||||
out vec2 Frag_UV;
|
+ "out float Frag_Depth;\n" //
|
||||||
out vec4 Frag_Color;
|
+ "void main() {\n" //
|
||||||
out float Frag_Depth;
|
+ " Frag_UV = TexCoord;\n" //
|
||||||
void main() {{
|
+ " Frag_Color = Color;\n" //
|
||||||
Frag_UV = TexCoord;
|
+ " vec4 VSPosition = ViewMtx * vec4(Position, 1);\n" //
|
||||||
Frag_Color = Color;
|
+ " Frag_Depth = -VSPosition.z;\n" //
|
||||||
vec4 VSPosition = ViewMtx * vec4(Position, 1);
|
+ " gl_Position = ProjMtx * VSPosition;\n" //
|
||||||
Frag_Depth = -VSPosition.z;
|
+ "}\n";
|
||||||
gl_Position = ProjMtx * VSPosition;
|
string fragment_shader = SHADER_VERSION + "precision mediump float;\n" //
|
||||||
}}
|
+ "uniform sampler2D Texture;\n" //
|
||||||
";
|
+ "uniform float UseTexture;\n" //
|
||||||
const string fragment_shader = $@"
|
+ "uniform float EnableFog;\n" //
|
||||||
{SHADER_VERSION}
|
+ "uniform float FogStart;\n" //
|
||||||
precision mediump float;
|
+ "uniform float FogEnd;\n" //
|
||||||
uniform sampler2D Texture;
|
+ "const vec4 FogColor = vec4(0.3f, 0.3f, 0.32f, 1.0f);\n" //
|
||||||
uniform float UseTexture;
|
+ "in vec2 Frag_UV;\n" //
|
||||||
uniform float EnableFog;
|
+ "in vec4 Frag_Color;\n" //
|
||||||
uniform float FogStart;
|
+ "in float Frag_Depth;\n" //
|
||||||
uniform float FogEnd;
|
+ "out vec4 Out_Color;\n" //
|
||||||
const vec4 FogColor = vec4(0.3f, 0.3f, 0.32f, 1.0f);
|
+ "void main(){\n" //
|
||||||
in vec2 Frag_UV;
|
+ " 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 vec4 Frag_Color;
|
+ "}\n";
|
||||||
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);
|
||||||
|
@ -157,10 +150,6 @@ void main(){{
|
||||||
_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()
|
||||||
|
@ -202,18 +191,35 @@ void main(){{
|
||||||
// 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);
|
||||||
|
|
||||||
_gl.BufferData<OpenGLVertex>(GLEnum.ArrayBuffer, vertices.AsArray(), GLEnum.DynamicDraw);
|
uint vboSize = (uint)vertices.Count * 24;
|
||||||
|
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
|
||||||
|
|
||||||
|
{
|
||||||
|
byte* pVerts = (byte*)_gl.MapBuffer(GLEnum.ArrayBuffer, GLEnum.WriteOnly);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
if (currentPrim == DebugDrawPrimitives.QUADS)
|
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)
|
for (int i = 0; i < vertices.Count; i += 4)
|
||||||
{
|
{
|
||||||
elements.Add(i);
|
bw.Write(i);
|
||||||
elements.Add(i + 1);
|
bw.Write(i + 1);
|
||||||
elements.Add(i + 2);
|
bw.Write(i + 2);
|
||||||
elements.Add(i);
|
bw.Write(i);
|
||||||
elements.Add(i + 2);
|
bw.Write(i + 2);
|
||||||
elements.Add(i + 3);
|
bw.Write(i + 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -222,10 +228,16 @@ void main(){{
|
||||||
{
|
{
|
||||||
elements.Add(i);
|
elements.Add(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fixed (void* e = elements.AsArray())
|
||||||
|
{
|
||||||
|
System.Buffer.MemoryCopy(e, pElems, eboSize, eboSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_gl.BufferData<int>(GLEnum.ElementArrayBuffer, elements.AsArray(), GLEnum.DynamicDraw);
|
_gl.UnmapBuffer(GLEnum.ElementArrayBuffer);
|
||||||
|
_gl.UnmapBuffer(GLEnum.ArrayBuffer);
|
||||||
|
}
|
||||||
if (_texture != null)
|
if (_texture != null)
|
||||||
{
|
{
|
||||||
_texture.Bind();
|
_texture.Bind();
|
||||||
|
@ -259,22 +271,15 @@ void main(){{
|
||||||
_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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -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.RcRecast;
|
using static DotRecast.Recast.RcCommons;
|
||||||
|
|
||||||
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.DU_DRAWNAVMESH_OFFMESHCONS | RecastDebugDraw.DU_DRAWNAVMESH_CLOSEDLIST;
|
private readonly int _navMeshDrawFlags = RecastDebugDraw.DRAWNAVMESH_OFFMESHCONS | RecastDebugDraw.DRAWNAVMESH_CLOSEDLIST;
|
||||||
|
|
||||||
public NavMeshRenderer(RecastDebugDraw debugDraw)
|
public NavMeshRenderer(RecastDebugDraw debugDraw)
|
||||||
{
|
{
|
||||||
|
@ -123,80 +123,80 @@ public class NavMeshRenderer
|
||||||
|
|
||||||
foreach (RcBuilderResult rcBuilderResult in rcBuilderResults)
|
foreach (RcBuilderResult rcBuilderResult in rcBuilderResults)
|
||||||
{
|
{
|
||||||
if (rcBuilderResult.CompactHeightfield != null && drawMode == DrawMode.DRAWMODE_COMPACT)
|
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT)
|
||||||
{
|
{
|
||||||
_debugDraw.DebugDrawCompactHeightfieldSolid(rcBuilderResult.CompactHeightfield);
|
_debugDraw.DebugDrawCompactHeightfieldSolid(rcBuilderResult.GetCompactHeightfield());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rcBuilderResult.CompactHeightfield != null && drawMode == DrawMode.DRAWMODE_COMPACT_DISTANCE)
|
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT_DISTANCE)
|
||||||
{
|
{
|
||||||
_debugDraw.DebugDrawCompactHeightfieldDistance(rcBuilderResult.CompactHeightfield);
|
_debugDraw.DebugDrawCompactHeightfieldDistance(rcBuilderResult.GetCompactHeightfield());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rcBuilderResult.CompactHeightfield != null && drawMode == DrawMode.DRAWMODE_COMPACT_REGIONS)
|
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT_REGIONS)
|
||||||
{
|
{
|
||||||
_debugDraw.DebugDrawCompactHeightfieldRegions(rcBuilderResult.CompactHeightfield);
|
_debugDraw.DebugDrawCompactHeightfieldRegions(rcBuilderResult.GetCompactHeightfield());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rcBuilderResult.SolidHeightfiled != null && drawMode == DrawMode.DRAWMODE_VOXELS)
|
if (rcBuilderResult.GetSolidHeightfield() != null && drawMode == DrawMode.DRAWMODE_VOXELS)
|
||||||
{
|
{
|
||||||
_debugDraw.Fog(true);
|
_debugDraw.Fog(true);
|
||||||
_debugDraw.DebugDrawHeightfieldSolid(rcBuilderResult.SolidHeightfiled);
|
_debugDraw.DebugDrawHeightfieldSolid(rcBuilderResult.GetSolidHeightfield());
|
||||||
_debugDraw.Fog(false);
|
_debugDraw.Fog(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rcBuilderResult.SolidHeightfiled != null && drawMode == DrawMode.DRAWMODE_VOXELS_WALKABLE)
|
if (rcBuilderResult.GetSolidHeightfield() != null && drawMode == DrawMode.DRAWMODE_VOXELS_WALKABLE)
|
||||||
{
|
{
|
||||||
_debugDraw.Fog(true);
|
_debugDraw.Fog(true);
|
||||||
_debugDraw.DebugDrawHeightfieldWalkable(rcBuilderResult.SolidHeightfiled);
|
_debugDraw.DebugDrawHeightfieldWalkable(rcBuilderResult.GetSolidHeightfield());
|
||||||
_debugDraw.Fog(false);
|
_debugDraw.Fog(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rcBuilderResult.ContourSet != null && drawMode == DrawMode.DRAWMODE_RAW_CONTOURS)
|
if (rcBuilderResult.GetContourSet() != null && drawMode == DrawMode.DRAWMODE_RAW_CONTOURS)
|
||||||
{
|
{
|
||||||
_debugDraw.DepthMask(false);
|
_debugDraw.DepthMask(false);
|
||||||
_debugDraw.DebugDrawRawContours(rcBuilderResult.ContourSet, 1f);
|
_debugDraw.DebugDrawRawContours(rcBuilderResult.GetContourSet(), 1f);
|
||||||
_debugDraw.DepthMask(true);
|
_debugDraw.DepthMask(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rcBuilderResult.ContourSet != null && drawMode == DrawMode.DRAWMODE_BOTH_CONTOURS)
|
if (rcBuilderResult.GetContourSet() != null && drawMode == DrawMode.DRAWMODE_BOTH_CONTOURS)
|
||||||
{
|
{
|
||||||
_debugDraw.DepthMask(false);
|
_debugDraw.DepthMask(false);
|
||||||
_debugDraw.DebugDrawRawContours(rcBuilderResult.ContourSet, 0.5f);
|
_debugDraw.DebugDrawRawContours(rcBuilderResult.GetContourSet(), 0.5f);
|
||||||
_debugDraw.DebugDrawContours(rcBuilderResult.ContourSet);
|
_debugDraw.DebugDrawContours(rcBuilderResult.GetContourSet());
|
||||||
_debugDraw.DepthMask(true);
|
_debugDraw.DepthMask(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rcBuilderResult.ContourSet != null && drawMode == DrawMode.DRAWMODE_CONTOURS)
|
if (rcBuilderResult.GetContourSet() != null && drawMode == DrawMode.DRAWMODE_CONTOURS)
|
||||||
{
|
{
|
||||||
_debugDraw.DepthMask(false);
|
_debugDraw.DepthMask(false);
|
||||||
_debugDraw.DebugDrawContours(rcBuilderResult.ContourSet);
|
_debugDraw.DebugDrawContours(rcBuilderResult.GetContourSet());
|
||||||
_debugDraw.DepthMask(true);
|
_debugDraw.DepthMask(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rcBuilderResult.CompactHeightfield != null && drawMode == DrawMode.DRAWMODE_REGION_CONNECTIONS)
|
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_REGION_CONNECTIONS)
|
||||||
{
|
{
|
||||||
_debugDraw.DebugDrawCompactHeightfieldRegions(rcBuilderResult.CompactHeightfield);
|
_debugDraw.DebugDrawCompactHeightfieldRegions(rcBuilderResult.GetCompactHeightfield());
|
||||||
_debugDraw.DepthMask(false);
|
_debugDraw.DepthMask(false);
|
||||||
if (rcBuilderResult.ContourSet != null)
|
if (rcBuilderResult.GetContourSet() != null)
|
||||||
{
|
{
|
||||||
_debugDraw.DebugDrawRegionConnections(rcBuilderResult.ContourSet);
|
_debugDraw.DebugDrawRegionConnections(rcBuilderResult.GetContourSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
_debugDraw.DepthMask(true);
|
_debugDraw.DepthMask(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rcBuilderResult.Mesh != null && drawMode == DrawMode.DRAWMODE_POLYMESH)
|
if (rcBuilderResult.GetMesh() != null && drawMode == DrawMode.DRAWMODE_POLYMESH)
|
||||||
{
|
{
|
||||||
_debugDraw.DepthMask(false);
|
_debugDraw.DepthMask(false);
|
||||||
_debugDraw.DebugDrawPolyMesh(rcBuilderResult.Mesh);
|
_debugDraw.DebugDrawPolyMesh(rcBuilderResult.GetMesh());
|
||||||
_debugDraw.DepthMask(true);
|
_debugDraw.DepthMask(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rcBuilderResult.MeshDetail != null && drawMode == DrawMode.DRAWMODE_POLYMESH_DETAIL)
|
if (rcBuilderResult.GetMeshDetail() != null && drawMode == DrawMode.DRAWMODE_POLYMESH_DETAIL)
|
||||||
{
|
{
|
||||||
_debugDraw.DepthMask(false);
|
_debugDraw.DepthMask(false);
|
||||||
_debugDraw.DebugDrawPolyMeshDetail(rcBuilderResult.MeshDetail);
|
_debugDraw.DebugDrawPolyMeshDetail(rcBuilderResult.GetMeshDetail());
|
||||||
_debugDraw.DepthMask(true);
|
_debugDraw.DepthMask(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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -19,6 +19,7 @@ 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;
|
||||||
|
@ -26,13 +27,11 @@ 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 const int DU_DRAWNAVMESH_OFFMESHCONS = 0x01;
|
public static readonly int DRAWNAVMESH_OFFMESHCONS = 0x01;
|
||||||
public const int DU_DRAWNAVMESH_CLOSEDLIST = 0x02;
|
public static readonly int DRAWNAVMESH_CLOSEDLIST = 0x02;
|
||||||
public const int DU_DRAWNAVMESH_COLOR_TILES = 0x04;
|
public static readonly int DRAWNAVMESH_COLOR_TILES = 0x04;
|
||||||
|
|
||||||
public RecastDebugDraw(GL gl) : base(gl)
|
public RecastDebugDraw(GL gl) : base(gl)
|
||||||
{
|
{
|
||||||
|
@ -102,7 +101,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 & DU_DRAWNAVMESH_CLOSEDLIST) != 0 ? query : null;
|
DtNavMeshQuery q = (flags & 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);
|
||||||
|
@ -117,7 +116,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
{
|
{
|
||||||
long @base = mesh.GetPolyRefBase(tile);
|
long @base = mesh.GetPolyRefBase(tile);
|
||||||
|
|
||||||
int tileNum = DecodePolyIdTile(@base);
|
int tileNum = DtNavMesh.DecodePolyIdTile(@base);
|
||||||
int tileColor = DuIntToCol(tileNum, 128);
|
int tileColor = DuIntToCol(tileNum, 128);
|
||||||
DepthMask(false);
|
DepthMask(false);
|
||||||
Begin(DebugDrawPrimitives.TRIS);
|
Begin(DebugDrawPrimitives.TRIS);
|
||||||
|
@ -136,7 +135,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((flags & DU_DRAWNAVMESH_COLOR_TILES) != 0)
|
if ((flags & DRAWNAVMESH_COLOR_TILES) != 0)
|
||||||
{
|
{
|
||||||
col = tileColor;
|
col = tileColor;
|
||||||
}
|
}
|
||||||
|
@ -164,7 +163,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 & DU_DRAWNAVMESH_OFFMESHCONS) != 0)
|
if ((flags & 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)
|
||||||
|
@ -199,7 +198,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 = p.firstLink; k != DT_NULL_LINK; k = tile.links[k].next)
|
for (int k = tile.polyLinks[p.index]; k != DtNavMesh.DT_NULL_LINK; k = tile.links[k].next)
|
||||||
{
|
{
|
||||||
if (tile.links[k].edge == 0)
|
if (tile.links[k].edge == 0)
|
||||||
{
|
{
|
||||||
|
@ -300,7 +299,6 @@ 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];
|
||||||
|
@ -320,10 +318,10 @@ public class RecastDebugDraw : DebugDraw
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((p.neis[j] & DT_EXT_LINK) != 0)
|
if ((p.neis[j] & DtNavMesh.DT_EXT_LINK) != 0)
|
||||||
{
|
{
|
||||||
bool con = false;
|
bool con = false;
|
||||||
for (int k = p.firstLink; k != DT_NULL_LINK; k = tile.links[k].next)
|
for (int k = tile.polyLinks[p.index]; k != DtNavMesh.DT_NULL_LINK; k = tile.links[k].next)
|
||||||
{
|
{
|
||||||
if (tile.links[k].edge == j)
|
if (tile.links[k].edge == j)
|
||||||
{
|
{
|
||||||
|
@ -372,14 +370,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], tile.data.verts[p.verts[v] * 3 + 1],
|
||||||
tile.data.verts[p.verts[v] * 3 + 1],
|
|
||||||
tile.data.verts[p.verts[v] * 3 + 2]
|
tile.data.verts[p.verts[v] * 3 + 2]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -395,7 +393,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 ((GetDetailTriEdgeFlags(tile.data.detailTris[t + 3], n) & DtDetailTriEdgeFlags.DT_DETAIL_EDGE_BOUNDARY) == 0)
|
if ((DtNavMesh.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)
|
||||||
|
@ -465,13 +463,9 @@ public class RecastDebugDraw : DebugDraw
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
AppendBoxWire(
|
AppendBoxWire(tile.data.header.bmin.X + n.bmin[0] * cs, tile.data.header.bmin.Y + n.bmin[1] * cs,
|
||||||
tile.data.header.bmin.X + n.bmin.X * cs,
|
tile.data.header.bmin.Z + n.bmin[2] * cs, tile.data.header.bmin.X + n.bmax[0] * cs,
|
||||||
tile.data.header.bmin.Y + n.bmin.Y * cs,
|
tile.data.header.bmin.Y + n.bmax[1] * cs, tile.data.header.bmin.Z + n.bmax[2] * 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,7 +497,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
{
|
{
|
||||||
color = DuRGBA(0, 192, 255, 64);
|
color = DuRGBA(0, 192, 255, 64);
|
||||||
}
|
}
|
||||||
else if (area == RcRecast.RC_NULL_AREA)
|
else if (area == RcConstants.RC_NULL_AREA)
|
||||||
{
|
{
|
||||||
color = DuRGBA(0, 0, 0, 64);
|
color = DuRGBA(0, 0, 0, 64);
|
||||||
}
|
}
|
||||||
|
@ -675,7 +669,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 & RcRecast.RC_BORDER_VERTEX) != 0)
|
if ((v3 & RcConstants.RC_BORDER_VERTEX) != 0)
|
||||||
{
|
{
|
||||||
colv = DuRGBA(255, 255, 255, a);
|
colv = DuRGBA(255, 255, 255, a);
|
||||||
off = ch * 2;
|
off = ch * 2;
|
||||||
|
@ -722,7 +716,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 & RcRecast.RC_AREA_BORDER) != 0 ? bcolor : color;
|
int col = (va3 & RcConstants.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;
|
||||||
|
@ -753,7 +747,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 & RcRecast.RC_BORDER_VERTEX) != 0)
|
if ((v3 & RcConstants.RC_BORDER_VERTEX) != 0)
|
||||||
{
|
{
|
||||||
colv = DuRGBA(255, 255, 255, a);
|
colv = DuRGBA(255, 255, 255, a);
|
||||||
off = ch * 2;
|
off = ch * 2;
|
||||||
|
@ -833,7 +827,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
{
|
{
|
||||||
fcol[0] = DuRGBA(64, 128, 160, 255);
|
fcol[0] = DuRGBA(64, 128, 160, 255);
|
||||||
}
|
}
|
||||||
else if (s.area == RcRecast.RC_NULL_AREA)
|
else if (s.area == RcConstants.RC_NULL_AREA)
|
||||||
{
|
{
|
||||||
fcol[0] = DuRGBA(64, 64, 64, 255);
|
fcol[0] = DuRGBA(64, 64, 64, 255);
|
||||||
}
|
}
|
||||||
|
@ -955,7 +949,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
{
|
{
|
||||||
color = DuRGBA(0, 192, 255, 64);
|
color = DuRGBA(0, 192, 255, 64);
|
||||||
}
|
}
|
||||||
else if (area == RcRecast.RC_NULL_AREA)
|
else if (area == RcConstants.RC_NULL_AREA)
|
||||||
{
|
{
|
||||||
color = DuRGBA(0, 0, 0, 64);
|
color = DuRGBA(0, 0, 0, 64);
|
||||||
}
|
}
|
||||||
|
@ -967,7 +961,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] == RcRecast.RC_MESH_NULL_IDX)
|
if (mesh.polys[p + j] == RcConstants.RC_MESH_NULL_IDX)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -998,7 +992,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] == RcRecast.RC_MESH_NULL_IDX)
|
if (mesh.polys[p + j] == RcConstants.RC_MESH_NULL_IDX)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1008,7 +1002,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nj = (j + 1 >= nvp || mesh.polys[p + j + 1] == RcRecast.RC_MESH_NULL_IDX) ? 0 : j + 1;
|
int nj = (j + 1 >= nvp || mesh.polys[p + j + 1] == RcConstants.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)
|
||||||
|
@ -1032,7 +1026,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] == RcRecast.RC_MESH_NULL_IDX)
|
if (mesh.polys[p + j] == RcConstants.RC_MESH_NULL_IDX)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1042,7 +1036,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nj = (j + 1 >= nvp || mesh.polys[p + j + 1] == RcRecast.RC_MESH_NULL_IDX) ? 0 : j + 1;
|
int nj = (j + 1 >= nvp || mesh.polys[p + j + 1] == RcConstants.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;
|
||||||
|
@ -1333,7 +1327,7 @@ public class RecastDebugDraw : DebugDraw
|
||||||
|
|
||||||
for (int side = 0; side < 8; ++side)
|
for (int side = 0; side < 8; ++side)
|
||||||
{
|
{
|
||||||
int m = DT_EXT_LINK | (short)side;
|
int m = DtNavMesh.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,8 +10,6 @@ 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();
|
||||||
|
@ -24,6 +22,7 @@ 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -25,8 +25,6 @@ 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;
|
||||||
|
@ -320,7 +318,7 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
|
|
||||||
if (null != mesh)
|
if (null != mesh)
|
||||||
{
|
{
|
||||||
_sample.Update(_sample.GetInputGeom(), _sample.GetRecastConfig(), ImmutableArray<RcBuilderResult>.Empty, mesh);
|
_sample.Update(_sample.GetInputGeom(), ImmutableArray<RcBuilderResult>.Empty, mesh);
|
||||||
_toolsetView.SetEnabled(true);
|
_toolsetView.SetEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -411,17 +409,9 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
|
|
||||||
var workingDirectory = Directory.GetCurrentDirectory();
|
var workingDirectory = Directory.GetCurrentDirectory();
|
||||||
Logger.Information($"Working directory - {workingDirectory}");
|
Logger.Information($"Working directory - {workingDirectory}");
|
||||||
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($"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($"{vendor} {rendererGl}");
|
Logger.Information($"{vendor} {rendererGl}");
|
||||||
Logger.Information($"gl version({version}) lang version({glslString})");
|
Logger.Information($"gl version({version}) lang version({glslString})");
|
||||||
}
|
}
|
||||||
|
@ -472,7 +462,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();
|
||||||
RcRecast.CalcGridSize(bmin, bmax, settings.cellSize, out var gw, out var gh);
|
RcCommons.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));
|
||||||
|
@ -547,7 +537,6 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
bool hasBound = false;
|
bool hasBound = false;
|
||||||
RcVec3f bminN = RcVec3f.Zero;
|
RcVec3f bminN = RcVec3f.Zero;
|
||||||
RcVec3f bmaxN = RcVec3f.Zero;
|
RcVec3f bmaxN = RcVec3f.Zero;
|
||||||
|
|
||||||
if (_sample.GetInputGeom() != null)
|
if (_sample.GetInputGeom() != null)
|
||||||
{
|
{
|
||||||
bminN = _sample.GetInputGeom().GetMeshBoundsMin();
|
bminN = _sample.GetInputGeom().GetMeshBoundsMin();
|
||||||
|
@ -563,7 +552,7 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
{
|
{
|
||||||
foreach (RcBuilderResult result in _sample.GetRecastResults())
|
foreach (RcBuilderResult result in _sample.GetRecastResults())
|
||||||
{
|
{
|
||||||
if (result.CompactHeightfield != null)
|
if (result.GetSolidHeightfield() != null)
|
||||||
{
|
{
|
||||||
if (!hasBound)
|
if (!hasBound)
|
||||||
{
|
{
|
||||||
|
@ -572,15 +561,15 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
bminN = new RcVec3f(
|
bminN = new RcVec3f(
|
||||||
Math.Min(bminN.X, result.CompactHeightfield.bmin.X),
|
Math.Min(bminN.X, result.GetSolidHeightfield().bmin.X),
|
||||||
Math.Min(bminN.Y, result.CompactHeightfield.bmin.Y),
|
Math.Min(bminN.Y, result.GetSolidHeightfield().bmin.Y),
|
||||||
Math.Min(bminN.Z, result.CompactHeightfield.bmin.Z)
|
Math.Min(bminN.Z, result.GetSolidHeightfield().bmin.Z)
|
||||||
);
|
);
|
||||||
|
|
||||||
bmaxN = new RcVec3f(
|
bmaxN = new RcVec3f(
|
||||||
Math.Max(bmaxN.X, result.CompactHeightfield.bmax.X),
|
Math.Max(bmaxN.X, result.GetSolidHeightfield().bmax.X),
|
||||||
Math.Max(bmaxN.Y, result.CompactHeightfield.bmax.Y),
|
Math.Max(bmaxN.Y, result.GetSolidHeightfield().bmax.Y),
|
||||||
Math.Max(bmaxN.Z, result.CompactHeightfield.bmax.Z)
|
Math.Max(bmaxN.Z, result.GetSolidHeightfield().bmax.Z)
|
||||||
);
|
);
|
||||||
|
|
||||||
hasBound = true;
|
hasBound = true;
|
||||||
|
@ -588,15 +577,12 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset camera and fog to match the mesh bounds.
|
|
||||||
if (hasBound)
|
if (hasBound)
|
||||||
{
|
{
|
||||||
RcVec3f bmin = bminN;
|
RcVec3f bmin = bminN;
|
||||||
RcVec3f bmax = bmaxN;
|
RcVec3f bmax = bmaxN;
|
||||||
|
|
||||||
camr = (float)(Math.Sqrt(RcMath.Sqr(bmax.X - bmin.X) +
|
camr = (float)(Math.Sqrt(RcMath.Sqr(bmax.X - bmin.X) + RcMath.Sqr(bmax.Y - bmin.Y) + RcMath.Sqr(bmax.Z - bmin.Z)) / 2);
|
||||||
RcMath.Sqr(bmax.Y - bmin.Y) +
|
|
||||||
RcMath.Sqr(bmax.Z - bmin.Z)) / 2);
|
|
||||||
cameraPos.X = (bmax.X + bmin.X) / 2 + camr;
|
cameraPos.X = (bmax.X + bmin.X) / 2 + camr;
|
||||||
cameraPos.Y = (bmax.Y + bmin.Y) / 2 + camr;
|
cameraPos.Y = (bmax.Y + bmin.Y) / 2 + camr;
|
||||||
cameraPos.Z = (bmax.Z + bmin.Z) / 2 + camr;
|
cameraPos.Z = (bmax.Z + bmin.Z) / 2 + camr;
|
||||||
|
@ -684,7 +670,7 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
{
|
{
|
||||||
var geom = LoadInputMesh(args.FilePath);
|
var geom = LoadInputMesh(args.FilePath);
|
||||||
|
|
||||||
_sample.Update(geom, null, ImmutableArray<RcBuilderResult>.Empty, null);
|
_sample.Update(geom, ImmutableArray<RcBuilderResult>.Empty, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnNavMeshBuildBegan(NavMeshBuildBeganEvent args)
|
private void OnNavMeshBuildBegan(NavMeshBuildBeganEvent args)
|
||||||
|
@ -702,15 +688,14 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
|
|
||||||
NavMeshBuildResult buildResult;
|
NavMeshBuildResult buildResult;
|
||||||
|
|
||||||
var geom = _sample.GetInputGeom();
|
|
||||||
var settings = _sample.GetSettings();
|
var settings = _sample.GetSettings();
|
||||||
if (settings.tiled)
|
if (settings.tiled)
|
||||||
{
|
{
|
||||||
buildResult = tileNavMeshBuilder.Build(geom, settings);
|
buildResult = tileNavMeshBuilder.Build(_sample.GetInputGeom(), settings);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buildResult = soloNavMeshBuilder.Build(geom, settings);
|
buildResult = soloNavMeshBuilder.Build(_sample.GetInputGeom(), settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!buildResult.Success)
|
if (!buildResult.Success)
|
||||||
|
@ -719,7 +704,7 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_sample.Update(_sample.GetInputGeom(), buildResult.Cfg, buildResult.RecastBuilderResults, buildResult.NavMesh);
|
_sample.Update(_sample.GetInputGeom(), 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());
|
||||||
|
@ -728,7 +713,7 @@ public class RecastDemo : IRecastDemoChannel
|
||||||
Logger.Information($"build times");
|
Logger.Information($"build times");
|
||||||
Logger.Information($"-----------------------------------------");
|
Logger.Information($"-----------------------------------------");
|
||||||
var telemetries = buildResult.RecastBuilderResults
|
var telemetries = buildResult.RecastBuilderResults
|
||||||
.Select(x => x.Context)
|
.Select(x => x.GetTelemetry())
|
||||||
.SelectMany(x => x.ToList())
|
.SelectMany(x => x.ToList())
|
||||||
.GroupBy(x => x.Key)
|
.GroupBy(x => x.Key)
|
||||||
.ToImmutableSortedDictionary(x => x.Key, x => x.Sum(y => y.Millis));
|
.ToImmutableSortedDictionary(x => x.Key, x => x.Sum(y => y.Millis));
|
||||||
|
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -18,9 +18,12 @@ 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;
|
||||||
|
@ -95,11 +98,6 @@ 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();
|
||||||
|
@ -120,11 +118,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():0.00} ms");
|
ImGui.Text($"Sampling Time: {_tool.GetCrowdUpdateSamplingTime()} ms");
|
||||||
ImGui.Text($"Current Update Time: {_tool.GetCrowdUpdateTime():0.00} ms");
|
ImGui.Text($"Current Update Time: {_tool.GetCrowdUpdateTime()} ms");
|
||||||
ImGui.Text($"Avg Update Time: {_tool.GetCrowdUpdateAvgTime():0.00} ms");
|
ImGui.Text($"Avg Update Time: {_tool.GetCrowdUpdateAvgTime()} ms");
|
||||||
ImGui.Text($"Max Update Time: {_tool.GetCrowdUpdateMaxTime():0.00} ms");
|
ImGui.Text($"Max Update Time: {_tool.GetCrowdUpdateMaxTime()} ms");
|
||||||
ImGui.Text($"Min Update Time: {_tool.GetCrowdUpdateMinTime():0.00} ms");
|
ImGui.Text($"Min Update Time: {_tool.GetCrowdUpdateMinTime()} ms");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +132,7 @@ public class CrowdAgentProfilingSampleTool : ISampleTool
|
||||||
dd.DepthMask(false);
|
dd.DepthMask(false);
|
||||||
|
|
||||||
var crowd = _tool.GetCrowd();
|
var crowd = _tool.GetCrowd();
|
||||||
if (crowd != null && _tool.GetToolConfig().showAgents)
|
if (crowd != null)
|
||||||
{
|
{
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -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 = RcVec.Create(trail.trail, v);
|
prev = RcVecUtils.Create(trail.trail, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
dd.End();
|
dd.End();
|
||||||
|
@ -251,10 +251,10 @@ public class CrowdSampleTool : ISampleTool
|
||||||
|
|
||||||
if (_showCorners)
|
if (_showCorners)
|
||||||
{
|
{
|
||||||
if (0 < ag.ncorners)
|
if (0 < ag.corners.Count)
|
||||||
{
|
{
|
||||||
dd.Begin(LINES, 2.0f);
|
dd.Begin(LINES, 2.0f);
|
||||||
for (int j = 0; j < ag.ncorners; ++j)
|
for (int j = 0; j < ag.corners.Count; ++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.ncorners - 1].flags
|
if ((ag.corners[ag.corners.Count - 1].flags
|
||||||
& DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
& DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
||||||
{
|
{
|
||||||
RcVec3f v = ag.corners[ag.ncorners - 1].pos;
|
RcVec3f v = ag.corners[ag.corners.Count - 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.nneis; ++j)
|
for (int j = 0; j < ag.neis.Count; ++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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -25,7 +25,6 @@ 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;
|
||||||
|
@ -92,7 +91,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
var bridgeGeom = DemoInputGeomProvider.LoadFile("bridge.obj");
|
var bridgeGeom = DemoInputGeomProvider.LoadFile("bridge.obj");
|
||||||
var houseGeom = DemoInputGeomProvider.LoadFile("house.obj");
|
var houseGeom = DemoInputGeomProvider.LoadFile("house.obj");
|
||||||
var convexGeom = DemoInputGeomProvider.LoadFile("convex.obj");
|
var convexGeom = DemoInputGeomProvider.LoadFile("convex.obj");
|
||||||
_tool = new(new RcRand(Random.Shared), bridgeGeom, houseGeom, convexGeom);
|
_tool = new(Random.Shared, bridgeGeom, houseGeom, convexGeom);
|
||||||
executor = Task.Factory;
|
executor = Task.Factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,17 +116,8 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
|
|
||||||
if (mode == RcDynamicUpdateToolMode.BUILD)
|
if (mode == RcDynamicUpdateToolMode.BUILD)
|
||||||
{
|
{
|
||||||
const string loadVoxelPopupStrId = "Load Voxels Popup";
|
var 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);
|
||||||
|
@ -145,7 +135,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
ImGui.EndPopup();
|
ImGui.EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
const string saveVoxelPopupStrId = "Save Voxels Popup";
|
var saveVoxelPopupStrId = "Save Voxels Popup";
|
||||||
bool isSaveVoxelPopup = true;
|
bool isSaveVoxelPopup = true;
|
||||||
|
|
||||||
var dynaMesh = _tool.GetDynamicNavMesh();
|
var dynaMesh = _tool.GetDynamicNavMesh();
|
||||||
|
@ -154,7 +144,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.OpenPopup(saveVoxelPopupStrId);
|
ImGui.BeginPopup(saveVoxelPopupStrId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui.BeginPopupModal(saveVoxelPopupStrId, ref isSaveVoxelPopup, ImGuiWindowFlags.NoTitleBar))
|
if (ImGui.BeginPopupModal(saveVoxelPopupStrId, ref isSaveVoxelPopup, ImGuiWindowFlags.NoTitleBar))
|
||||||
|
@ -162,7 +152,9 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,12 +406,12 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
long t = RcFrequency.Ticks;
|
long t = RcFrequency.Ticks;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bool updated = _tool.Update(executor);
|
bool updated = _tool.UpdateDynaMesh(executor);
|
||||||
if (updated)
|
if (updated)
|
||||||
{
|
{
|
||||||
buildTime = (RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond;
|
buildTime = (RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond;
|
||||||
var dynaMesh = _tool.GetDynamicNavMesh();
|
var dynaMesh = _tool.GetDynamicNavMesh();
|
||||||
_sample.Update(null, null, dynaMesh.RecastResults(), dynaMesh.NavMesh());
|
_sample.Update(null, dynaMesh.RecastResults(), dynaMesh.NavMesh());
|
||||||
_sample.SetChanged(false);
|
_sample.SetChanged(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -429,15 +421,6 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -467,7 +450,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
long t = RcFrequency.Ticks;
|
long t = RcFrequency.Ticks;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var _ = dynaMesh.Build(executor);
|
var _ = dynaMesh.Build(executor).Result;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -475,7 +458,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTime = (RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond;
|
buildTime = (RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond;
|
||||||
_sample.Update(null, null, dynaMesh.RecastResults(), dynaMesh.NavMesh());
|
_sample.Update(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,11 +36,16 @@ public static class GizmoRenderer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetColorByNormal(RcVec3f v0, RcVec3f v1, RcVec3f v2)
|
public static int GetColorByNormal(float[] vertices, int v0, int v1, int v2)
|
||||||
{
|
{
|
||||||
|
RcVec3f e0 = new RcVec3f();
|
||||||
|
RcVec3f e1 = new RcVec3f();
|
||||||
RcVec3f normal = new RcVec3f();
|
RcVec3f normal = new RcVec3f();
|
||||||
RcVec3f e0 = v1 - v0;
|
for (int j = 0; j < 3; ++j)
|
||||||
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;
|
||||||
|
@ -60,7 +65,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);
|
||||||
Span<float> vertices = stackalloc float[8 * 3];
|
float[] vertices = new 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;
|
||||||
|
@ -155,13 +160,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)
|
||||||
{
|
{
|
||||||
RcVec3f v0 = RcVec.Create(trimesh.vertices, 3 * trimesh.triangles[i]);
|
int v0 = 3 * trimesh.triangles[i];
|
||||||
RcVec3f v1 = RcVec.Create(trimesh.vertices, 3 * trimesh.triangles[i + 1]);
|
int v1 = 3 * trimesh.triangles[i + 1];
|
||||||
RcVec3f v2 = RcVec.Create(trimesh.vertices, 3 * trimesh.triangles[i + 2]);
|
int v2 = 3 * trimesh.triangles[i + 2];
|
||||||
int col = GetColorByNormal(v0, v1, v2);
|
int col = GetColorByNormal(trimesh.vertices, v0, v1, v2);
|
||||||
debugDraw.Vertex(v0.X, v0.Y, v0.Z, col);
|
debugDraw.Vertex(trimesh.vertices[v0], trimesh.vertices[v0 + 1], trimesh.vertices[v0 + 2], col);
|
||||||
debugDraw.Vertex(v1.X, v1.Y, v1.Z, col);
|
debugDraw.Vertex(trimesh.vertices[v1], trimesh.vertices[v1 + 1], trimesh.vertices[v1 + 2], col);
|
||||||
debugDraw.Vertex(v2.X, v2.Y, v2.Z, col);
|
debugDraw.Vertex(trimesh.vertices[v2], trimesh.vertices[v2 + 1], trimesh.vertices[v2 + 2], 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -16,7 +16,6 @@ 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.Linq;
|
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Detour.Extras.Jumplink;
|
using DotRecast.Detour.Extras.Jumplink;
|
||||||
using DotRecast.Recast.Demo.Draw;
|
using DotRecast.Recast.Demo.Draw;
|
||||||
|
@ -97,25 +96,13 @@ public class JumpLinkBuilderSampleTool : ISampleTool
|
||||||
|
|
||||||
if (build || _cfg.buildOffMeshConnections)
|
if (build || _cfg.buildOffMeshConnections)
|
||||||
{
|
{
|
||||||
do
|
if (0 < _sample.GetRecastResults().Count)
|
||||||
{
|
{
|
||||||
if (0 >= _sample.GetRecastResults().Count)
|
|
||||||
{
|
|
||||||
Logger.Error("build navmesh");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_sample.GetRecastResults().Any(x => null == x.SolidHeightfiled))
|
|
||||||
{
|
|
||||||
Logger.Error("Tick 'Keep Itermediate Results' option");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var geom = _sample.GetInputGeom();
|
var geom = _sample.GetInputGeom();
|
||||||
var settings = _sample.GetSettings();
|
var settings = _sample.GetSettings();
|
||||||
|
|
||||||
_tool.Build(geom, settings, _sample.GetRecastResults(), _cfg);
|
_tool.Build(geom, settings, _sample.GetRecastResults(), _cfg);
|
||||||
} while (false);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
|
@ -417,7 +404,7 @@ public class JumpLinkBuilderSampleTool : ISampleTool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void DrawTrajectory(RecastDebugDraw dd, JumpLink link, RcVec3f pa, RcVec3f pb, ITrajectory tra, int cola)
|
private void DrawTrajectory(RecastDebugDraw dd, JumpLink link, RcVec3f pa, RcVec3f pb, Trajectory 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.Cfg, buildResult.RecastBuilderResults, buildResult.NavMesh);
|
_sample.Update(_sample.GetInputGeom(), 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -57,8 +57,7 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
private bool m_hitResult;
|
private bool m_hitResult;
|
||||||
|
|
||||||
private float m_distanceToWall;
|
private float m_distanceToWall;
|
||||||
private DtStraightPath[] m_straightPath;
|
private List<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;
|
||||||
|
@ -78,8 +77,6 @@ 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()
|
||||||
|
@ -140,22 +137,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);
|
||||||
|
@ -287,7 +284,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_straightPathCount - 1; ++i)
|
for (int i = 0; i < m_straightPath.Count - 1; ++i)
|
||||||
{
|
{
|
||||||
DtStraightPath straightPathItem = m_straightPath[i];
|
DtStraightPath straightPathItem = m_straightPath[i];
|
||||||
DtStraightPath straightPathItem2 = m_straightPath[i + 1];
|
DtStraightPath straightPathItem2 = m_straightPath[i + 1];
|
||||||
|
@ -307,7 +304,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_straightPathCount; ++i)
|
for (int i = 0; i < m_straightPath.Count; ++i)
|
||||||
{
|
{
|
||||||
DtStraightPath straightPathItem = m_straightPath[i];
|
DtStraightPath straightPathItem = m_straightPath[i];
|
||||||
int col;
|
int col;
|
||||||
|
@ -352,7 +349,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_straightPathCount - 1; ++i)
|
for (int i = 0; i < m_straightPath.Count - 1; ++i)
|
||||||
{
|
{
|
||||||
DtStraightPath straightPathItem = m_straightPath[i];
|
DtStraightPath straightPathItem = m_straightPath[i];
|
||||||
DtStraightPath straightPathItem2 = m_straightPath[i + 1];
|
DtStraightPath straightPathItem2 = m_straightPath[i + 1];
|
||||||
|
@ -362,7 +359,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_straightPathCount; ++i)
|
for (int i = 0; i < m_straightPath.Count; ++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);
|
||||||
|
@ -472,9 +469,8 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
{
|
{
|
||||||
if (m_polys != null)
|
if (m_polys != null)
|
||||||
{
|
{
|
||||||
const int MAX_SEGS = DtDetour.DT_VERTS_PER_POLYGON * 4;
|
var segmentVerts = new List<RcSegmentVert>();
|
||||||
Span<RcSegmentVert> segs = stackalloc RcSegmentVert[MAX_SEGS];
|
var segmentRefs = new List<long>();
|
||||||
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++)
|
||||||
{
|
{
|
||||||
|
@ -492,20 +488,18 @@ 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], m_filter, segs, refs, ref nsegs, MAX_SEGS);
|
.GetPolyWallSegments(m_polys[i], false, m_filter, ref segmentVerts, ref segmentRefs);
|
||||||
|
|
||||||
if (result.Succeeded())
|
if (result.Succeeded())
|
||||||
{
|
{
|
||||||
dd.Begin(LINES, 2.0f);
|
dd.Begin(LINES, 2.0f);
|
||||||
for (int j = 0; j < nsegs; ++j)
|
for (int j = 0; j < segmentVerts.Count; ++j)
|
||||||
{
|
{
|
||||||
ref RcSegmentVert s = ref segs[j];
|
RcSegmentVert s = segmentVerts[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))
|
||||||
|
@ -514,13 +508,12 @@ public class TestNavmeshSampleTool : ISampleTool
|
||||||
}
|
}
|
||||||
|
|
||||||
RcVec3f delta = RcVec3f.Subtract(s3, s.vmin);
|
RcVec3f delta = RcVec3f.Subtract(s3, s.vmin);
|
||||||
RcVec3f p0 = RcVec.Mad(s.vmin, delta, 0.5f);
|
RcVec3f p0 = RcVecUtils.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 = RcVec.Mad(p0, norm, agentRadius * 0.5f);
|
RcVec3f p1 = RcVecUtils.Mad(p0, norm, agentRadius * 0.5f);
|
||||||
|
|
||||||
// Skip backfacing segments.
|
// Skip backfacing segments.
|
||||||
if (refs[j] != 0)
|
if (segmentRefs[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);
|
||||||
|
@ -668,23 +661,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, m_polys?.Count ?? 0, ref m_smoothPath);
|
ref m_polys, 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, m_straightPath, out m_straightPathCount, MAX_POLYS, _straightPathOption);
|
ref m_polys, ref m_straightPath, _straightPathOption);
|
||||||
}
|
}
|
||||||
else if (_mode == RcTestNavmeshToolMode.PATHFIND_SLICED)
|
else if (_mode == RcTestNavmeshToolMode.PATHFIND_SLICED)
|
||||||
{
|
{
|
||||||
m_polys?.Clear();
|
m_polys?.Clear();
|
||||||
m_straightPathCount = 0;
|
m_straightPath?.Clear();
|
||||||
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, m_straightPath, out m_straightPathCount, MAX_POLYS, ref m_hitPos, ref m_hitNormal, ref m_hitResult);
|
ref m_polys, ref m_straightPath, ref m_hitPos, ref m_hitNormal, ref m_hitResult);
|
||||||
}
|
}
|
||||||
else if (_mode == RcTestNavmeshToolMode.DISTANCE_TO_WALL)
|
else if (_mode == RcTestNavmeshToolMode.DISTANCE_TO_WALL)
|
||||||
{
|
{
|
||||||
|
@ -719,7 +712,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, m_straightPath, out m_straightPathCount, MAX_POLYS);
|
m_pathFindStatus = _tool.UpdateSlicedFindPath(navQuery, 1, m_endRef, m_spos, m_epos, ref m_polys, ref m_straightPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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.BeginChild(1, new Vector2(1024, 400)))
|
if (ImGui.BeginChildFrame(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.EndChild();
|
ImGui.EndChildFrame();
|
||||||
|
|
||||||
|
|
||||||
if (ImGui.Button("Cancel"))
|
if (ImGui.Button("Cancel"))
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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, ImGuiChildFlags.None, ImGuiWindowFlags.HorizontalScrollbar))
|
if (ImGui.BeginChild("scrolling", Vector2.Zero, false, 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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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
|
||||||
|
@ -167,10 +166,6 @@ public class RcSettingsView : IRcView
|
||||||
ImGui.SliderFloat("Max Sample Error", ref settings.detailSampleMaxError, 0f, 16f, "%.1f");
|
ImGui.SliderFloat("Max Sample Error", ref settings.detailSampleMaxError, 0f, 16f, "%.1f");
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
|
|
||||||
ImGui.Checkbox("Keep Itermediate Results", ref settings.keepInterResults);
|
|
||||||
ImGui.Checkbox("Build All Tiles", ref settings.buildAll);
|
|
||||||
ImGui.NewLine();
|
|
||||||
|
|
||||||
ImGui.Text("Tiling");
|
ImGui.Text("Tiling");
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
ImGui.Checkbox("Enable", ref settings.tiled);
|
ImGui.Checkbox("Enable", ref settings.tiled);
|
||||||
|
@ -233,12 +228,6 @@ public class RcSettingsView : IRcView
|
||||||
DrawMode.Values.ForEach(dm => { ImGui.RadioButton(dm.Text, ref drawMode, dm.Idx); });
|
DrawMode.Values.ForEach(dm => { ImGui.RadioButton(dm.Text, ref drawMode, dm.Idx); });
|
||||||
ImGui.NewLine();
|
ImGui.NewLine();
|
||||||
|
|
||||||
ImGui.Separator();
|
|
||||||
ImGui.Text("Tick 'Keep Itermediate Results'");
|
|
||||||
ImGui.Text("rebuild some tiles to see");
|
|
||||||
ImGui.Text("more debug mode options.");
|
|
||||||
ImGui.NewLine();
|
|
||||||
|
|
||||||
ImGui.End();
|
ImGui.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) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Demo.UI.ViewModels;
|
namespace DotRecast.Recast.Demo.UI.ViewModels;
|
||||||
|
|
||||||
public class LogMessageItem
|
public class LogMessageItem
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,8 +10,8 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb,
|
float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb,
|
||||||
RcBuilderResult rcResult)
|
RcBuilderResult rcResult)
|
||||||
{
|
{
|
||||||
RcPolyMesh pmesh = rcResult.Mesh;
|
RcPolyMesh pmesh = rcResult.GetMesh();
|
||||||
RcPolyMeshDetail dmesh = rcResult.MeshDetail;
|
RcPolyMeshDetail dmesh = rcResult.GetMeshDetail();
|
||||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||||
for (int i = 0; i < pmesh.npolys; ++i)
|
for (int i = 0; i < pmesh.npolys; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DotRecast.Detour;
|
using DotRecast.Detour;
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ 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;
|
||||||
|
|
||||||
|
@ -18,22 +17,11 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
NavMesh = null;
|
NavMesh = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for solo
|
public NavMeshBuildResult(IList<RcBuilderResult> recastBuilderResults, DtNavMesh navMesh)
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -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 const int SAMPLE_POLYFLAGS_WALK = 0x01; // Ability to walk (ground, grass, road)
|
public static readonly int SAMPLE_POLYFLAGS_WALK = 0x01; // Ability to walk (ground, grass, road)
|
||||||
public const int SAMPLE_POLYFLAGS_SWIM = 0x02; // Ability to swim (water).
|
public static readonly int SAMPLE_POLYFLAGS_SWIM = 0x02; // Ability to swim (water).
|
||||||
public const int SAMPLE_POLYFLAGS_DOOR = 0x04; // Ability to move through doors.
|
public static readonly int SAMPLE_POLYFLAGS_DOOR = 0x04; // Ability to move through doors.
|
||||||
public const int SAMPLE_POLYFLAGS_JUMP = 0x08; // Ability to jump.
|
public static readonly int SAMPLE_POLYFLAGS_JUMP = 0x08; // Ability to jump.
|
||||||
public const int SAMPLE_POLYFLAGS_DISABLED = 0x10; // Disabled polygon
|
public static readonly int SAMPLE_POLYFLAGS_DISABLED = 0x10; // Disabled polygon
|
||||||
public const int SAMPLE_POLYFLAGS_ALL = 0xffff; // All abilities.
|
public static readonly 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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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
|
||||||
|
@ -35,8 +34,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
settings.edgeMaxLen, settings.edgeMaxError,
|
settings.edgeMaxLen, settings.edgeMaxError,
|
||||||
settings.vertsPerPoly,
|
settings.vertsPerPoly,
|
||||||
settings.detailSampleDist, settings.detailSampleMaxError,
|
settings.detailSampleDist, settings.detailSampleMaxError,
|
||||||
settings.filterLowHangingObstacles, settings.filterLedgeSpans, settings.filterWalkableLowHeightSpans,
|
settings.filterLowHangingObstacles, settings.filterLedgeSpans, settings.filterWalkableLowHeightSpans);
|
||||||
settings.keepInterResults);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public NavMeshBuildResult Build(DemoInputGeomProvider geom,
|
public NavMeshBuildResult Build(DemoInputGeomProvider geom,
|
||||||
|
@ -47,8 +45,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
float edgeMaxLen, float edgeMaxError,
|
float edgeMaxLen, float edgeMaxError,
|
||||||
int vertsPerPoly,
|
int vertsPerPoly,
|
||||||
float detailSampleDist, float detailSampleMaxError,
|
float detailSampleDist, float detailSampleMaxError,
|
||||||
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans,
|
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans)
|
||||||
bool keepInterResults)
|
|
||||||
{
|
{
|
||||||
RcConfig cfg = new RcConfig(
|
RcConfig cfg = new RcConfig(
|
||||||
partitionType,
|
partitionType,
|
||||||
|
@ -61,7 +58,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
|
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true);
|
SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true);
|
||||||
|
|
||||||
RcBuilderResult rcResult = BuildRecastResult(geom, cfg, keepInterResults);
|
RcBuilderResult rcResult = BuildRecastResult(geom, cfg);
|
||||||
var meshData = BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, rcResult);
|
var meshData = BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, rcResult);
|
||||||
if (null == meshData)
|
if (null == meshData)
|
||||||
{
|
{
|
||||||
|
@ -69,26 +66,19 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
}
|
}
|
||||||
|
|
||||||
var navMesh = BuildNavMesh(meshData, vertsPerPoly);
|
var navMesh = BuildNavMesh(meshData, vertsPerPoly);
|
||||||
return new NavMeshBuildResult(cfg, RcImmutableArray.Create(rcResult), navMesh);
|
return new NavMeshBuildResult(RcImmutableArray.Create(rcResult), navMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DtNavMesh BuildNavMesh(DtMeshData meshData, int vertsPerPoly)
|
private DtNavMesh BuildNavMesh(DtMeshData meshData, int vertsPerPoly)
|
||||||
{
|
{
|
||||||
var mesh = new DtNavMesh();
|
return new DtNavMesh(meshData, vertsPerPoly, 0);
|
||||||
var status = mesh.Init(meshData, vertsPerPoly, 0);
|
|
||||||
if (status.Failed())
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mesh;
|
private RcBuilderResult BuildRecastResult(DemoInputGeomProvider geom, RcConfig cfg)
|
||||||
}
|
|
||||||
|
|
||||||
private RcBuilderResult BuildRecastResult(DemoInputGeomProvider geom, RcConfig cfg, bool keepInterResults)
|
|
||||||
{
|
{
|
||||||
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();
|
||||||
return rcBuilder.Build(geom, bcfg, keepInterResults);
|
return rcBuilder.Build(geom, bcfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtMeshData BuildMeshData(DemoInputGeomProvider geom,
|
public DtMeshData BuildMeshData(DemoInputGeomProvider geom,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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
|
||||||
|
@ -42,8 +41,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
settings.minRegionSize, settings.mergedRegionSize,
|
settings.minRegionSize, settings.mergedRegionSize,
|
||||||
settings.edgeMaxLen, settings.edgeMaxError,
|
settings.edgeMaxLen, settings.edgeMaxError,
|
||||||
settings.vertsPerPoly, settings.detailSampleDist, settings.detailSampleMaxError,
|
settings.vertsPerPoly, settings.detailSampleDist, settings.detailSampleMaxError,
|
||||||
settings.filterLowHangingObstacles, settings.filterLedgeSpans, settings.filterWalkableLowHeightSpans,
|
settings.filterLowHangingObstacles, settings.filterLedgeSpans, settings.filterWalkableLowHeightSpans);
|
||||||
settings.keepInterResults, settings.buildAll);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public NavMeshBuildResult Build(IInputGeomProvider geom,
|
public NavMeshBuildResult Build(IInputGeomProvider geom,
|
||||||
|
@ -55,10 +53,9 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
float edgeMaxLen, float edgeMaxError,
|
float edgeMaxLen, float edgeMaxError,
|
||||||
int vertsPerPoly,
|
int vertsPerPoly,
|
||||||
float detailSampleDist, float detailSampleMaxError,
|
float detailSampleDist, float detailSampleMaxError,
|
||||||
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans,
|
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans)
|
||||||
bool keepInterResults, bool buildAll)
|
|
||||||
{
|
{
|
||||||
NavMeshBuildResult result = BuildRecastResult(
|
List<RcBuilderResult> results = BuildRecastResult(
|
||||||
geom,
|
geom,
|
||||||
tileSize,
|
tileSize,
|
||||||
partitionType,
|
partitionType,
|
||||||
|
@ -68,16 +65,15 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
edgeMaxLen, edgeMaxError,
|
edgeMaxLen, edgeMaxError,
|
||||||
vertsPerPoly,
|
vertsPerPoly,
|
||||||
detailSampleDist, detailSampleMaxError,
|
detailSampleDist, detailSampleMaxError,
|
||||||
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
|
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans
|
||||||
keepInterResults, buildAll
|
|
||||||
);
|
);
|
||||||
|
|
||||||
var tileMeshData = BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, result.RecastBuilderResults);
|
var tileMeshData = BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, results);
|
||||||
var tileNavMesh = BuildNavMesh(geom, tileMeshData, cellSize, tileSize, vertsPerPoly);
|
var tileNavMesh = BuildNavMesh(geom, tileMeshData, cellSize, tileSize, vertsPerPoly);
|
||||||
return new NavMeshBuildResult(result.Cfg, result.RecastBuilderResults, tileNavMesh);
|
return new NavMeshBuildResult(results, tileNavMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NavMeshBuildResult BuildRecastResult(IInputGeomProvider geom,
|
public List<RcBuilderResult> BuildRecastResult(IInputGeomProvider geom,
|
||||||
int tileSize,
|
int tileSize,
|
||||||
RcPartition partitionType,
|
RcPartition partitionType,
|
||||||
float cellSize, float cellHeight,
|
float cellSize, float cellHeight,
|
||||||
|
@ -86,8 +82,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
float edgeMaxLen, float edgeMaxError,
|
float edgeMaxLen, float edgeMaxError,
|
||||||
int vertsPerPoly,
|
int vertsPerPoly,
|
||||||
float detailSampleDist, float detailSampleMaxError,
|
float detailSampleDist, float detailSampleMaxError,
|
||||||
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans,
|
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans)
|
||||||
bool keepInterResults, bool buildAll)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
RcConfig cfg = new RcConfig(true, tileSize, tileSize,
|
RcConfig cfg = new RcConfig(true, tileSize, tileSize,
|
||||||
|
@ -102,8 +97,7 @@ 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();
|
||||||
var results = rcBuilder.BuildTiles(geom, cfg, keepInterResults, buildAll, Environment.ProcessorCount + 1, Task.Factory);
|
return rcBuilder.BuildTiles(geom, cfg, 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)
|
||||||
|
@ -117,9 +111,8 @@ 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();
|
DtNavMesh navMesh = new DtNavMesh(navMeshParams, vertsPerPoly);
|
||||||
navMesh.Init(navMeshParams, vertsPerPoly);
|
meshData.ForEach(md => navMesh.AddTile(md, 0, 0));
|
||||||
meshData.ForEach(md => navMesh.AddTile(md, 0, 0, out _));
|
|
||||||
return navMesh;
|
return navMesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,9 +123,10 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
List<DtMeshData> meshData = new List<DtMeshData>();
|
List<DtMeshData> meshData = new List<DtMeshData>();
|
||||||
foreach (RcBuilderResult result in results)
|
foreach (RcBuilderResult result in results)
|
||||||
{
|
{
|
||||||
int x = result.TileX;
|
int x = result.tileX;
|
||||||
int z = result.TileZ;
|
int z = result.tileZ;
|
||||||
DtNavMeshCreateParams option = DemoNavMeshBuilder.GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, result);
|
DtNavMeshCreateParams option = DemoNavMeshBuilder
|
||||||
|
.GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, result);
|
||||||
|
|
||||||
option.tileX = x;
|
option.tileX = x;
|
||||||
option.tileZ = z;
|
option.tileZ = z;
|
||||||
|
@ -161,7 +155,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
|
|
||||||
private int GetTileBits(IInputGeomProvider geom, float cellSize, int tileSize)
|
private int GetTileBits(IInputGeomProvider geom, float cellSize, int tileSize)
|
||||||
{
|
{
|
||||||
RcRecast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
|
RcCommons.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);
|
||||||
|
@ -170,7 +164,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
||||||
|
|
||||||
public int[] GetTiles(DemoInputGeomProvider geom, float cellSize, int tileSize)
|
public int[] GetTiles(DemoInputGeomProvider geom, float cellSize, int tileSize)
|
||||||
{
|
{
|
||||||
RcRecast.CalcGridSize(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), cellSize, out var gw, out var gh);
|
RcCommons.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,22 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Recast.Toolset",
|
|
||||||
"rootNamespace": "DotRecast.Recast.Toolset",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Core",
|
|
||||||
"DotRecast.Recast",
|
|
||||||
"DotRecast.Detour",
|
|
||||||
"DotRecast.Detour.Crowd",
|
|
||||||
"DotRecast.Detour.Dynamic",
|
|
||||||
"DotRecast.Detour.Extras",
|
|
||||||
"DotRecast.Detour.TileCache"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": true
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
@ -46,13 +46,13 @@ namespace DotRecast.Recast.Toolset.Geom
|
||||||
if (null != _geom)
|
if (null != _geom)
|
||||||
{
|
{
|
||||||
var offMeshConnections = _geom.GetOffMeshConnections();
|
var offMeshConnections = _geom.GetOffMeshConnections();
|
||||||
option.offMeshConCount = offMeshConnections.Count;
|
|
||||||
option.offMeshConVerts = new float[option.offMeshConCount * 6];
|
option.offMeshConVerts = new float[option.offMeshConCount * 6];
|
||||||
option.offMeshConRad = new float[option.offMeshConCount];
|
option.offMeshConRad = new float[option.offMeshConCount];
|
||||||
option.offMeshConDir = new int[option.offMeshConCount];
|
option.offMeshConDir = new int[option.offMeshConCount];
|
||||||
option.offMeshConAreas = new int[option.offMeshConCount];
|
option.offMeshConAreas = new int[option.offMeshConCount];
|
||||||
option.offMeshConFlags = new int[option.offMeshConCount];
|
option.offMeshConFlags = new int[option.offMeshConCount];
|
||||||
option.offMeshConUserID = new int[option.offMeshConCount];
|
option.offMeshConUserID = new int[option.offMeshConCount];
|
||||||
|
option.offMeshConCount = offMeshConnections.Count;
|
||||||
for (int i = 0; i < option.offMeshConCount; i++)
|
for (int i = 0; i < option.offMeshConCount; i++)
|
||||||
{
|
{
|
||||||
RcOffMeshConnection offMeshCon = offMeshConnections[i];
|
RcOffMeshConnection offMeshCon = offMeshConnections[i];
|
||||||
|
@ -65,7 +65,7 @@ namespace DotRecast.Recast.Toolset.Geom
|
||||||
option.offMeshConDir[i] = offMeshCon.bidir ? 1 : 0;
|
option.offMeshConDir[i] = offMeshCon.bidir ? 1 : 0;
|
||||||
option.offMeshConAreas[i] = offMeshCon.area;
|
option.offMeshConAreas[i] = offMeshCon.area;
|
||||||
option.offMeshConFlags[i] = offMeshCon.flags;
|
option.offMeshConFlags[i] = offMeshCon.flags;
|
||||||
option.offMeshConUserID[i] = offMeshCon.userId;
|
// option.offMeshConUserID[i] = offMeshCon.userId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -41,7 +41,7 @@ namespace DotRecast.Recast.Toolset.Geom
|
||||||
|
|
||||||
public static DemoInputGeomProvider LoadFile(string objFilePath)
|
public static DemoInputGeomProvider LoadFile(string objFilePath)
|
||||||
{
|
{
|
||||||
byte[] chunk = RcIO.ReadFileIfFound(objFilePath);
|
byte[] chunk = RcResources.Load(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 = new RcVec3f(vertices);
|
bmin = RcVecUtils.Create(vertices);
|
||||||
bmax = new RcVec3f(vertices);
|
bmax = RcVecUtils.Create(vertices);
|
||||||
for (int i = 1; i < vertices.Length / 3; i++)
|
for (int i = 1; i < vertices.Length / 3; i++)
|
||||||
{
|
{
|
||||||
bmin = RcVec3f.Min(bmin, RcVec.Create(vertices, i * 3));
|
bmin = RcVecUtils.Min(bmin, vertices, i * 3);
|
||||||
bmax = RcVec3f.Max(bmax, RcVec.Create(vertices, i * 3));
|
bmax = RcVecUtils.Max(bmax, 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)
|
||||||
{
|
{
|
||||||
RcVec3f v0 = RcVec.Create(vertices, faces[i] * 3);
|
int v0 = faces[i] * 3;
|
||||||
RcVec3f v1 = RcVec.Create(vertices, faces[i + 1] * 3);
|
int v1 = faces[i + 1] * 3;
|
||||||
RcVec3f v2 = RcVec.Create(vertices, faces[i + 2] * 3);
|
int v2 = faces[i + 2] * 3;
|
||||||
RcVec3f e0 = v1 - v0;
|
var e0 = RcVecUtils.Subtract(vertices, v1, v0);
|
||||||
RcVec3f e1 = v2 - v0;
|
var e1 = RcVecUtils.Subtract(vertices, 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 = RcChunkyTriMeshs.GetChunksOverlappingSegment(_mesh.chunkyTriMesh, p, q);
|
List<RcChunkyTriMeshNode> chunks = _mesh.chunkyTriMesh.GetChunksOverlappingSegment(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);
|
||||||
Span<RcVec3f> normals = stackalloc RcVec3f[3];
|
RcVec3f[] normals = new 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);
|
||||||
Span<RcVec3f> normals = stackalloc RcVec3f[3];
|
RcVec3f[] normals = new 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 const int SEGMENTS = 16;
|
private static readonly int SEGMENTS = 16;
|
||||||
private const int RINGS = 8;
|
private static readonly int RINGS = 8;
|
||||||
|
|
||||||
private static float[] sphericalVertices;
|
private static float[] sphericalVertices;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
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,4 +1,4 @@
|
||||||
namespace DotRecast.Recast.Toolset
|
namespace DotRecast.Recast.Toolset
|
||||||
{
|
{
|
||||||
public class RcNavMeshBuildSettings
|
public class RcNavMeshBuildSettings
|
||||||
{
|
{
|
||||||
|
@ -31,8 +31,5 @@ namespace DotRecast.Recast.Toolset
|
||||||
|
|
||||||
public bool tiled = false;
|
public bool tiled = false;
|
||||||
public int tileSize = 32;
|
public int tileSize = 32;
|
||||||
|
|
||||||
public bool keepInterResults = true; // full memory
|
|
||||||
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 double _samplingUpdateTime;
|
private long _samplingUpdateTime;
|
||||||
private readonly RcCyclicBuffer<long> _updateTimes;
|
private readonly RcCyclicBuffer<long> _updateTimes;
|
||||||
private double _curUpdateTime;
|
private long _curUpdateTime;
|
||||||
private double _avgUpdateTime;
|
private long _avgUpdateTime;
|
||||||
private double _minUpdateTime;
|
private long _minUpdateTime;
|
||||||
private double _maxUpdateTime;
|
private long _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() / (double)TimeSpan.TicksPerMillisecond;
|
_samplingUpdateTime = _updateTimes.Sum() / TimeSpan.TicksPerMillisecond;
|
||||||
_curUpdateTime = currentTime / (double)TimeSpan.TicksPerMillisecond;
|
_curUpdateTime = currentTime / TimeSpan.TicksPerMillisecond;
|
||||||
_avgUpdateTime = (_updateTimes.Average() / (double)TimeSpan.TicksPerMillisecond);
|
_avgUpdateTime = (long)(_updateTimes.Average() / TimeSpan.TicksPerMillisecond);
|
||||||
_minUpdateTime = _updateTimes.Min() / (double)TimeSpan.TicksPerMillisecond;
|
_minUpdateTime = _updateTimes.Min() / TimeSpan.TicksPerMillisecond;
|
||||||
_maxUpdateTime = _updateTimes.Max() / (double)TimeSpan.TicksPerMillisecond;
|
_maxUpdateTime = _updateTimes.Max() / 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 double GetCrowdUpdateSamplingTime()
|
public long GetCrowdUpdateSamplingTime()
|
||||||
{
|
{
|
||||||
return _samplingUpdateTime;
|
return _samplingUpdateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double GetCrowdUpdateTime()
|
public long GetCrowdUpdateTime()
|
||||||
{
|
{
|
||||||
return _curUpdateTime;
|
return _curUpdateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double GetCrowdUpdateAvgTime()
|
public long GetCrowdUpdateAvgTime()
|
||||||
{
|
{
|
||||||
return _avgUpdateTime;
|
return _avgUpdateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double GetCrowdUpdateMinTime()
|
public long GetCrowdUpdateMinTime()
|
||||||
{
|
{
|
||||||
return _minUpdateTime;
|
return _minUpdateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double GetCrowdUpdateMaxTime()
|
public long 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,7 +12,5 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
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 * speed;
|
return vel.Scale(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;
|
||||||
|
@ -18,12 +18,12 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
private DtDynamicNavMesh dynaMesh;
|
private DtDynamicNavMesh dynaMesh;
|
||||||
private readonly Dictionary<long, RcGizmo> colliderGizmos;
|
private readonly Dictionary<long, RcGizmo> colliderGizmos;
|
||||||
|
|
||||||
private readonly IRcRand random;
|
private readonly Random random;
|
||||||
private readonly DemoInputGeomProvider bridgeGeom;
|
private readonly DemoInputGeomProvider bridgeGeom;
|
||||||
private readonly DemoInputGeomProvider houseGeom;
|
private readonly DemoInputGeomProvider houseGeom;
|
||||||
private readonly DemoInputGeomProvider convexGeom;
|
private readonly DemoInputGeomProvider convexGeom;
|
||||||
|
|
||||||
public RcDynamicUpdateTool(IRcRand rand, DemoInputGeomProvider bridgeGeom, DemoInputGeomProvider houseGeom, DemoInputGeomProvider convexGeom)
|
public RcDynamicUpdateTool(Random rand, DemoInputGeomProvider bridgeGeom, DemoInputGeomProvider houseGeom, DemoInputGeomProvider convexGeom)
|
||||||
{
|
{
|
||||||
this.colliderGizmos = new Dictionary<long, RcGizmo>();
|
this.colliderGizmos = new Dictionary<long, RcGizmo>();
|
||||||
this.random = rand;
|
this.random = rand;
|
||||||
|
@ -141,16 +141,6 @@ 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);
|
||||||
|
@ -169,7 +159,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.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
|
using var fs = new FileStream(filename, FileMode.CreateNew, FileAccess.Write);
|
||||||
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);
|
||||||
|
@ -349,14 +339,20 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
return resultvector;
|
return resultvector;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Update(TaskFactory executor)
|
public bool UpdateDynaMesh(TaskFactory executor)
|
||||||
{
|
{
|
||||||
if (dynaMesh == null)
|
if (dynaMesh == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dynaMesh.Update(executor);
|
bool updated = dynaMesh.Update(executor).Result;
|
||||||
|
if (updated)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Raycast(RcVec3f spos, RcVec3f epos, out float hitPos, out RcVec3f raycastHitPos)
|
public bool Raycast(RcVec3f spos, RcVec3f epos, out float hitPos, out RcVec3f raycastHitPos)
|
||||||
|
|
|
@ -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 || RcVec.Dist2D(prev, p) > agentRadius)
|
if (i == 0 || RcVecUtils.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();
|
||||||
RcRecast.CalcGridSize(bmin, bmax, setting.cellSize, out var gw, out var gh);
|
RcCommons.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(cfg, RcImmutableArray<RcBuilderResult>.Empty, _tc.GetNavMesh());
|
return new NavMeshBuildResult(RcImmutableArray<RcBuilderResult>.Empty, _tc.GetNavMesh());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearAllTempObstacles()
|
public void ClearAllTempObstacles()
|
||||||
|
@ -141,8 +141,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
navMeshParams.maxTiles = 256; // ..
|
navMeshParams.maxTiles = 256; // ..
|
||||||
navMeshParams.maxPolys = 16384;
|
navMeshParams.maxPolys = 16384;
|
||||||
|
|
||||||
var navMesh = new DtNavMesh();
|
var navMesh = new DtNavMesh(navMeshParams, 6);
|
||||||
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(RcVec.DistanceSquared(p, offMeshCon.verts, 0), RcVec.DistanceSquared(p, offMeshCon.verts, 3));
|
float d = Math.Min(RcVecUtils.DistanceSquared(p, offMeshCon.verts, 0), RcVecUtils.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,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
using DotRecast.Detour;
|
using DotRecast.Detour;
|
||||||
|
@ -11,6 +12,7 @@ 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()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -21,7 +23,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, int pathIterPolyCount, ref List<RcVec3f> smoothPath)
|
ref List<long> pathIterPolys, ref List<RcVec3f> smoothPath)
|
||||||
{
|
{
|
||||||
if (startRef == 0 || endRef == 0)
|
if (startRef == 0 || endRef == 0)
|
||||||
{
|
{
|
||||||
|
@ -35,8 +37,6 @@ 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);
|
||||||
|
@ -44,29 +44,24 @@ 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 _);
|
||||||
|
|
||||||
const float STEP_SIZE = 0.5f;
|
float STEP_SIZE = 0.5f;
|
||||||
const float SLOP = 0.01f;
|
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 < pathIterPolyCount && smoothPath.Count < MAX_SMOOTH)
|
while (0 < pathIterPolys.Count && 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, pathIterPolyCount, out var steerPos, out var steerPosFlag, out var steerPosRef))
|
pathIterPolys, out var steerPos, out var steerPosFlag, out var steerPosRef))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -91,15 +86,15 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
len = STEP_SIZE / len;
|
len = STEP_SIZE / len;
|
||||||
}
|
}
|
||||||
|
|
||||||
RcVec3f moveTgt = RcVec.Mad(iterPos, delta, len);
|
RcVec3f moveTgt = RcVecUtils.Mad(iterPos, delta, len);
|
||||||
|
|
||||||
// Move
|
// Move
|
||||||
navQuery.MoveAlongSurface(pathIterPolys[0], iterPos, moveTgt, filter, out var result, visited, out nvisited, 16);
|
navQuery.MoveAlongSurface(pathIterPolys[0], iterPos, moveTgt, filter, out var result, ref visited);
|
||||||
|
|
||||||
iterPos = result;
|
iterPos = result;
|
||||||
|
|
||||||
pathIterPolyCount = DtPathUtils.MergeCorridorStartMoved(pathIterPolys, pathIterPolyCount, MAX_POLYS, visited, nvisited);
|
DtPathUtils.MergeCorridorStartMoved(pathIterPolys, pathIterPolys.Count, MAX_POLYS, visited);
|
||||||
pathIterPolyCount = DtPathUtils.FixupShortcuts(ref pathIterPolys, pathIterPolyCount, navQuery);
|
pathIterPolys = DtPathUtils.FixupShortcuts(pathIterPolys, 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())
|
||||||
|
@ -129,7 +124,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 < pathIterPolyCount && polyRef != steerPosRef)
|
while (npos < pathIterPolys.Count && polyRef != steerPosRef)
|
||||||
{
|
{
|
||||||
prevRef = polyRef;
|
prevRef = polyRef;
|
||||||
polyRef = pathIterPolys[npos];
|
polyRef = pathIterPolys[npos];
|
||||||
|
@ -137,7 +132,6 @@ 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);
|
||||||
|
@ -171,15 +165,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, Span<DtStraightPath> straightPath, out int straightPathCount, int maxStraightPath, int straightPathOptions)
|
ref List<long> polys, ref List<DtStraightPath> straightPath, 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();
|
||||||
|
@ -201,7 +195,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
navQuery.FindStraightPath(startPt, epos, polys, polys.Count, straightPath, out straightPathCount, maxStraightPath, straightPathOptions);
|
navQuery.FindStraightPath(startPt, epos, polys, ref straightPath, MAX_POLYS, straightPathOptions);
|
||||||
|
|
||||||
return DtStatus.DT_SUCCESS;
|
return DtStatus.DT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -220,9 +214,8 @@ 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, Span<DtStraightPath> straightPath, out int straightPathCount, int maxStraightPath)
|
ref List<long> path, ref List<DtStraightPath> straightPath)
|
||||||
{
|
{
|
||||||
straightPathCount = 0;
|
|
||||||
var status = navQuery.UpdateSlicedFindPath(maxIter, out _);
|
var status = navQuery.UpdateSlicedFindPath(maxIter, out _);
|
||||||
|
|
||||||
if (!status.Succeeded())
|
if (!status.Succeeded())
|
||||||
|
@ -232,6 +225,7 @@ 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.
|
||||||
|
@ -245,7 +239,8 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
navQuery.FindStraightPath(startPos, epos, path, path.Count, straightPath, out straightPathCount, maxStraightPath, DtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS);
|
straightPath = new List<DtStraightPath>(MAX_POLYS);
|
||||||
|
navQuery.FindStraightPath(startPos, epos, path, ref straightPath, MAX_POLYS, DtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return DtStatus.DT_SUCCESS;
|
return DtStatus.DT_SUCCESS;
|
||||||
|
@ -253,12 +248,13 @@ 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, Span<DtStraightPath> straightPath, out int straightPathCount, int maxStraightPath, ref RcVec3f hitPos, ref RcVec3f hitNormal, ref bool hitResult)
|
ref List<long> polys, ref List<DtStraightPath> straightPath, 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +268,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;
|
||||||
|
@ -296,8 +292,10 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
straightPath[straightPathCount++] = new DtStraightPath(startPos, 0, 0);
|
straightPath ??= new List<DtStraightPath>();
|
||||||
straightPath[straightPathCount++] = new DtStraightPath(hitPos, 0, 0);
|
straightPath.Clear();
|
||||||
|
straightPath.Add(new DtStraightPath(startPos, 0, 0));
|
||||||
|
straightPath.Add(new DtStraightPath(hitPos, 0, 0));
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -380,7 +378,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;
|
||||||
|
|
||||||
RcVec3f[] tempQueryPoly = new RcVec3f[4];
|
var 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;
|
||||||
RcRecast.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh);
|
RcCommons.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;
|
||||||
RcRecast.CalcGridSize(bmin, bmax, settings.cellSize, out gw, out gh);
|
RcCommons.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 availableTile = navMesh.IsAvailableTileCount();
|
var availableTileCount = navMesh.GetAvailableTileCount();
|
||||||
if (!availableTile)
|
if (0 >= availableTileCount)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
|
|
||||||
var beginTick = RcFrequency.Ticks;
|
var beginTick = RcFrequency.Ticks;
|
||||||
var rb = new RcBuilder();
|
var rb = new RcBuilder();
|
||||||
var result = rb.BuildTile(geom, cfg, bmin, bmax, tx, ty, new RcAtomicInteger(0), 1, settings.keepInterResults);
|
var result = rb.BuildTile(geom, cfg, bmin, bmax, tx, ty, new RcAtomicInteger(0), 1);
|
||||||
|
|
||||||
var tb = new TileNavMeshBuilder();
|
var tb = new TileNavMeshBuilder();
|
||||||
var meshData = tb.BuildMeshData(geom, settings.cellSize, settings.cellHeight, settings.agentHeight, settings.agentRadius, settings.agentMaxClimb, RcImmutableArray.Create(result)
|
var meshData = tb.BuildMeshData(geom, settings.cellSize, settings.cellHeight, settings.agentHeight, settings.agentRadius, settings.agentMaxClimb, RcImmutableArray.Create(result)
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Recast",
|
|
||||||
"rootNamespace": "DotRecast.Recast",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Core"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": true
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -18,14 +18,278 @@ 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
|
||||||
{
|
{
|
||||||
public List<RcChunkyTriMeshNode> nodes;
|
private List<RcChunkyTriMeshNode> nodes;
|
||||||
public int ntris;
|
private int ntris;
|
||||||
public int maxTrisPerChunk;
|
private 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
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,305 +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-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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -33,7 +33,7 @@ namespace DotRecast.Recast.Geom
|
||||||
public readonly int flags;
|
public readonly int flags;
|
||||||
public readonly int userId;
|
public readonly int userId;
|
||||||
|
|
||||||
public RcOffMeshConnection(RcVec3f start, RcVec3f end, float radius, bool bidir, int area, int flags, int userId = 0)
|
public RcOffMeshConnection(RcVec3f start, RcVec3f end, float radius, bool bidir, int area, int flags)
|
||||||
{
|
{
|
||||||
verts = new float[6];
|
verts = new float[6];
|
||||||
verts[0] = start.X;
|
verts[0] = start.X;
|
||||||
|
@ -46,7 +46,6 @@ namespace DotRecast.Recast.Geom
|
||||||
this.bidir = bidir;
|
this.bidir = bidir;
|
||||||
this.area = area;
|
this.area = area;
|
||||||
this.flags = flags;
|
this.flags = flags;
|
||||||
this.userId = userId;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -19,7 +19,6 @@ 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
|
||||||
{
|
{
|
||||||
|
@ -33,8 +32,7 @@ namespace DotRecast.Recast.Geom
|
||||||
{
|
{
|
||||||
this.vertices = vertices;
|
this.vertices = vertices;
|
||||||
this.faces = faces;
|
this.faces = faces;
|
||||||
chunkyTriMesh = new RcChunkyTriMesh();
|
chunkyTriMesh = new RcChunkyTriMesh(vertices, faces, faces.Length / 3, 32);
|
||||||
RcChunkyTriMeshs.CreateChunkyTriMesh(vertices, faces, faces.Length / 3, 32, chunkyTriMesh);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int[] GetTris()
|
public int[] GetTris()
|
||||||
|
@ -47,9 +45,9 @@ namespace DotRecast.Recast.Geom
|
||||||
return vertices;
|
return vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RcChunkyTriMeshNode> GetChunksOverlappingRect(RcVec2f bmin, RcVec2f bmax)
|
public List<RcChunkyTriMeshNode> GetChunksOverlappingRect(float[] bmin, float[] bmax)
|
||||||
{
|
{
|
||||||
return RcChunkyTriMeshs.GetChunksOverlappingRect(chunkyTriMesh, bmin, bmax);
|
return chunkyTriMesh.GetChunksOverlappingRect(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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -39,7 +39,7 @@ namespace DotRecast.Recast.Geom
|
||||||
|
|
||||||
public static SimpleInputGeomProvider LoadFile(string objFilePath)
|
public static SimpleInputGeomProvider LoadFile(string objFilePath)
|
||||||
{
|
{
|
||||||
byte[] chunk = RcIO.ReadFileIfFound(objFilePath);
|
byte[] chunk = RcResources.Load(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 = new RcVec3f(vertices);
|
bmin = RcVecUtils.Create(vertices);
|
||||||
bmax = new RcVec3f(vertices);
|
bmax = RcVecUtils.Create(vertices);
|
||||||
for (int i = 1; i < vertices.Length / 3; i++)
|
for (int i = 1; i < vertices.Length / 3; i++)
|
||||||
{
|
{
|
||||||
bmin = RcVec3f.Min(bmin, RcVec.Create(vertices, i * 3));
|
bmin = RcVecUtils.Min(bmin, vertices, i * 3);
|
||||||
bmax = RcVec3f.Max(bmax, RcVec.Create(vertices, i * 3));
|
bmax = RcVecUtils.Max(bmax, 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -25,7 +25,8 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcRecast;
|
using static RcConstants;
|
||||||
|
using static RcCommons;
|
||||||
|
|
||||||
public static class RcAreas
|
public static class RcAreas
|
||||||
{
|
{
|
||||||
|
@ -456,12 +457,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 = new RcVec3f(verts);
|
RcVec3f bmin = RcVecUtils.Create(verts);
|
||||||
RcVec3f bmax = new RcVec3f(verts);
|
RcVec3f bmax = RcVecUtils.Create(verts);
|
||||||
for (int i = 3; i < verts.Length; i += 3)
|
for (int i = 3; i < verts.Length; i += 3)
|
||||||
{
|
{
|
||||||
bmin = RcVec3f.Min(bmin, RcVec.Create(verts, i));
|
bmin = RcVecUtils.Min(bmin, verts, i);
|
||||||
bmax = RcVec3f.Max(bmax, RcVec.Create(verts, i));
|
bmax = RcVecUtils.Max(bmax, verts, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
bmin.Y = minY;
|
bmin.Y = minY;
|
||||||
|
@ -752,19 +753,19 @@ namespace DotRecast.Recast
|
||||||
int vertIndexB = vertIndex;
|
int vertIndexB = vertIndex;
|
||||||
int vertIndexC = (vertIndex + 1) % numVerts;
|
int vertIndexC = (vertIndex + 1) % numVerts;
|
||||||
|
|
||||||
RcVec3f vertA = RcVec.Create(verts, vertIndexA * 3);
|
RcVec3f vertA = RcVecUtils.Create(verts, vertIndexA * 3);
|
||||||
RcVec3f vertB = RcVec.Create(verts, vertIndexB * 3);
|
RcVec3f vertB = RcVecUtils.Create(verts, vertIndexB * 3);
|
||||||
RcVec3f vertC = RcVec.Create(verts, vertIndexC * 3);
|
RcVec3f vertC = RcVecUtils.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 = RcVec.SafeNormalize(prevSegmentDir);
|
prevSegmentDir = RcVecUtils.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 = RcVec.SafeNormalize(currSegmentDir);
|
currSegmentDir = RcVecUtils.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
|
||||||
|
@ -791,7 +792,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 > RcVec.EPSILON)
|
if (cornerMiterSqMag > RcVecUtils.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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -19,9 +19,7 @@ freely, subject to the following restrictions:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
|
@ -30,7 +28,7 @@ using DotRecast.Recast.Geom;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcRecast;
|
using static RcCommons;
|
||||||
using static RcAreas;
|
using static RcAreas;
|
||||||
|
|
||||||
public class RcBuilder
|
public class RcBuilder
|
||||||
|
@ -47,113 +45,132 @@ namespace DotRecast.Recast
|
||||||
_progressListener = progressListener;
|
_progressListener = progressListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RcBuilderResult> BuildTiles(IInputGeomProvider geom, RcConfig cfg, bool keepInterResults, bool buildAll,
|
public List<RcBuilderResult> BuildTiles(IInputGeomProvider geom, RcConfig cfg, TaskFactory taskFactory)
|
||||||
int threads = 0, TaskFactory taskFactory = null, CancellationToken cancellation = default)
|
|
||||||
{
|
{
|
||||||
RcVec3f bmin = geom.GetMeshBoundsMin();
|
RcVec3f bmin = geom.GetMeshBoundsMin();
|
||||||
RcVec3f bmax = geom.GetMeshBoundsMax();
|
RcVec3f bmax = geom.GetMeshBoundsMax();
|
||||||
CalcTileCount(bmin, bmax, cfg.Cs, cfg.TileSizeX, cfg.TileSizeZ, out var tw, out var th);
|
CalcTileCount(bmin, bmax, cfg.Cs, cfg.TileSizeX, cfg.TileSizeZ, out var tw, out var th);
|
||||||
|
List<RcBuilderResult> results = new List<RcBuilderResult>();
|
||||||
if (1 < threads)
|
if (null != taskFactory)
|
||||||
{
|
{
|
||||||
return BuildMultiThread(geom, cfg, bmin, bmax, tw, th, threads, taskFactory ?? Task.Factory, cancellation, keepInterResults, buildAll);
|
BuildMultiThreadAsync(geom, cfg, bmin, bmax, tw, th, results, taskFactory, default);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
return BuildSingleThread(geom, cfg, bmin, bmax, tw, th, keepInterResults, buildAll);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<RcBuilderResult> BuildSingleThread(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax, int tw, int th,
|
|
||||||
bool keepInterResults, bool buildAll)
|
|
||||||
{
|
{
|
||||||
var results = new List<RcBuilderResult>(th * tw);
|
BuildSingleThreadAsync(geom, cfg, bmin, bmax, tw, th, results);
|
||||||
RcAtomicInteger counter = new RcAtomicInteger(0);
|
|
||||||
|
|
||||||
for (int y = 0; y < th; ++y)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < tw; ++x)
|
|
||||||
{
|
|
||||||
var result = BuildTile(geom, cfg, bmin, bmax, x, y, counter, tw * th, keepInterResults);
|
|
||||||
results.Add(result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<RcBuilderResult> BuildMultiThread(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax, int tw, int th,
|
|
||||||
int threads, TaskFactory taskFactory, CancellationToken cancellation,
|
|
||||||
bool keepInterResults, bool buildAll)
|
|
||||||
{
|
|
||||||
var results = new ConcurrentQueue<RcBuilderResult>();
|
|
||||||
RcAtomicInteger progress = new RcAtomicInteger(0);
|
|
||||||
|
|
||||||
List<Task> limits = new List<Task>(threads);
|
public Task BuildTilesAsync(IInputGeomProvider geom, RcConfig cfg, int threads, List<RcBuilderResult> results, TaskFactory taskFactory, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
RcVec3f bmin = geom.GetMeshBoundsMin();
|
||||||
|
RcVec3f bmax = geom.GetMeshBoundsMax();
|
||||||
|
CalcTileCount(bmin, bmax, cfg.Cs, cfg.TileSizeX, cfg.TileSizeZ, out var tw, out var th);
|
||||||
|
Task task;
|
||||||
|
if (1 < threads)
|
||||||
|
{
|
||||||
|
task = BuildMultiThreadAsync(geom, cfg, bmin, bmax, tw, th, results, taskFactory, cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
task = BuildSingleThreadAsync(geom, cfg, bmin, bmax, tw, th, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task BuildSingleThreadAsync(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax,
|
||||||
|
int tw, int th, List<RcBuilderResult> results)
|
||||||
|
{
|
||||||
|
RcAtomicInteger counter = new RcAtomicInteger(0);
|
||||||
|
for (int y = 0; y < th; ++y)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < tw; ++x)
|
||||||
|
{
|
||||||
|
results.Add(BuildTile(geom, cfg, bmin, bmax, x, y, counter, tw * th));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task BuildMultiThreadAsync(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax,
|
||||||
|
int tw, int th, List<RcBuilderResult> results, TaskFactory taskFactory, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
RcAtomicInteger counter = new RcAtomicInteger(0);
|
||||||
|
CountdownEvent latch = new CountdownEvent(tw * th);
|
||||||
|
List<Task> tasks = new List<Task>();
|
||||||
|
|
||||||
for (int x = 0; x < tw; ++x)
|
for (int x = 0; x < tw; ++x)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < th; ++y)
|
for (int y = 0; y < th; ++y)
|
||||||
{
|
{
|
||||||
int tx = x;
|
int tx = x;
|
||||||
int ty = y;
|
int ty = y;
|
||||||
var task = taskFactory.StartNew(state =>
|
var task = taskFactory.StartNew(() =>
|
||||||
{
|
{
|
||||||
if (cancellation.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RcBuilderResult result = BuildTile(geom, cfg, bmin, bmax, tx, ty, progress, tw * th, keepInterResults);
|
RcBuilderResult tile = BuildTile(geom, cfg, bmin, bmax, tx, ty, counter, tw * th);
|
||||||
results.Enqueue(result);
|
lock (results)
|
||||||
|
{
|
||||||
|
results.Add(tile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Console.WriteLine(e);
|
Console.WriteLine(e);
|
||||||
}
|
}
|
||||||
}, null, cancellation);
|
|
||||||
|
|
||||||
limits.Add(task);
|
|
||||||
if (threads <= limits.Count)
|
latch.Signal();
|
||||||
|
}, cancellationToken);
|
||||||
|
|
||||||
|
tasks.Add(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Task.WaitAll(limits.ToArray());
|
latch.Wait();
|
||||||
limits.Clear();
|
|
||||||
}
|
}
|
||||||
}
|
catch (ThreadInterruptedException)
|
||||||
}
|
|
||||||
|
|
||||||
if (0 < limits.Count)
|
|
||||||
{
|
{
|
||||||
Task.WaitAll(limits.ToArray());
|
|
||||||
limits.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var list = results.ToList();
|
return Task.WhenAll(tasks.ToArray());
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RcBuilderResult BuildTile(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax, int tx, int ty, RcAtomicInteger progress, int total, bool keepInterResults)
|
public RcBuilderResult BuildTile(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax, int tx,
|
||||||
|
int ty, RcAtomicInteger counter, int total)
|
||||||
{
|
{
|
||||||
var bcfg = new RcBuilderConfig(cfg, bmin, bmax, tx, ty);
|
RcBuilderResult result = Build(geom, new RcBuilderConfig(cfg, bmin, bmax, tx, ty));
|
||||||
RcBuilderResult result = Build(geom, bcfg, keepInterResults);
|
|
||||||
if (_progressListener != null)
|
if (_progressListener != null)
|
||||||
{
|
{
|
||||||
_progressListener.OnProgress(progress.IncrementAndGet(), total);
|
_progressListener.OnProgress(counter.IncrementAndGet(), total);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RcBuilderResult Build(IInputGeomProvider geom, RcBuilderConfig bcfg, bool keepInterResults)
|
public RcBuilderResult Build(IInputGeomProvider geom, RcBuilderConfig builderCfg)
|
||||||
{
|
{
|
||||||
RcConfig cfg = bcfg.cfg;
|
RcConfig cfg = builderCfg.cfg;
|
||||||
RcContext ctx = new RcContext();
|
RcContext ctx = new RcContext();
|
||||||
//
|
//
|
||||||
// Step 1. Rasterize input polygon soup.
|
// Step 1. Rasterize input polygon soup.
|
||||||
//
|
//
|
||||||
RcHeightfield solid = RcVoxelizations.BuildSolidHeightfield(ctx, geom, bcfg);
|
RcHeightfield solid = RcVoxelizations.BuildSolidHeightfield(ctx, geom, builderCfg);
|
||||||
return Build(ctx, bcfg.tileX, bcfg.tileZ, geom, cfg, solid, keepInterResults);
|
return Build(ctx, builderCfg.tileX, builderCfg.tileZ, geom, cfg, solid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RcBuilderResult Build(RcContext ctx, int tileX, int tileZ, IInputGeomProvider geom, RcConfig cfg, RcHeightfield solid, bool keepInterResults)
|
public RcBuilderResult Build(RcContext ctx, int tileX, int tileZ, IInputGeomProvider geom, RcConfig cfg, RcHeightfield solid)
|
||||||
{
|
{
|
||||||
FilterHeightfield(ctx, solid, cfg);
|
FilterHeightfield(ctx, solid, cfg);
|
||||||
RcCompactHeightfield chf = BuildCompactHeightfield(ctx, geom, cfg, solid);
|
RcCompactHeightfield chf = BuildCompactHeightfield(ctx, geom, cfg, solid);
|
||||||
|
@ -224,17 +241,7 @@ namespace DotRecast.Recast
|
||||||
RcPolyMeshDetail dmesh = cfg.BuildMeshDetail
|
RcPolyMeshDetail dmesh = cfg.BuildMeshDetail
|
||||||
? RcMeshDetails.BuildPolyMeshDetail(ctx, pmesh, chf, cfg.DetailSampleDist, cfg.DetailSampleMaxError)
|
? RcMeshDetails.BuildPolyMeshDetail(ctx, pmesh, chf, cfg.DetailSampleDist, cfg.DetailSampleMaxError)
|
||||||
: null;
|
: null;
|
||||||
|
return new RcBuilderResult(tileX, tileZ, solid, chf, cset, pmesh, dmesh, ctx);
|
||||||
return new RcBuilderResult(
|
|
||||||
tileX,
|
|
||||||
tileZ,
|
|
||||||
keepInterResults ? solid : null,
|
|
||||||
keepInterResults ? chf : null,
|
|
||||||
keepInterResults ? cset : null,
|
|
||||||
pmesh,
|
|
||||||
dmesh,
|
|
||||||
ctx
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -92,7 +92,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RcRecast.CalcGridSize(this.bmin, this.bmax, cfg.Cs, out width, out height);
|
RcCommons.CalcGridSize(this.bmin, this.bmax, cfg.Cs, out width, out height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,59 @@
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public class RcBuilderResult
|
public class RcBuilderResult
|
||||||
{
|
{
|
||||||
public readonly int TileX;
|
public readonly int tileX;
|
||||||
public readonly int TileZ;
|
public readonly int tileZ;
|
||||||
|
|
||||||
public readonly RcHeightfield SolidHeightfiled;
|
private readonly RcCompactHeightfield chf;
|
||||||
public readonly RcCompactHeightfield CompactHeightfield;
|
private readonly RcContourSet cs;
|
||||||
public readonly RcContourSet ContourSet;
|
private readonly RcPolyMesh pmesh;
|
||||||
public readonly RcPolyMesh Mesh;
|
private readonly RcPolyMeshDetail dmesh;
|
||||||
public readonly RcPolyMeshDetail MeshDetail;
|
private readonly RcHeightfield solid;
|
||||||
public readonly RcContext Context;
|
private readonly RcContext _context;
|
||||||
|
|
||||||
public RcBuilderResult(int tileX, int tileZ, RcHeightfield solidHeightfiled, RcCompactHeightfield compactHeightfield, RcContourSet contourSet, RcPolyMesh mesh, RcPolyMeshDetail meshDetail, RcContext ctx)
|
public RcBuilderResult(int tileX, int tileZ, RcHeightfield solid, RcCompactHeightfield chf, RcContourSet cs, RcPolyMesh pmesh, RcPolyMeshDetail dmesh, RcContext ctx)
|
||||||
{
|
{
|
||||||
TileX = tileX;
|
this.tileX = tileX;
|
||||||
TileZ = tileZ;
|
this.tileZ = tileZ;
|
||||||
SolidHeightfiled = solidHeightfiled;
|
this.solid = solid;
|
||||||
CompactHeightfield = compactHeightfield;
|
this.chf = chf;
|
||||||
ContourSet = contourSet;
|
this.cs = cs;
|
||||||
Mesh = mesh;
|
this.pmesh = pmesh;
|
||||||
MeshDetail = meshDetail;
|
this.dmesh = dmesh;
|
||||||
Context = ctx;
|
_context = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RcPolyMesh GetMesh()
|
||||||
|
{
|
||||||
|
return pmesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RcPolyMeshDetail GetMeshDetail()
|
||||||
|
{
|
||||||
|
return dmesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RcCompactHeightfield GetCompactHeightfield()
|
||||||
|
{
|
||||||
|
return chf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RcContourSet GetContourSet()
|
||||||
|
{
|
||||||
|
return cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RcHeightfield GetSolidHeightfield()
|
||||||
|
{
|
||||||
|
return solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RcContext GetTelemetry()
|
||||||
|
{
|
||||||
|
return _context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -24,81 +24,10 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public static class RcRecast
|
using static RcConstants;
|
||||||
|
|
||||||
|
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 };
|
||||||
|
@ -198,10 +127,7 @@ 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;
|
||||||
RcVec3f v0 = RcVec.Create(verts, tris[tri + 0] * 3);
|
CalcTriNormal(verts, tris[tri], tris[tri + 1], tris[tri + 2], ref norm);
|
||||||
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]);
|
||||||
|
@ -210,10 +136,10 @@ namespace DotRecast.Recast
|
||||||
return areas;
|
return areas;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CalcTriNormal(RcVec3f v0, RcVec3f v1, RcVec3f v2, ref RcVec3f norm)
|
public static void CalcTriNormal(float[] verts, int v0, int v1, int v2, ref RcVec3f norm)
|
||||||
{
|
{
|
||||||
var e0 = v1 - v0;
|
var e0 = RcVecUtils.Subtract(verts, v1 * 3, v0 * 3);
|
||||||
var e1 = v2 - v0;
|
var e1 = RcVecUtils.Subtract(verts, v2 * 3, v0 * 3);
|
||||||
norm = RcVec3f.Cross(e0, e1);
|
norm = RcVec3f.Cross(e0, e1);
|
||||||
norm = RcVec3f.Normalize(norm);
|
norm = RcVec3f.Normalize(norm);
|
||||||
}
|
}
|
||||||
|
@ -236,10 +162,7 @@ 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;
|
||||||
RcVec3f v0 = RcVec.Create(verts, tris[tri + 0] * 3);
|
CalcTriNormal(verts, tris[tri], tris[tri + 1], tris[tri + 2], ref norm);
|
||||||
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,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -20,14 +20,17 @@ 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 RcRecast;
|
using static RcCommons;
|
||||||
|
|
||||||
|
|
||||||
public static class RcCompacts
|
public static class RcCompacts
|
||||||
{
|
{
|
||||||
private const int MAX_HEIGHT = RC_SPAN_MAX_HEIGHT;
|
private const int MAX_HEIGHT = RcConstants.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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -20,14 +20,25 @@ 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
|
||||||
{
|
{
|
||||||
public int[] verts; //< Simplified contour vertex and connection data. [Size: 4 * #nverts]
|
/** Simplified contour vertex and connection data. [Size: 4 * #nverts] */
|
||||||
public int nverts; //< The number of vertices in the simplified contour.
|
public int[] verts;
|
||||||
public int[] rverts; //< Raw contour vertex and connection data. [Size: 4 * #nrverts]
|
|
||||||
public int nrverts; //< The number of vertices in the raw contour.
|
/** The number of vertices in the simplified contour. */
|
||||||
public int reg; //< The region id of the contour.
|
public int nverts;
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -24,8 +24,8 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
|
using static RcConstants;
|
||||||
using static RcRecast;
|
using static RcCommons;
|
||||||
|
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
RcVec.Cross(planes[p], v1, v2);
|
RcVecUtils.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)
|
||||||
{
|
{
|
||||||
Span<RcVec3f> rectangleOnStartPlane = stackalloc RcVec3f[4];
|
RcVec3f[] rectangleOnStartPlane = new RcVec3f[4];
|
||||||
Span<RcVec3f> rectangleOnEndPlane = stackalloc RcVec3f[4];
|
RcVec3f[] rectangleOnEndPlane = new 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, Span<RcVec3f> rectangleOnPlane)
|
private static float[] CylinderCapIntersection(RcVec3f start, float radiusSqr, float[] s, int i, 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] &&
|
if (vertices[vi] >= rectangle[0] && vertices[vi] < rectangle[2] && vertices[vi + 2] >= rectangle[1]
|
||||||
vertices[vi + 2] >= rectangle[1] && vertices[vi + 2] < rectangle[3])
|
&& 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 = RcVec3f.Dot(new RcVec3f(planes[j]), point);
|
float dotNormalPoint = RcVecUtils.Dot(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] - RcVec3f.Dot(new RcVec3f(planes[plane]), point)) / planes[plane][1];
|
float t = (planes[plane][3] - RcVecUtils.Dot(planes[plane], point)) / planes[plane][1];
|
||||||
RcVec3f s = new RcVec3f(point.X, point.Y + t, point.Z);
|
float[] s = { point.X, point.Y + t, point.Z };
|
||||||
float u = RcVec3f.Dot(s, new RcVec3f(planes[plane + 1])) - planes[plane + 1][3];
|
float u = RcVecUtils.Dot(s, 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 = RcVec3f.Dot(s, new RcVec3f(planes[plane + 2])) - planes[plane + 2][3];
|
float v = RcVecUtils.Dot(s, 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.Y;
|
y = s[1];
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -23,8 +23,8 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
|
using static RcConstants;
|
||||||
using static RcRecast;
|
using static RcCommons;
|
||||||
|
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -22,21 +22,29 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
/// A dynamic heightfield representing obstructed space.
|
/** Represents a heightfield layer within a layer set. */
|
||||||
/// @ingroup recast
|
|
||||||
public class RcHeightfield
|
public class RcHeightfield
|
||||||
{
|
{
|
||||||
public readonly int width; //< The width of the heightfield. (Along the x-axis in cell units.)
|
/** The width of the heightfield. (Along the x-axis in cell units.) */
|
||||||
public readonly int height; //< The height of the heightfield. (Along the z-axis in cell units.)
|
public readonly int width;
|
||||||
public readonly RcVec3f bmin; //< The minimum bounds in world space. [(x, y, z)]
|
|
||||||
public RcVec3f bmax; //< The maximum bounds in world space. [(x, y, z)]
|
|
||||||
public readonly float cs; //< The size of each cell. (On the xz-plane.)
|
|
||||||
public readonly float ch; //< The height of each cell. (The minimum increment along the y-axis.)
|
|
||||||
public readonly RcSpan[] spans; //< Heightfield of spans (width*height).
|
|
||||||
|
|
||||||
// memory pool for rcSpan instances.
|
/** The height of the heightfield. (Along the z-axis in cell units.) */
|
||||||
public RcSpanPool pools; //< Linked list of span pools.
|
public readonly int height;
|
||||||
public RcSpan freelist; //< The next free span.
|
|
||||||
|
/** The minimum bounds in world space. [(x, y, z)] */
|
||||||
|
public readonly RcVec3f bmin;
|
||||||
|
|
||||||
|
/** The maximum bounds in world space. [(x, y, z)] */
|
||||||
|
public RcVec3f bmax;
|
||||||
|
|
||||||
|
/** The size of each cell. (On the xz-plane.) */
|
||||||
|
public readonly float cs;
|
||||||
|
|
||||||
|
/** The height of each cell. (The minimum increment along the y-axis.) */
|
||||||
|
public readonly float ch;
|
||||||
|
|
||||||
|
/** Heightfield of spans (width*height). */
|
||||||
|
public readonly RcSpan[] spans;
|
||||||
|
|
||||||
/** Border size in cell units */
|
/** Border size in cell units */
|
||||||
public readonly int borderSize;
|
public readonly int borderSize;
|
||||||
|
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
public class RcLayerRegion
|
public class RcLayerRegion
|
||||||
{
|
{
|
||||||
public readonly int index;
|
public int id;
|
||||||
public List<int> layers;
|
public int layerId; // Layer ID
|
||||||
public List<int> neis;
|
|
||||||
public int ymin, ymax;
|
|
||||||
public byte layerId; // Layer ID
|
|
||||||
public bool @base; // Flag indicating if the region is the base of merged regions.
|
public bool @base; // Flag indicating if the region is the base of merged regions.
|
||||||
|
public int ymin, ymax;
|
||||||
|
public List<int> layers; // Layer count
|
||||||
|
public List<int> neis; // Neighbour count
|
||||||
|
|
||||||
public RcLayerRegion(int i)
|
public RcLayerRegion(int i)
|
||||||
{
|
{
|
||||||
index = i;
|
id = i;
|
||||||
layers = new List<int>();
|
|
||||||
neis = new List<int>();
|
|
||||||
ymin = 0xFFFF;
|
ymin = 0xFFFF;
|
||||||
layerId = 0xff;
|
layerId = 0xff;
|
||||||
|
layers = new List<int>();
|
||||||
|
neis = new List<int>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -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 byte id; // region id
|
public int id; // region id
|
||||||
public byte nei; // neighbour id
|
public int 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -25,10 +25,15 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcRecast;
|
using static RcConstants;
|
||||||
|
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))
|
||||||
|
@ -56,6 +61,7 @@ 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.
|
||||||
|
@ -74,10 +80,10 @@ namespace DotRecast.Recast
|
||||||
int w = chf.width;
|
int w = chf.width;
|
||||||
int h = chf.height;
|
int h = chf.height;
|
||||||
|
|
||||||
Span<byte> srcReg = stackalloc byte[chf.spanCount];
|
int[] srcReg = new int[chf.spanCount];
|
||||||
srcReg.Fill(0xFF);
|
Array.Fill(srcReg, 0xFF);
|
||||||
|
|
||||||
int nsweeps = chf.width;
|
int nsweeps = chf.width; // Math.Max(chf.width, chf.height);
|
||||||
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++)
|
||||||
{
|
{
|
||||||
|
@ -85,15 +91,15 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// Partition walkable area into monotone regions.
|
// Partition walkable area into monotone regions.
|
||||||
Span<int> prevCount = stackalloc int[256];
|
int[] prevCount = new int[256];
|
||||||
byte regId = 0;
|
int 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.
|
||||||
prevCount.Fill(0);
|
Array.Fill(prevCount, 0);
|
||||||
byte sweepId = 0;
|
int sweepId = 0;
|
||||||
|
|
||||||
for (int x = borderSize; x < w - borderSize; ++x)
|
for (int x = borderSize; x < w - borderSize; ++x)
|
||||||
{
|
{
|
||||||
|
@ -105,7 +111,7 @@ namespace DotRecast.Recast
|
||||||
if (chf.areas[i] == RC_NULL_AREA)
|
if (chf.areas[i] == RC_NULL_AREA)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
byte sid = 0xFF;
|
int sid = 0xFF;
|
||||||
|
|
||||||
// -x
|
// -x
|
||||||
if (GetCon(ref s, 0) != RC_NOT_CONNECTED)
|
if (GetCon(ref s, 0) != RC_NOT_CONNECTED)
|
||||||
|
@ -130,7 +136,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);
|
||||||
byte nr = srcReg[ai];
|
int 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.
|
||||||
|
@ -260,11 +266,9 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create 2D layers from regions.
|
// Create 2D layers from regions.
|
||||||
byte layerId = 0;
|
int layerId = 0;
|
||||||
|
|
||||||
const int MAX_STACK = 64;
|
List<int> stack = new List<int>();
|
||||||
Span<byte> stack = stackalloc byte[MAX_STACK];
|
|
||||||
int nstack = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < nregs; ++i)
|
for (int i = 0; i < nregs; ++i)
|
||||||
{
|
{
|
||||||
|
@ -277,16 +281,14 @@ namespace DotRecast.Recast
|
||||||
root.layerId = layerId;
|
root.layerId = layerId;
|
||||||
root.@base = true;
|
root.@base = true;
|
||||||
|
|
||||||
nstack = 0;
|
stack.Add(i);
|
||||||
stack[nstack++] = ((byte)i);
|
|
||||||
|
|
||||||
while (0 != nstack)
|
while (stack.Count != 0)
|
||||||
{
|
{
|
||||||
// Pop front
|
// Pop front
|
||||||
RcLayerRegion reg = regs[stack[0]];
|
int pop = stack[0]; // TODO : 여기에 stack 처럼 작동하게 했는데, 스택인지는 모르겠음
|
||||||
nstack--;
|
stack.RemoveAt(0);
|
||||||
for (int j = 0; j < nstack; ++j)
|
RcLayerRegion reg = regs[pop];
|
||||||
stack[j] = stack[j + 1];
|
|
||||||
|
|
||||||
foreach (int nei in reg.neis)
|
foreach (int nei in reg.neis)
|
||||||
{
|
{
|
||||||
|
@ -305,10 +307,8 @@ namespace DotRecast.Recast
|
||||||
if ((ymax - ymin) >= 255)
|
if ((ymax - ymin) >= 255)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (nstack < MAX_STACK)
|
|
||||||
{
|
|
||||||
// Deepen
|
// Deepen
|
||||||
stack[nstack++] = (byte)nei;
|
stack.Add(nei);
|
||||||
|
|
||||||
// Mark layer id
|
// Mark layer id
|
||||||
regn.layerId = layerId;
|
regn.layerId = layerId;
|
||||||
|
@ -322,7 +322,6 @@ namespace DotRecast.Recast
|
||||||
root.ymax = Math.Max(root.ymax, regn.ymax);
|
root.ymax = Math.Max(root.ymax, regn.ymax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
layerId++;
|
layerId++;
|
||||||
}
|
}
|
||||||
|
@ -336,7 +335,7 @@ namespace DotRecast.Recast
|
||||||
if (!ri.@base)
|
if (!ri.@base)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
byte newId = ri.layerId;
|
int newId = ri.layerId;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -412,7 +411,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compact layerIds
|
// Compact layerIds
|
||||||
Span<byte> remap = stackalloc byte[256];
|
int[] remap = new int[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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -22,57 +22,178 @@ 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 RcRecast;
|
using static RcCommons;
|
||||||
using static RcVec;
|
|
||||||
using static EdgeValues;
|
|
||||||
|
|
||||||
public static class RcMeshDetails
|
public static class RcMeshDetails
|
||||||
{
|
{
|
||||||
public const int RC_UNSET_HEIGHT = RC_SPAN_MAX_HEIGHT;
|
public const int MAX_VERTS = 127;
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
public static bool CircumCircle(RcVec3f p1, RcVec3f p2, RcVec3f p3, ref RcVec3f c, out float r)
|
private static float Vdot2(float[] a, float[] b)
|
||||||
|
{
|
||||||
|
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 = p2 - p1;
|
var v2 = RcVecUtils.Subtract(verts, p2, p1);
|
||||||
var v3 = p3 - p1;
|
var v3 = RcVecUtils.Subtract(verts, p3, p1);
|
||||||
|
|
||||||
float cp = Cross2(v1, v2, v3);
|
float cp = Vcross2(v1, v2, v3);
|
||||||
if (MathF.Abs(cp) > EPS)
|
if (MathF.Abs(cp) > EPS)
|
||||||
{
|
{
|
||||||
float v1Sq = Dot2(v1, v1);
|
float v1Sq = Vdot2(v1, v1);
|
||||||
float v2Sq = Dot2(v2, v2);
|
float v2Sq = Vdot2(v2, v2);
|
||||||
float v3Sq = Dot2(v3, v3);
|
float v3Sq = Vdot2(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 = Dist2(c, v1);
|
r.Exchange(Vdist2(c, v1));
|
||||||
c = c + p1;
|
c = RcVecUtils.Add(c, verts, p1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = p1;
|
c = RcVecUtils.Create(verts, p1);
|
||||||
r = 0f;
|
r.Exchange(0f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float DistPtTri(RcVec3f p, RcVec3f a, RcVec3f b, RcVec3f c)
|
private static float DistPtTri(RcVec3f p, float[] verts, int a, int b, int c)
|
||||||
{
|
{
|
||||||
var v0 = c - a;
|
var v0 = RcVecUtils.Subtract(verts, c, a);
|
||||||
var v1 = b - a;
|
var v1 = RcVecUtils.Subtract(verts, b, a);
|
||||||
var v2 = p - a;
|
var v2 = RcVecUtils.Subtract(p, verts, a);
|
||||||
|
|
||||||
float dot00 = Dot2(v0, v0);
|
float dot00 = Vdot2(v0, v0);
|
||||||
float dot01 = Dot2(v0, v1);
|
float dot01 = Vdot2(v0, v1);
|
||||||
float dot02 = Dot2(v0, v2);
|
float dot02 = Vdot2(v0, v2);
|
||||||
float dot11 = Dot2(v1, v1);
|
float dot11 = Vdot2(v1, v1);
|
||||||
float dot12 = Dot2(v1, v2);
|
float dot12 = Vdot2(v1, v2);
|
||||||
|
|
||||||
// Compute barycentric coordinates
|
// Compute barycentric coordinates
|
||||||
float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
|
float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
|
||||||
|
@ -83,14 +204,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 = a.Y + v0.Y * u + v1.Y * v;
|
float y = verts[a + 1] + v0.Y * u + v1.Y * v;
|
||||||
return MathF.Abs(y - p.Y);
|
return MathF.Abs(y - p.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
return float.MaxValue;
|
return float.MaxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float DistancePtSeg(float[] verts, int pt, int p, int q)
|
private 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];
|
||||||
|
@ -121,7 +242,7 @@ namespace DotRecast.Recast
|
||||||
return dx * dx + dy * dy + dz * dz;
|
return dx * dx + dy * dy + dz * dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float DistancePtSeg2d(RcVec3f verts, float[] poly, int p, int q)
|
private 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];
|
||||||
|
@ -149,7 +270,7 @@ namespace DotRecast.Recast
|
||||||
return dx * dx + dz * dz;
|
return dx * dx + dz * dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float DistancePtSeg2d(float[] verts, int pt, float[] poly, int p, int q)
|
private 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];
|
||||||
|
@ -177,15 +298,15 @@ namespace DotRecast.Recast
|
||||||
return dx * dx + dz * dz;
|
return dx * dx + dz * dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float DistToTriMesh(RcVec3f p, float[] verts, int nverts, List<int> tris, int ntris)
|
private 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)
|
||||||
{
|
{
|
||||||
RcVec3f va = RcVec.Create(verts, tris[i * 4 + 0] * 3);
|
int va = tris[i * 4 + 0] * 3;
|
||||||
RcVec3f vb = RcVec.Create(verts, tris[i * 4 + 1] * 3);
|
int vb = tris[i * 4 + 1] * 3;
|
||||||
RcVec3f vc = RcVec.Create(verts, tris[i * 4 + 2] * 3);
|
int vc = tris[i * 4 + 2] * 3;
|
||||||
float d = DistPtTri(p, va, vb, vc);
|
float d = DistPtTri(p, verts, va, vb, vc);
|
||||||
if (d < dmin)
|
if (d < dmin)
|
||||||
{
|
{
|
||||||
dmin = d;
|
dmin = d;
|
||||||
|
@ -200,7 +321,7 @@ namespace DotRecast.Recast
|
||||||
return dmin;
|
return dmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float DistToPoly(int nvert, float[] verts, RcVec3f p)
|
private static float DistToPoly(int nvert, float[] verts, RcVec3f p)
|
||||||
{
|
{
|
||||||
float dmin = float.MaxValue;
|
float dmin = float.MaxValue;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -221,7 +342,7 @@ namespace DotRecast.Recast
|
||||||
return c ? -dmin : dmin;
|
return c ? -dmin : dmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetHeight(float fx, float fy, float fz, float cs, float ics, float ch, int radius,
|
private 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);
|
||||||
|
@ -304,7 +425,7 @@ namespace DotRecast.Recast
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int FindEdge(List<int> edges, int s, int t)
|
private 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++)
|
||||||
{
|
{
|
||||||
|
@ -318,7 +439,7 @@ namespace DotRecast.Recast
|
||||||
return EV_UNDEF;
|
return EV_UNDEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddEdge(RcContext ctx, List<int> edges, int maxEdges, int s, int t, int l, int r)
|
private 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)
|
||||||
{
|
{
|
||||||
|
@ -336,7 +457,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UpdateLeftFace(List<int> edges, int e, int s, int t, int f)
|
private 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)
|
||||||
{
|
{
|
||||||
|
@ -348,13 +469,13 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool OverlapSegSeg2d(float[] verts, int a, int b, int c, int d)
|
private static bool OverlapSegSeg2d(float[] verts, int a, int b, int c, int d)
|
||||||
{
|
{
|
||||||
float a1 = Cross2(verts, a, b, d);
|
float a1 = Vcross2(verts, a, b, d);
|
||||||
float a2 = Cross2(verts, a, b, c);
|
float a2 = Vcross2(verts, a, b, c);
|
||||||
if (a1 * a2 < 0.0f)
|
if (a1 * a2 < 0.0f)
|
||||||
{
|
{
|
||||||
float a3 = Cross2(verts, c, d, a);
|
float a3 = Vcross2(verts, c, d, a);
|
||||||
float a4 = a3 + a2 - a1;
|
float a4 = a3 + a2 - a1;
|
||||||
if (a3 * a4 < 0.0f)
|
if (a3 * a4 < 0.0f)
|
||||||
{
|
{
|
||||||
|
@ -365,7 +486,7 @@ namespace DotRecast.Recast
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool OverlapEdges(float[] pts, List<int> edges, int s1, int t1)
|
private 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)
|
||||||
{
|
{
|
||||||
|
@ -386,7 +507,7 @@ namespace DotRecast.Recast
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int CompleteFacet(RcContext ctx, float[] pts, int npts, List<int> edges, int maxEdges, int nfaces, int e)
|
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;
|
||||||
|
|
||||||
|
@ -413,7 +534,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();
|
||||||
float r = -1f;
|
RcAtomicFloat r = new RcAtomicFloat(-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)
|
||||||
|
@ -421,32 +542,28 @@ namespace DotRecast.Recast
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
RcVec3f vs = RcVec.Create(pts, s * 3);
|
if (Vcross2(pts, s * 3, t * 3, u * 3) > EPS)
|
||||||
RcVec3f vt = RcVec.Create(pts, t * 3);
|
|
||||||
RcVec3f vu = RcVec.Create(pts, u * 3);
|
|
||||||
|
|
||||||
if (Cross2(vs, vt, vu) > EPS)
|
|
||||||
{
|
{
|
||||||
if (r < 0)
|
if (r.Get() < 0)
|
||||||
{
|
{
|
||||||
// The circle is not updated yet, do it now.
|
// The circle is not updated yet, do it now.
|
||||||
pt = u;
|
pt = u;
|
||||||
CircumCircle(vs, vt, vu, ref c, out r);
|
CircumCircle(pts, s * 3, t * 3, u * 3, ref c, r);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float d = Dist2(c, vu);
|
float d = Vdist2(c, pts, u * 3);
|
||||||
float tol = 0.001f;
|
float tol = 0.001f;
|
||||||
if (d > r * (1 + tol))
|
if (d > r.Get() * (1 + tol))
|
||||||
{
|
{
|
||||||
// Outside current circumcircle, skip.
|
// Outside current circumcircle, skip.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (d < r * (1 - tol))
|
else if (d < r.Get() * (1 - tol))
|
||||||
{
|
{
|
||||||
// Inside safe circumcircle, update circle.
|
// Inside safe circumcircle, update circle.
|
||||||
pt = u;
|
pt = u;
|
||||||
CircumCircle(vs, vt, vu, ref c, out r);
|
CircumCircle(pts, s * 3, t * 3, u * 3, ref c, r);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -464,7 +581,7 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
// Edge is valid.
|
// Edge is valid.
|
||||||
pt = u;
|
pt = u;
|
||||||
CircumCircle(vs, vt, vu, ref c, out r);
|
CircumCircle(pts, s * 3, t * 3, u * 3, ref c, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -507,7 +624,7 @@ namespace DotRecast.Recast
|
||||||
return nfaces;
|
return nfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DelaunayHull(RcContext ctx, int npts, float[] pts, int nhull, int[] hull, List<int> tris)
|
private 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;
|
||||||
|
@ -603,7 +720,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate minimum extend of the polygon.
|
// Calculate minimum extend of the polygon.
|
||||||
public static float PolyMinExtent(float[] verts, int nverts)
|
private 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++)
|
||||||
|
@ -629,7 +746,7 @@ namespace DotRecast.Recast
|
||||||
return MathF.Sqrt(minDist);
|
return MathF.Sqrt(minDist);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void TriangulateHull(int nverts, float[] verts, int nhull, int[] hull, int nin, List<int> tris)
|
private 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;
|
||||||
|
|
||||||
|
@ -649,7 +766,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 = Dist2(verts, pv, cv) + Dist2(verts, cv, nv) + Dist2(verts, nv, pv);
|
float d = Vdist2(verts, pv, cv) + Vdist2(verts, cv, nv) + Vdist2(verts, nv, pv);
|
||||||
if (d < dmin)
|
if (d < dmin)
|
||||||
{
|
{
|
||||||
start = i;
|
start = i;
|
||||||
|
@ -679,8 +796,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 = Dist2(verts, cvleft, nvleft) + Dist2(verts, nvleft, cvright);
|
float dleft = Vdist2(verts, cvleft, nvleft) + Vdist2(verts, nvleft, cvright);
|
||||||
float dright = Dist2(verts, cvright, nvright) + Dist2(verts, cvleft, nvright);
|
float dright = Vdist2(verts, cvright, nvright) + Vdist2(verts, cvleft, nvright);
|
||||||
|
|
||||||
if (dleft < dright)
|
if (dleft < dright)
|
||||||
{
|
{
|
||||||
|
@ -701,37 +818,33 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float GetJitterX(int i)
|
private 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float GetJitterY(int i)
|
private 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int BuildPolyDetail(RcContext ctx, float[] @in, int nin,
|
static int BuildPolyDetail(RcContext ctx, float[] @in, int nin, float sampleDist, float sampleMaxError,
|
||||||
float sampleDist, float sampleMaxError,
|
int heightSearchRadius, RcCompactHeightfield chf, RcHeightPatch hp, float[] verts, List<int> tris)
|
||||||
int heightSearchRadius, RcCompactHeightfield chf,
|
|
||||||
RcHeightPatch hp, float[] verts,
|
|
||||||
ref List<int> tris, ref List<int> edges, ref List<int> samples)
|
|
||||||
{
|
{
|
||||||
const int MAX_VERTS = 127;
|
List<int> samples = new List<int>(512);
|
||||||
const int MAX_TRIS = 255; // Max tris for delaunay is 2n-2-k (n=num verts, k=num hull verts).
|
|
||||||
const int MAX_VERTS_PER_EDGE = 32;
|
int nverts = 0;
|
||||||
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;
|
||||||
|
|
||||||
int nverts = nin;
|
nverts = nin;
|
||||||
|
|
||||||
for (int i = 0; i < nin; ++i)
|
for (int i = 0; i < nin; ++i)
|
||||||
{
|
{
|
||||||
RcVec.Copy(verts, i * 3, @in, i * 3);
|
RcVecUtils.Copy(verts, i * 3, @in, i * 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
edges.Clear();
|
|
||||||
tris.Clear();
|
tris.Clear();
|
||||||
|
|
||||||
float cs = chf.cs;
|
float cs = chf.cs;
|
||||||
|
@ -844,7 +957,7 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
for (int k = nidx - 2; k > 0; --k)
|
for (int k = nidx - 2; k > 0; --k)
|
||||||
{
|
{
|
||||||
RcVec.Copy(verts, nverts * 3, edge, idx[k] * 3);
|
RcVecUtils.Copy(verts, nverts * 3, edge, idx[k] * 3);
|
||||||
hull[nhull++] = nverts;
|
hull[nhull++] = nverts;
|
||||||
nverts++;
|
nverts++;
|
||||||
}
|
}
|
||||||
|
@ -853,7 +966,7 @@ namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
for (int k = 1; k < nidx - 1; ++k)
|
for (int k = 1; k < nidx - 1; ++k)
|
||||||
{
|
{
|
||||||
RcVec.Copy(verts, nverts * 3, edge, idx[k] * 3);
|
RcVecUtils.Copy(verts, nverts * 3, edge, idx[k] * 3);
|
||||||
hull[nhull++] = nverts;
|
hull[nhull++] = nverts;
|
||||||
nverts++;
|
nverts++;
|
||||||
}
|
}
|
||||||
|
@ -884,12 +997,12 @@ namespace DotRecast.Recast
|
||||||
if (sampleDist > 0)
|
if (sampleDist > 0)
|
||||||
{
|
{
|
||||||
// Create sample locations in a grid.
|
// Create sample locations in a grid.
|
||||||
RcVec3f bmin = new RcVec3f(@in);
|
RcVec3f bmin = RcVecUtils.Create(@in);
|
||||||
RcVec3f bmax = new RcVec3f(@in);
|
RcVec3f bmax = RcVecUtils.Create(@in);
|
||||||
for (int i = 1; i < nin; ++i)
|
for (int i = 1; i < nin; ++i)
|
||||||
{
|
{
|
||||||
bmin = RcVec3f.Min(bmin, RcVec.Create(@in, i * 3));
|
bmin = RcVecUtils.Min(bmin, @in, i * 3);
|
||||||
bmax = RcVec3f.Max(bmax, RcVec.Create(@in, i * 3));
|
bmax = RcVecUtils.Max(bmax, @in, i * 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
int x0 = (int)MathF.Floor(bmin.X / sampleDist);
|
int x0 = (int)MathF.Floor(bmin.X / sampleDist);
|
||||||
|
@ -992,7 +1105,7 @@ namespace DotRecast.Recast
|
||||||
return nverts;
|
return nverts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool OnHull(int a, int b, int nhull, int[] hull)
|
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)
|
||||||
|
@ -1008,7 +1121,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.
|
||||||
public static void SetTriFlags(List<int> tris, int nhull, int[] hull)
|
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;
|
||||||
|
@ -1027,7 +1140,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void SeedArrayWithPolyCenter(RcContext ctx, RcCompactHeightfield chf, int[] meshpoly, int poly, int npoly,
|
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)
|
||||||
|
@ -1176,25 +1289,22 @@ 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;
|
||||||
|
|
||||||
public static void Push3(List<int> queue, int v1, int v2, int v3)
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void GetHeightData(RcContext ctx, RcCompactHeightfield chf,
|
static void GetHeightData(RcContext ctx, RcCompactHeightfield chf, int[] meshpolys, int poly, int npoly, int[] verts,
|
||||||
int[] meshpolys, int poly, int npoly,
|
int bs, RcHeightPatch hp, int region)
|
||||||
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.
|
||||||
|
|
||||||
queue.Clear();
|
List<int> queue = new List<int>(512);
|
||||||
// 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;
|
||||||
|
@ -1260,7 +1370,6 @@ 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
|
||||||
|
@ -1332,10 +1441,7 @@ 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;
|
||||||
|
@ -1420,20 +1526,18 @@ 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, ref hp, ref arr, mesh.regs[i]);
|
GetHeightData(ctx, chf, mesh.polys, p, npoly, mesh.verts, borderSize, hp, mesh.regs[i]);
|
||||||
|
|
||||||
// Build detail mesh.
|
// Build detail mesh.
|
||||||
int nverts = BuildPolyDetail(ctx, poly, npoly,
|
int nverts = BuildPolyDetail(ctx, poly, npoly, sampleDist, sampleMaxError, heightSearchRadius, chf, hp,
|
||||||
sampleDist, sampleMaxError,
|
verts, tris);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1510,7 +1614,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @see rcAllocPolyMeshDetail, rcPolyMeshDetail
|
/// @see rcAllocPolyMeshDetail, rcPolyMeshDetail
|
||||||
public static RcPolyMeshDetail MergePolyMeshDetails(RcContext ctx, RcPolyMeshDetail[] meshes, int nmeshes)
|
private 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);
|
||||||
|
|
||||||
|
@ -1561,7 +1665,7 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
for (int k = 0; k < dm.nverts; ++k)
|
for (int k = 0; k < dm.nverts; ++k)
|
||||||
{
|
{
|
||||||
RcVec.Copy(mesh.verts, mesh.nverts * 3, dm.verts, k * 3);
|
RcVecUtils.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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -24,7 +24,7 @@ using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
using static RcRecast;
|
using static RcConstants;
|
||||||
|
|
||||||
public static class RcMeshs
|
public static class RcMeshs
|
||||||
{
|
{
|
||||||
|
@ -715,13 +715,8 @@ 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.
|
||||||
|
@ -961,7 +956,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 + ".");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1038,23 +1033,11 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1215,12 +1198,14 @@ namespace DotRecast.Recast
|
||||||
|
|
||||||
if (mesh.nverts > MAX_MESH_VERTS_POLY)
|
if (mesh.nverts > MAX_MESH_VERTS_POLY)
|
||||||
{
|
{
|
||||||
throw new Exception($"BuildPolyMesh: The resulting mesh has too many vertices {mesh.nverts} (max {MAX_MESH_VERTS_POLY}). Data can be corrupted.");
|
throw new Exception("rcBuildPolyMesh: The resulting mesh has too many vertices " + mesh.nverts
|
||||||
|
+ " (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($"BuildPolyMesh: The resulting mesh has too many polygons {mesh.npolys} (max {MAX_MESH_VERTS_POLY}). Data can be corrupted.");
|
throw new Exception("rcBuildPolyMesh: The resulting mesh has too many polygons " + mesh.npolys
|
||||||
|
+ " (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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -17,7 +17,6 @@ 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;
|
||||||
|
@ -31,9 +30,9 @@ namespace DotRecast.Recast
|
||||||
hitTime = 0.0f;
|
hitTime = 0.0f;
|
||||||
foreach (RcBuilderResult result in results)
|
foreach (RcBuilderResult result in results)
|
||||||
{
|
{
|
||||||
if (result.MeshDetail != null)
|
if (result.GetMeshDetail() != null)
|
||||||
{
|
{
|
||||||
if (Raycast(result.Mesh, result.MeshDetail, src, dst, out hitTime))
|
if (Raycast(result.GetMesh(), result.GetMeshDetail(), src, dst, out hitTime))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +45,6 @@ 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)
|
||||||
|
@ -59,7 +57,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)
|
||||||
{
|
{
|
||||||
Span<RcVec3f> vs = tempVs;
|
RcVec3f[] vs = new RcVec3f[3];
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -21,12 +21,10 @@ 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
|
||||||
|
@ -44,63 +42,6 @@ namespace DotRecast.Recast
|
||||||
aMin.Z <= bMax.Z && aMax.Z >= bMin.Z;
|
aMin.Z <= bMax.Z && aMax.Z >= bMin.Z;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocates a new span in the heightfield.
|
|
||||||
/// Use a memory pool and free list to minimize actual allocations.
|
|
||||||
///
|
|
||||||
/// @param[in] heightfield The heightfield
|
|
||||||
/// @returns A pointer to the allocated or re-used span memory.
|
|
||||||
private static RcSpan AllocSpan(RcHeightfield heightfield)
|
|
||||||
{
|
|
||||||
// If necessary, allocate new page and update the freelist.
|
|
||||||
if (heightfield.freelist == null || heightfield.freelist.next == null)
|
|
||||||
{
|
|
||||||
// Create new page.
|
|
||||||
// Allocate memory for the new pool.
|
|
||||||
RcSpanPool spanPool = new RcSpanPool();
|
|
||||||
if (spanPool == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the pool into the list of pools.
|
|
||||||
spanPool.next = heightfield.pools;
|
|
||||||
heightfield.pools = spanPool;
|
|
||||||
|
|
||||||
// Add new spans to the free list.
|
|
||||||
RcSpan freeList = heightfield.freelist;
|
|
||||||
int head = 0;
|
|
||||||
int it = RC_SPANS_PER_POOL;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
--it;
|
|
||||||
spanPool.items[it].next = freeList;
|
|
||||||
freeList = spanPool.items[it];
|
|
||||||
} while (it != head);
|
|
||||||
|
|
||||||
heightfield.freelist = spanPool.items[it];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pop item from the front of the free list.
|
|
||||||
RcSpan newSpan = heightfield.freelist;
|
|
||||||
heightfield.freelist = heightfield.freelist.next;
|
|
||||||
return newSpan;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Releases the memory used by the span back to the heightfield, so it can be re-used for new spans.
|
|
||||||
/// @param[in] heightfield The heightfield.
|
|
||||||
/// @param[in] span A pointer to the span to free
|
|
||||||
private static void FreeSpan(RcHeightfield heightfield, RcSpan span)
|
|
||||||
{
|
|
||||||
if (span == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the span to the front of the free list.
|
|
||||||
span.next = heightfield.freelist;
|
|
||||||
heightfield.freelist = span;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Adds a span to the heightfield. If the new span overlaps existing spans,
|
/// Adds a span to the heightfield. If the new span overlaps existing spans,
|
||||||
/// it will merge the new span with the existing ones.
|
/// it will merge the new span with the existing ones.
|
||||||
|
@ -209,13 +150,13 @@ 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(Span<float> inVerts, int inVertsOffset, int inVertsCount,
|
private static void DividePoly(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)
|
||||||
{
|
{
|
||||||
// How far positive or negative away from the separating axis is each vertex.
|
// How far positive or negative away from the separating axis is each vertex.
|
||||||
Span<float> inVertAxisDelta = stackalloc float[12];
|
float[] inVertAxisDelta = new float[12];
|
||||||
for (int inVert = 0; inVert < inVertsCount; ++inVert)
|
for (int inVert = 0; inVert < inVertsCount; ++inVert)
|
||||||
{
|
{
|
||||||
inVertAxisDelta[inVert] = axisOffset - inVerts[inVertsOffset + inVert * 3 + axis];
|
inVertAxisDelta[inVert] = axisOffset - inVerts[inVertsOffset + inVert * 3 + axis];
|
||||||
|
@ -233,7 +174,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;
|
||||||
RcVec.Copy(inVerts, outVerts2 + poly2Vert * 3, inVerts, outVerts1 + poly1Vert * 3);
|
RcVecUtils.Copy(inVerts, outVerts2 + poly2Vert * 3, inVerts, outVerts1 + poly1Vert * 3);
|
||||||
poly1Vert++;
|
poly1Vert++;
|
||||||
poly2Vert++;
|
poly2Vert++;
|
||||||
|
|
||||||
|
@ -241,12 +182,12 @@ namespace DotRecast.Recast
|
||||||
// since these were already added above
|
// since these were already added above
|
||||||
if (inVertAxisDelta[inVertA] > 0)
|
if (inVertAxisDelta[inVertA] > 0)
|
||||||
{
|
{
|
||||||
RcVec.Copy(inVerts, outVerts1 + poly1Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
RcVecUtils.Copy(inVerts, outVerts1 + poly1Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
||||||
poly1Vert++;
|
poly1Vert++;
|
||||||
}
|
}
|
||||||
else if (inVertAxisDelta[inVertA] < 0)
|
else if (inVertAxisDelta[inVertA] < 0)
|
||||||
{
|
{
|
||||||
RcVec.Copy(inVerts, outVerts2 + poly2Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
RcVecUtils.Copy(inVerts, outVerts2 + poly2Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
||||||
poly2Vert++;
|
poly2Vert++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,7 +196,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)
|
||||||
{
|
{
|
||||||
RcVec.Copy(inVerts, outVerts1 + poly1Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
RcVecUtils.Copy(inVerts, outVerts1 + poly1Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
||||||
poly1Vert++;
|
poly1Vert++;
|
||||||
if (inVertAxisDelta[inVertA] != 0)
|
if (inVertAxisDelta[inVertA] != 0)
|
||||||
{
|
{
|
||||||
|
@ -263,7 +204,7 @@ namespace DotRecast.Recast
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RcVec.Copy(inVerts, outVerts2 + poly2Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
RcVecUtils.Copy(inVerts, outVerts2 + poly2Vert * 3, inVerts, inVertsOffset + inVertA * 3);
|
||||||
poly2Vert++;
|
poly2Vert++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,13 +236,13 @@ namespace DotRecast.Recast
|
||||||
int flagMergeThreshold)
|
int flagMergeThreshold)
|
||||||
{
|
{
|
||||||
// Calculate the bounding box of the triangle.
|
// Calculate the bounding box of the triangle.
|
||||||
RcVec3f triBBMin = RcVec.Create(verts, v0 * 3);
|
RcVec3f triBBMin = RcVecUtils.Create(verts, v0 * 3);
|
||||||
triBBMin = RcVec3f.Min(triBBMin, RcVec.Create(verts, v1 * 3));
|
triBBMin = RcVecUtils.Min(triBBMin, verts, v1 * 3);
|
||||||
triBBMin = RcVec3f.Min(triBBMin, RcVec.Create(verts, v2 * 3));
|
triBBMin = RcVecUtils.Min(triBBMin, verts, v2 * 3);
|
||||||
|
|
||||||
RcVec3f triBBMax = RcVec.Create(verts, v0 * 3);
|
RcVec3f triBBMax = RcVecUtils.Create(verts, v0 * 3);
|
||||||
triBBMax = RcVec3f.Max(triBBMax, RcVec.Create(verts, v1 * 3));
|
triBBMax = RcVecUtils.Max(triBBMax, verts, v1 * 3);
|
||||||
triBBMax = RcVec3f.Max(triBBMax, RcVec.Create(verts, v2 * 3));
|
triBBMax = RcVecUtils.Max(triBBMax, 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))
|
||||||
|
@ -322,15 +263,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.
|
||||||
Span<float> buf = stackalloc float[7 * 3 * 4];
|
float[] buf = new 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;
|
||||||
|
|
||||||
RcVec.Copy(buf, 0, verts, v0 * 3);
|
RcVecUtils.Copy(buf, 0, verts, v0 * 3);
|
||||||
RcVec.Copy(buf, 3, verts, v1 * 3);
|
RcVecUtils.Copy(buf, 3, verts, v1 * 3);
|
||||||
RcVec.Copy(buf, 6, verts, v2 * 3);
|
RcVecUtils.Copy(buf, 6, verts, v2 * 3);
|
||||||
int nvRow;
|
int nvRow;
|
||||||
int nvIn = 3;
|
int nvIn = 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -25,8 +25,8 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
namespace DotRecast.Recast
|
||||||
{
|
{
|
||||||
|
using static RcConstants;
|
||||||
using static RcRecast;
|
using static RcCommons;
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
const int LOG_NB_STACKS = 3;
|
int LOG_NB_STACKS = 3;
|
||||||
const int NB_STACKS = 1 << LOG_NB_STACKS;
|
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -20,13 +20,19 @@ 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
|
||||||
{
|
{
|
||||||
public int smin; //< The lower limit of the span. [Limit: < #smax]
|
/** The lower limit of the span. [Limit: < smax] */
|
||||||
public int smax; //< The upper limit of the span. [Limit: <= #RC_SPAN_MAX_HEIGHT]
|
public int smin;
|
||||||
public int area; //< The area id assigned to the span.
|
|
||||||
public RcSpan next; //< The next span higher up in column.
|
/** The upper limit of the span. [Limit: <= SPAN_MAX_HEIGHT] */
|
||||||
|
public int smax;
|
||||||
|
|
||||||
|
/** The area id assigned to the span. */
|
||||||
|
public int area;
|
||||||
|
|
||||||
|
/** The next span higher up in column. */
|
||||||
|
public RcSpan next;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DotRecast.Recast
|
|
||||||
{
|
|
||||||
/// A memory pool used for quick allocation of spans within a heightfield.
|
|
||||||
/// @see rcHeightfield
|
|
||||||
public class RcSpanPool
|
|
||||||
{
|
|
||||||
public RcSpanPool next; //< The next span pool.
|
|
||||||
public readonly RcSpan[] items; //< Array of spans in the pool.
|
|
||||||
|
|
||||||
public RcSpanPool()
|
|
||||||
{
|
|
||||||
items = new RcSpan[RcRecast.RC_SPANS_PER_POOL];
|
|
||||||
for (int i = 0; i < items.Length; ++i)
|
|
||||||
{
|
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -19,7 +19,6 @@ 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
|
||||||
|
@ -45,18 +44,18 @@ namespace DotRecast.Recast
|
||||||
float[] verts = geom.GetVerts();
|
float[] verts = geom.GetVerts();
|
||||||
if (cfg.UseTiles)
|
if (cfg.UseTiles)
|
||||||
{
|
{
|
||||||
RcVec2f tbmin;
|
float[] tbmin = new float[2];
|
||||||
RcVec2f tbmax;
|
float[] tbmax = new float[2];
|
||||||
tbmin.X = builderCfg.bmin.X;
|
tbmin[0] = builderCfg.bmin.X;
|
||||||
tbmin.Y = builderCfg.bmin.Z;
|
tbmin[1] = builderCfg.bmin.Z;
|
||||||
tbmax.X = builderCfg.bmax.X;
|
tbmax[0] = builderCfg.bmax.X;
|
||||||
tbmax.Y = builderCfg.bmax.Z;
|
tbmax[1] = 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 = RcRecast.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
|
int[] m_triareas = RcCommons.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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +63,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 = RcRecast.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
|
int[] m_triareas = RcCommons.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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"name": "com.rnd.dotrecast",
|
|
||||||
"displayName": "DotRecast",
|
|
||||||
"version": "0.4.1"
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,278 +0,0 @@
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
<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,15 +7,15 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
<PackageReference Include="Moq" Version="4.20.72" />
|
<PackageReference Include="Moq" Version="4.20.70" />
|
||||||
<PackageReference Include="NUnit" Version="4.2.2" />
|
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||||
<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,157 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Buffers;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using DotRecast.Core.Buffers;
|
|
||||||
using DotRecast.Core.Collections;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace DotRecast.Core.Test;
|
|
||||||
|
|
||||||
public class RcArrayBenchmarkTests
|
|
||||||
{
|
|
||||||
private const int StepLength = 512;
|
|
||||||
private const int RandomLoop = 1000;
|
|
||||||
private readonly RcRand _rand = new RcRand();
|
|
||||||
|
|
||||||
private (string title, long ticks) Bench(string title, Action<int> source)
|
|
||||||
{
|
|
||||||
var begin = RcFrequency.Ticks;
|
|
||||||
for (int step = StepLength; step > 0; --step)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < RandomLoop; ++i)
|
|
||||||
{
|
|
||||||
source.Invoke(step);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var end = RcFrequency.Ticks - begin;
|
|
||||||
return (title, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void RoundForArray(int len)
|
|
||||||
{
|
|
||||||
var array = new int[len];
|
|
||||||
for (int ii = 0; ii < len; ++ii)
|
|
||||||
{
|
|
||||||
array[ii] = _rand.NextInt32();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void RoundForPureRentArray(int len)
|
|
||||||
{
|
|
||||||
var array = ArrayPool<int>.Shared.Rent(len);
|
|
||||||
for (int ii = 0; ii < array.Length; ++ii)
|
|
||||||
{
|
|
||||||
array[ii] = _rand.NextInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayPool<int>.Shared.Return(array);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void RoundForRcRentedArray(int len)
|
|
||||||
{
|
|
||||||
using var rentedArray = RcRentedArray.Rent<int>(len);
|
|
||||||
var array = rentedArray.AsArray();
|
|
||||||
for (int i = 0; i < rentedArray.Length; ++i)
|
|
||||||
{
|
|
||||||
array[i] = _rand.NextInt32();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void RoundForRcStackArray(int len)
|
|
||||||
{
|
|
||||||
var array = new RcStackArray512<int>();
|
|
||||||
for (int ii = 0; ii < len; ++ii)
|
|
||||||
{
|
|
||||||
array[ii] = _rand.NextInt32();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RoundForStackalloc(int len)
|
|
||||||
{
|
|
||||||
Span<int> array = stackalloc int[len];
|
|
||||||
for (int ii = 0; ii < len; ++ii)
|
|
||||||
{
|
|
||||||
array[ii] = _rand.NextInt32();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestBenchmarkArrays()
|
|
||||||
{
|
|
||||||
var results = new List<(string title, long ticks)>();
|
|
||||||
results.Add(Bench("new int[len]", RoundForArray));
|
|
||||||
results.Add(Bench("ArrayPool<int>.Shared.Rent(len)", RoundForPureRentArray));
|
|
||||||
results.Add(Bench("RcRentedArray.Rent<int>(len)", RoundForRcRentedArray));
|
|
||||||
results.Add(Bench("new RcStackArray512<int>()", RoundForRcStackArray));
|
|
||||||
results.Add(Bench("stackalloc int[len]", RoundForStackalloc));
|
|
||||||
|
|
||||||
results.Sort((x, y) => x.ticks.CompareTo(y.ticks));
|
|
||||||
|
|
||||||
foreach (var t in results)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"{t.title} {t.ticks / (double)TimeSpan.TicksPerMillisecond} ms");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestSpanVsArray()
|
|
||||||
{
|
|
||||||
var r = new RcRand();
|
|
||||||
var list = new List<(long[] src, long[] dest)>();
|
|
||||||
for (int i = 0; i < 14; ++i)
|
|
||||||
{
|
|
||||||
var s = new long[(int)Math.Pow(2, i + 1)];
|
|
||||||
var d = new long[(int)Math.Pow(2, i + 1)];
|
|
||||||
for (int ii = 0; ii < s.Length; ++ii)
|
|
||||||
{
|
|
||||||
s[ii] = r.NextInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
list.Add((s, d));
|
|
||||||
}
|
|
||||||
|
|
||||||
var results = new List<(string title, long ticks)>();
|
|
||||||
for (int i = 0; i < list.Count; ++i)
|
|
||||||
{
|
|
||||||
var seq = i;
|
|
||||||
|
|
||||||
Array.Fill(list[seq].dest, 0);
|
|
||||||
var resultLong = Bench($"long[{list[seq].src.Length}]", _ =>
|
|
||||||
{
|
|
||||||
var v = list[seq];
|
|
||||||
RcArrays.Copy(v.src, 0, v.dest, 0, v.src.Length);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
Array.Fill(list[seq].dest, 0);
|
|
||||||
var resultSpan = Bench($"Span<long[], {list[seq].src.Length}>", _ =>
|
|
||||||
{
|
|
||||||
var v = list[seq];
|
|
||||||
RcSpans.Copy<long>(v.src, 0, v.dest, 0, v.src.Length);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
results.Add(resultLong);
|
|
||||||
results.Add(resultSpan);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int newLine = 0;
|
|
||||||
foreach (var t in results)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"{t.title}: {t.ticks / (double)TimeSpan.TicksPerMillisecond} ms");
|
|
||||||
newLine += 1;
|
|
||||||
if (0 == (newLine % 2))
|
|
||||||
{
|
|
||||||
Console.WriteLine("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,147 +0,0 @@
|
||||||
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;
|
||||||
|
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
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,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using DotRecast.Core.Buffers;
|
using DotRecast.Core.Buffers;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
@ -32,7 +31,7 @@ public class RcRentedArrayTest
|
||||||
{
|
{
|
||||||
int length = Math.Max(2, (int)(rand.Next() * 2048));
|
int length = Math.Max(2, (int)(rand.Next() * 2048));
|
||||||
var values = RandomValues(length);
|
var values = RandomValues(length);
|
||||||
using var array = RcRentedArray.Rent<int>(length);
|
using var array = RcRentedArray.RentDisposableArray<int>(length);
|
||||||
|
|
||||||
for (int i = 0; i < array.Length; ++i)
|
for (int i = 0; i < array.Length; ++i)
|
||||||
{
|
{
|
||||||
|
@ -57,50 +56,4 @@ public class RcRentedArrayTest
|
||||||
Assert.Throws<NullReferenceException>(() => rentedArray[^1] = 0);
|
Assert.Throws<NullReferenceException>(() => rentedArray[^1] = 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestSame()
|
|
||||||
{
|
|
||||||
// not same
|
|
||||||
{
|
|
||||||
using var r1 = RcRentedArray.Rent<float>(1024);
|
|
||||||
using var r2 = RcRentedArray.Rent<float>(1024);
|
|
||||||
|
|
||||||
Assert.That(r2.AsArray() != r1.AsArray(), Is.EqualTo(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
// same
|
|
||||||
{
|
|
||||||
// error case
|
|
||||||
float[] r1Array;
|
|
||||||
using (var r1 = RcRentedArray.Rent<float>(1024))
|
|
||||||
{
|
|
||||||
r1Array = r1.AsArray();
|
|
||||||
for (int i = 0; i < r1.Length; ++i)
|
|
||||||
{
|
|
||||||
r1[i] = 123;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
using var r2 = RcRentedArray.Rent<float>(1024);
|
|
||||||
|
|
||||||
Assert.That(r2.AsArray() == r1Array, Is.EqualTo(true));
|
|
||||||
Assert.That(r2.AsArray().Sum(), Is.EqualTo(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestDispose()
|
|
||||||
{
|
|
||||||
var r1 = RcRentedArray.Rent<float>(1024);
|
|
||||||
for (int i = 0; i < r1.Length; ++i)
|
|
||||||
{
|
|
||||||
r1[i] = 123;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.That(r1.IsDisposed, Is.EqualTo(false));
|
|
||||||
r1.Dispose();
|
|
||||||
Assert.That(r1.IsDisposed, Is.EqualTo(true));
|
|
||||||
Assert.That(r1.AsArray(), Is.Null);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -1,148 +0,0 @@
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -25,6 +25,7 @@ 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 =
|
||||||
|
@ -62,9 +63,8 @@ public class AbstractCrowdTest
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp()
|
public void SetUp()
|
||||||
{
|
{
|
||||||
nmd = TestMeshDataFactory.Create();
|
nmd = new RecastTestMeshBuilder().GetMeshData();
|
||||||
navmesh = new DtNavMesh();
|
navmesh = new DtNavMesh(nmd, 6, 0);
|
||||||
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 * speed;
|
vel = vel.Scale(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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -7,15 +7,15 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
<PackageReference Include="Moq" Version="4.20.72" />
|
<PackageReference Include="Moq" Version="4.20.70" />
|
||||||
<PackageReference Include="NUnit" Version="4.2.2" />
|
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||||
<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,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -17,57 +17,212 @@ 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 Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Crowd.Test;
|
namespace DotRecast.Detour.Crowd.Test;
|
||||||
|
|
||||||
public class DtPathCorridorTest
|
public class DtPathCorridorTest
|
||||||
{
|
{
|
||||||
private readonly DtPathCorridor corridor = new DtPathCorridor();
|
private DtPathCorridor corridor;
|
||||||
private readonly IDtQueryFilter filter = new DtQueryDefaultFilter();
|
private IDtQueryFilter filter;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp()
|
public void SetUp()
|
||||||
{
|
{
|
||||||
corridor.Init(256);
|
corridor = new DtPathCorridor();
|
||||||
|
corridor.Init(DtCrowdConst.MAX_PATH_RESULT);
|
||||||
corridor.Reset(0, new RcVec3f(10, 20, 30));
|
corridor.Reset(0, new RcVec3f(10, 20, 30));
|
||||||
|
|
||||||
|
filter = new DtQueryDefaultFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test(Description = "dtMergeCorridorStartMoved")]
|
||||||
|
public void ShouldHandleEmptyInput()
|
||||||
|
{
|
||||||
|
var path = new List<long>();
|
||||||
|
const int npath = 0;
|
||||||
|
const int maxPath = 0;
|
||||||
|
var visited = new List<long>();
|
||||||
|
var result = DtPathUtils.MergeCorridorStartMoved(path, npath, maxPath, visited);
|
||||||
|
Assert.That(result, Is.EqualTo(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test(Description = "dtMergeCorridorStartMoved")]
|
||||||
|
public void ShouldHandleEmptyVisited()
|
||||||
|
{
|
||||||
|
var path = new List<long> { 1 };
|
||||||
|
const int npath = 1;
|
||||||
|
const int maxPath = 1;
|
||||||
|
|
||||||
|
var visited = new List<long>();
|
||||||
|
|
||||||
|
var result = DtPathUtils.MergeCorridorStartMoved(path, npath, maxPath, visited);
|
||||||
|
Assert.That(result, Is.EqualTo(1));
|
||||||
|
|
||||||
|
var expectedPath = new List<long> { 1 };
|
||||||
|
Assert.That(path, Is.EqualTo(expectedPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test(Description = "dtMergeCorridorStartMoved")]
|
||||||
|
public void ShouldHandleEmptyPath()
|
||||||
|
{
|
||||||
|
var path = new List<long>();
|
||||||
|
const int npath = 0;
|
||||||
|
const int maxPath = 0;
|
||||||
|
|
||||||
|
var visited = new List<long> { 1 };
|
||||||
|
|
||||||
|
var result = DtPathUtils.MergeCorridorStartMoved(path, npath, maxPath, visited);
|
||||||
|
Assert.That(result, Is.EqualTo(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test(Description = "dtMergeCorridorStartMoved")]
|
||||||
|
public void ShouldStripVisitedPointsFromPathExceptLast()
|
||||||
|
{
|
||||||
|
var path = new List<long> { 1, 2 };
|
||||||
|
const int npath = 2;
|
||||||
|
const int maxPath = 2;
|
||||||
|
|
||||||
|
var visited = new List<long> { 1, 2 };
|
||||||
|
|
||||||
|
var result = DtPathUtils.MergeCorridorStartMoved(path, npath, maxPath, visited);
|
||||||
|
Assert.That(result, Is.EqualTo(1));
|
||||||
|
|
||||||
|
var expectedPath = new List<long> { 2, 2 };
|
||||||
|
Assert.That(path, Is.EqualTo(expectedPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test(Description = "dtMergeCorridorStartMoved")]
|
||||||
|
public void ShouldAddVisitedPointsNotPresentInPathInReverseOrder()
|
||||||
|
{
|
||||||
|
var path = new List<long> { 1, 2, 0 };
|
||||||
|
const int npath = 2;
|
||||||
|
const int maxPath = 3;
|
||||||
|
var visited = new List<long> { 1, 2, 3, 4 };
|
||||||
|
var result = DtPathUtils.MergeCorridorStartMoved(path, npath, maxPath, visited);
|
||||||
|
Assert.That(result, Is.EqualTo(3));
|
||||||
|
|
||||||
|
var expectedPath = new List<long> { 4, 3, 2 };
|
||||||
|
Assert.That(path, Is.EqualTo(expectedPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test(Description = "dtMergeCorridorStartMoved")]
|
||||||
|
public void ShouldAddVisitedPointsNotPresentInPathUpToThePathCapacity()
|
||||||
|
{
|
||||||
|
var path = new List<long>() { 1, 2, 0 };
|
||||||
|
const int npath = 2;
|
||||||
|
const int maxPath = 3;
|
||||||
|
var visited = new List<long>() { 1, 2, 3, 4, 5 };
|
||||||
|
var result = DtPathUtils.MergeCorridorStartMoved(path, npath, maxPath, visited);
|
||||||
|
Assert.That(result, Is.EqualTo(3));
|
||||||
|
|
||||||
|
var expectedPath = new List<long> { 5, 4, 3 };
|
||||||
|
Assert.That(path, Is.EqualTo(expectedPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test(Description = "dtMergeCorridorStartMoved")]
|
||||||
|
public void ShouldNotChangePathIfThereIsNoIntersectionWithVisited()
|
||||||
|
{
|
||||||
|
var path = new List<long>() { 1, 2 };
|
||||||
|
const int npath = 2;
|
||||||
|
const int maxPath = 2;
|
||||||
|
var visited = new List<long>() { 3, 4 };
|
||||||
|
var result = DtPathUtils.MergeCorridorStartMoved(path, npath, maxPath, visited);
|
||||||
|
Assert.That(result, Is.EqualTo(2));
|
||||||
|
|
||||||
|
var expectedPath = new List<long> { 1, 2 };
|
||||||
|
Assert.That(path, Is.EqualTo(expectedPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test(Description = "dtMergeCorridorStartMoved")]
|
||||||
|
public void ShouldSaveUnvisitedPathPoints()
|
||||||
|
{
|
||||||
|
var path = new List<long>() { 1, 2, 0 };
|
||||||
|
const int npath = 2;
|
||||||
|
const int maxPath = 3;
|
||||||
|
var visited = new List<long>() { 1, 3 };
|
||||||
|
var result = DtPathUtils.MergeCorridorStartMoved(path, npath, maxPath, visited);
|
||||||
|
Assert.That(result, Is.EqualTo(3));
|
||||||
|
|
||||||
|
var expectedPath = new List<long> { 3, 1, 2 };
|
||||||
|
Assert.That(path, Is.EqualTo(expectedPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test(Description = "dtMergeCorridorStartMoved")]
|
||||||
|
public void ShouldSaveUnvisitedPathPointsUpToThePathCapacity()
|
||||||
|
{
|
||||||
|
var path = new List<long>() { 1, 2 };
|
||||||
|
const int npath = 2;
|
||||||
|
const int maxPath = 2;
|
||||||
|
var visited = new List<long>() { 1, 3 };
|
||||||
|
var result = DtPathUtils.MergeCorridorStartMoved(path, npath, maxPath, visited);
|
||||||
|
Assert.That(result, Is.EqualTo(2));
|
||||||
|
|
||||||
|
var expectedPath = new List<long> { 3, 1 };
|
||||||
|
Assert.That(path, Is.EqualTo(expectedPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ShouldKeepOriginalPathInFindCornersWhenNothingCanBePruned()
|
public void ShouldKeepOriginalPathInFindCornersWhenNothingCanBePruned()
|
||||||
{
|
{
|
||||||
var straightPath = new DtStraightPath[4];
|
List<DtStraightPath> straightPath = new();
|
||||||
straightPath[0] = new DtStraightPath(new RcVec3f(11, 20, 30.00001f), 0, 0);
|
straightPath.Add(new DtStraightPath(new RcVec3f(11, 20, 30.00001f), 0, 0));
|
||||||
straightPath[1] = new DtStraightPath(new RcVec3f(12, 20, 30.00002f), 0, 0);
|
straightPath.Add(new DtStraightPath(new RcVec3f(12, 20, 30.00002f), 0, 0));
|
||||||
straightPath[2] = new DtStraightPath(new RcVec3f(11f, 21, 32f), 0, 0);
|
straightPath.Add(new DtStraightPath(new RcVec3f(11f, 21, 32f), 0, 0));
|
||||||
straightPath[3] = new DtStraightPath(new RcVec3f(11f, 21, 32f), 0, 0);
|
straightPath.Add(new DtStraightPath(new RcVec3f(11f, 21, 32f), 0, 0));
|
||||||
var query = new DtNavMeshQueryMock(straightPath, DtStatus.DT_SUCCESS);
|
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);
|
||||||
|
|
||||||
Span<DtStraightPath> path = stackalloc DtStraightPath[8];
|
var path = new List<DtStraightPath>();
|
||||||
var npath = corridor.FindCorners(path, 8, query, filter);
|
corridor.FindCorners(ref path, int.MaxValue, mockQuery.Object, filter);
|
||||||
Assert.That(npath, Is.EqualTo(4));
|
Assert.That(path.Count, Is.EqualTo(4));
|
||||||
Assert.That(path.Slice(0, npath).ToArray(), Is.EqualTo(straightPath));
|
Assert.That(path, Is.EqualTo(straightPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ShouldPrunePathInFindCorners()
|
public void ShouldPrunePathInFindCorners()
|
||||||
{
|
{
|
||||||
DtStraightPath[] straightPath = new DtStraightPath[5];
|
List<DtStraightPath> straightPath = new();
|
||||||
straightPath[0] = (new DtStraightPath(new RcVec3f(10, 20, 30.00001f), 0, 0)); // too close
|
straightPath.Add(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.Add(new DtStraightPath(new RcVec3f(10, 20, 30.00002f), 0, 0)); // too close
|
||||||
straightPath[2] = (new DtStraightPath(new RcVec3f(11f, 21, 32f), 0, 0));
|
straightPath.Add(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.Add(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
|
straightPath.Add(new DtStraightPath(new RcVec3f(11f, 21, 32f), DtStraightPathFlags.DT_STRAIGHTPATH_OFFMESH_CONNECTION, 0)); // offmesh
|
||||||
|
|
||||||
var query = new DtNavMeshQueryMock(straightPath, DtStatus.DT_SUCCESS);
|
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);
|
||||||
|
|
||||||
Span<DtStraightPath> path = stackalloc DtStraightPath[8];
|
var path = new List<DtStraightPath>();
|
||||||
int npath = corridor.FindCorners(path, 8, query, filter);
|
corridor.FindCorners(ref path, int.MaxValue, mockQuery.Object, filter);
|
||||||
Assert.That(npath, Is.EqualTo(2));
|
Assert.That(path.Count, Is.EqualTo(2));
|
||||||
Assert.That(path.Slice(0, npath).ToArray(), Is.EqualTo(new DtStraightPath[] { straightPath[2], straightPath[3] }));
|
Assert.That(path, Is.EqualTo(new List<DtStraightPath> { straightPath[2], straightPath[3] }));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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
|
||||||
|
@ -23,42 +22,46 @@ using DotRecast.Recast.Geom;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Crowd.Test;
|
namespace DotRecast.Detour.Crowd.Test;
|
||||||
|
|
||||||
public class TestMeshDataFactory
|
public class RecastTestMeshBuilder
|
||||||
{
|
{
|
||||||
private const float m_cellSize = 0.3f;
|
private readonly DtMeshData meshData;
|
||||||
private const float m_cellHeight = 0.2f;
|
public const float m_cellSize = 0.3f;
|
||||||
private const float m_agentHeight = 2.0f;
|
public const float m_cellHeight = 0.2f;
|
||||||
private const float m_agentRadius = 0.6f;
|
public const float m_agentHeight = 2.0f;
|
||||||
private const float m_agentMaxClimb = 0.9f;
|
public const float m_agentRadius = 0.6f;
|
||||||
private const float m_agentMaxSlope = 45.0f;
|
public const float m_agentMaxClimb = 0.9f;
|
||||||
private const int m_regionMinSize = 8;
|
public const float m_agentMaxSlope = 45.0f;
|
||||||
private const int m_regionMergeSize = 20;
|
public const int m_regionMinSize = 8;
|
||||||
private const float m_edgeMaxLen = 12.0f;
|
public const int m_regionMergeSize = 20;
|
||||||
private const float m_edgeMaxError = 1.3f;
|
public const float m_edgeMaxLen = 12.0f;
|
||||||
private const int m_vertsPerPoly = 6;
|
public const float m_edgeMaxError = 1.3f;
|
||||||
private const float m_detailSampleDist = 6.0f;
|
public const int m_vertsPerPoly = 6;
|
||||||
private const float m_detailSampleMaxError = 1.0f;
|
public const float m_detailSampleDist = 6.0f;
|
||||||
|
public const float m_detailSampleMaxError = 1.0f;
|
||||||
|
|
||||||
public static DtMeshData Create()
|
public RecastTestMeshBuilder()
|
||||||
|
: 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(
|
||||||
partition,
|
partitionType,
|
||||||
cellSize, cellHeight,
|
cellSize, cellHeight,
|
||||||
agentMaxSlope, agentHeight, agentRadius, agentMaxClimb,
|
agentMaxSlope, agentHeight, agentRadius, agentMaxClimb,
|
||||||
regionMinSize, regionMergeSize,
|
regionMinSize, regionMergeSize,
|
||||||
|
@ -69,32 +72,32 @@ public class TestMeshDataFactory
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
||||||
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);
|
||||||
RcPolyMesh pmesh = rcResult.Mesh;
|
RcPolyMesh m_pmesh = rcResult.GetMesh();
|
||||||
for (int i = 0; i < pmesh.npolys; ++i)
|
for (int i = 0; i < m_pmesh.npolys; ++i)
|
||||||
{
|
{
|
||||||
pmesh.flags[i] = 1;
|
m_pmesh.flags[i] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
RcPolyMeshDetail dmesh = rcResult.MeshDetail;
|
RcPolyMeshDetail m_dmesh = rcResult.GetMeshDetail();
|
||||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||||
option.verts = pmesh.verts;
|
option.verts = m_pmesh.verts;
|
||||||
option.vertCount = pmesh.nverts;
|
option.vertCount = m_pmesh.nverts;
|
||||||
option.polys = pmesh.polys;
|
option.polys = m_pmesh.polys;
|
||||||
option.polyAreas = pmesh.areas;
|
option.polyAreas = m_pmesh.areas;
|
||||||
option.polyFlags = pmesh.flags;
|
option.polyFlags = m_pmesh.flags;
|
||||||
option.polyCount = pmesh.npolys;
|
option.polyCount = m_pmesh.npolys;
|
||||||
option.nvp = pmesh.nvp;
|
option.nvp = m_pmesh.nvp;
|
||||||
option.detailMeshes = dmesh.meshes;
|
option.detailMeshes = m_dmesh.meshes;
|
||||||
option.detailVerts = dmesh.verts;
|
option.detailVerts = m_dmesh.verts;
|
||||||
option.detailVertsCount = dmesh.nverts;
|
option.detailVertsCount = m_dmesh.nverts;
|
||||||
option.detailTris = dmesh.tris;
|
option.detailTris = m_dmesh.tris;
|
||||||
option.detailTriCount = dmesh.ntris;
|
option.detailTriCount = m_dmesh.ntris;
|
||||||
option.walkableHeight = agentHeight;
|
option.walkableHeight = agentHeight;
|
||||||
option.walkableRadius = agentRadius;
|
option.walkableRadius = agentRadius;
|
||||||
option.walkableClimb = agentMaxClimb;
|
option.walkableClimb = agentMaxClimb;
|
||||||
option.bmin = pmesh.bmin;
|
option.bmin = m_pmesh.bmin;
|
||||||
option.bmax = pmesh.bmax;
|
option.bmax = m_pmesh.bmax;
|
||||||
option.cs = cellSize;
|
option.cs = cellSize;
|
||||||
option.ch = cellHeight;
|
option.ch = cellHeight;
|
||||||
option.buildBvTree = true;
|
option.buildBvTree = true;
|
||||||
|
@ -117,8 +120,11 @@ public class TestMeshDataFactory
|
||||||
option.offMeshConUserID = new int[1];
|
option.offMeshConUserID = new int[1];
|
||||||
option.offMeshConUserID[0] = 0x4567;
|
option.offMeshConUserID[0] = 0x4567;
|
||||||
option.offMeshConCount = 1;
|
option.offMeshConCount = 1;
|
||||||
var meshData = DtNavMeshBuilder.CreateNavMeshData(option);
|
meshData = DtNavMeshBuilder.CreateNavMeshData(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DtMeshData GetMeshData()
|
||||||
|
{
|
||||||
return meshData;
|
return meshData;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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
|
||||||
|
|
|
@ -7,19 +7,19 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
<PackageReference Include="Moq" Version="4.20.72" />
|
<PackageReference Include="Moq" Version="4.20.70" />
|
||||||
<PackageReference Include="NUnit" Version="4.2.2" />
|
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.8" />
|
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.6" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -7,11 +6,11 @@ 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;
|
||||||
|
|
||||||
|
|
||||||
public class DynamicNavMeshTest
|
public class DynamicNavMeshTest
|
||||||
{
|
{
|
||||||
private static readonly RcVec3f START_POS = new RcVec3f(70.87453f, 0.0010070801f, 86.69021f);
|
private static readonly RcVec3f START_POS = new RcVec3f(70.87453f, 0.0010070801f, 86.69021f);
|
||||||
|
@ -23,7 +22,7 @@ public class DynamicNavMeshTest
|
||||||
[Test]
|
[Test]
|
||||||
public void E2eTest()
|
public void E2eTest()
|
||||||
{
|
{
|
||||||
byte[] bytes = RcIO.ReadFileIfFound("test_tiles.voxels");
|
byte[] bytes = RcResources.Load("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);
|
||||||
|
|
||||||
|
@ -33,7 +32,9 @@ public class DynamicNavMeshTest
|
||||||
// create dynamic navmesh
|
// create dynamic navmesh
|
||||||
DtDynamicNavMesh mesh = new DtDynamicNavMesh(f);
|
DtDynamicNavMesh mesh = new DtDynamicNavMesh(f);
|
||||||
// build navmesh asynchronously using multiple threads
|
// build navmesh asynchronously using multiple threads
|
||||||
mesh.Build(Task.Factory);
|
Task<bool> future = mesh.Build(Task.Factory);
|
||||||
|
// wait for build to complete
|
||||||
|
bool _ = future.Result;
|
||||||
|
|
||||||
// create new query
|
// create new query
|
||||||
DtNavMeshQuery query = new DtNavMeshQuery(mesh.NavMesh());
|
DtNavMeshQuery query = new DtNavMeshQuery(mesh.NavMesh());
|
||||||
|
@ -53,8 +54,9 @@ public class DynamicNavMeshTest
|
||||||
long colliderId = mesh.AddCollider(colldier);
|
long colliderId = mesh.AddCollider(colldier);
|
||||||
|
|
||||||
// update navmesh asynchronously
|
// update navmesh asynchronously
|
||||||
mesh.Update(Task.Factory);
|
future = mesh.Update(Task.Factory);
|
||||||
|
// wait for update to complete
|
||||||
|
_ = future.Result;
|
||||||
// create new query
|
// create new query
|
||||||
query = new DtNavMeshQuery(mesh.NavMesh());
|
query = new DtNavMeshQuery(mesh.NavMesh());
|
||||||
|
|
||||||
|
@ -68,7 +70,9 @@ public class DynamicNavMeshTest
|
||||||
// remove obstacle
|
// remove obstacle
|
||||||
mesh.RemoveCollider(colliderId);
|
mesh.RemoveCollider(colliderId);
|
||||||
// update navmesh asynchronously
|
// update navmesh asynchronously
|
||||||
mesh.Update(Task.Factory);
|
future = mesh.Update(Task.Factory);
|
||||||
|
// wait for update to complete
|
||||||
|
_ = future.Result;
|
||||||
// create new query
|
// create new query
|
||||||
query = new DtNavMeshQuery(mesh.NavMesh());
|
query = new DtNavMeshQuery(mesh.NavMesh());
|
||||||
|
|
||||||
|
@ -80,101 +84,4 @@ 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
recast4j copyright (c) 2021 Piotr Piastucki piotr@jtilia.org
|
||||||
DotRecast Copyright (c) 2023-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -31,7 +31,7 @@ public class VoxelFileReaderTest
|
||||||
[Test]
|
[Test]
|
||||||
public void ShouldReadSingleTileFile()
|
public void ShouldReadSingleTileFile()
|
||||||
{
|
{
|
||||||
byte[] bytes = RcIO.ReadFileIfFound("test.voxels");
|
byte[] bytes = RcResources.Load("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 = RcIO.ReadFileIfFound("test_tiles.voxels");
|
byte[] bytes = RcResources.Load("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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -32,7 +32,7 @@ public class VoxelFileReaderWriterTest
|
||||||
[TestCase(true)]
|
[TestCase(true)]
|
||||||
public void ShouldReadSingleTileFile(bool compression)
|
public void ShouldReadSingleTileFile(bool compression)
|
||||||
{
|
{
|
||||||
byte[] bytes = RcIO.ReadFileIfFound("test.voxels");
|
byte[] bytes = RcResources.Load("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 = RcIO.ReadFileIfFound("test_tiles.voxels");
|
byte[] bytes = RcResources.Load("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,5 @@
|
||||||
/*
|
/*
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -31,6 +31,7 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Dynamic.Test;
|
namespace DotRecast.Detour.Dynamic.Test;
|
||||||
|
|
||||||
|
|
||||||
public class VoxelQueryTest
|
public class VoxelQueryTest
|
||||||
{
|
{
|
||||||
private const int TILE_WIDTH = 100;
|
private const int TILE_WIDTH = 100;
|
||||||
|
@ -93,19 +94,19 @@ public class VoxelQueryTest
|
||||||
|
|
||||||
private DtDynamicNavMesh CreateDynaMesh()
|
private DtDynamicNavMesh CreateDynaMesh()
|
||||||
{
|
{
|
||||||
var bytes = RcIO.ReadFileIfFound("test_tiles.voxels");
|
var bytes = RcResources.Load("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);
|
||||||
|
|
||||||
// load voxels from file
|
// load voxels from file
|
||||||
DtVoxelFileReader reader = new DtVoxelFileReader(DtVoxelTileLZ4ForTestCompressor.Shared);
|
DtVoxelFileReader reader = new DtVoxelFileReader(DtVoxelTileLZ4ForTestCompressor.Shared);
|
||||||
DtVoxelFile f = reader.Read(br);
|
DtVoxelFile f = reader.Read(br);
|
||||||
|
|
||||||
// create dynamic navmesh
|
// create dynamic navmesh
|
||||||
var mesh = new DtDynamicNavMesh(f);
|
var mesh = new DtDynamicNavMesh(f);
|
||||||
|
|
||||||
// build navmesh asynchronously using multiple threads
|
// build navmesh asynchronously using multiple threads
|
||||||
mesh.Build(Task.Factory);
|
Task<bool> future = mesh.Build(Task.Factory);
|
||||||
|
// wait for build to complete
|
||||||
|
var _ = future.Result;
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,15 +7,15 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
<PackageReference Include="Moq" Version="4.20.72" />
|
<PackageReference Include="Moq" Version="4.20.70" />
|
||||||
<PackageReference Include="NUnit" Version="4.2.2" />
|
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||||
<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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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 +21,7 @@ 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,8 +64,6 @@ public abstract class AbstractDetourTest
|
||||||
|
|
||||||
protected DtNavMesh CreateNavMesh()
|
protected DtNavMesh CreateNavMesh()
|
||||||
{
|
{
|
||||||
var mesh = new DtNavMesh();
|
return new DtNavMesh(new RecastTestMeshBuilder().GetMeshData(), 6, 0);
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -17,7 +17,6 @@ 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 NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Test;
|
namespace DotRecast.Detour.Test;
|
||||||
|
@ -30,10 +29,9 @@ public class ConvexConvexIntersectionTest
|
||||||
{
|
{
|
||||||
float[] p = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
|
float[] p = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
|
||||||
float[] q = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
|
float[] q = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
|
||||||
float[] buffer = new float[128];
|
float[] intersection = DtConvexConvexIntersections.Intersect(p, q);
|
||||||
Span<float> intersection = DtConvexConvexIntersections.Intersect(p, q, buffer);
|
|
||||||
Assert.That(intersection.Length, Is.EqualTo(5 * 3));
|
Assert.That(intersection.Length, Is.EqualTo(5 * 3));
|
||||||
Assert.That(intersection.ToArray(), Is.EquivalentTo(p));
|
Assert.That(intersection, Is.EqualTo(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -41,9 +39,8 @@ public class ConvexConvexIntersectionTest
|
||||||
{
|
{
|
||||||
float[] p = { -5, 0, -5, -5, 0, 4, 1, 0, 4, 1, 0, -5 };
|
float[] p = { -5, 0, -5, -5, 0, 4, 1, 0, 4, 1, 0, -5 };
|
||||||
float[] q = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
|
float[] q = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
|
||||||
float[] buffer = new float[128];
|
float[] intersection = DtConvexConvexIntersections.Intersect(p, q);
|
||||||
Span<float> intersection = DtConvexConvexIntersections.Intersect(p, q, buffer);
|
|
||||||
Assert.That(intersection.Length, Is.EqualTo(5 * 3));
|
Assert.That(intersection.Length, Is.EqualTo(5 * 3));
|
||||||
Assert.That(intersection.ToArray(), Is.EquivalentTo(new[] { 1, 0, 3, 1, 0, -3.4f, -2, 0, -4, -4, 0, 0, -3, 0, 3 }));
|
Assert.That(intersection, Is.EqualTo(new[] { 1, 0, 3, 1, 0, -3.4f, -2, 0, -4, -4, 0, 0, -3, 0, 3 }));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,15 +7,15 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
<PackageReference Include="Moq" Version="4.20.72" />
|
<PackageReference Include="Moq" Version="4.20.70" />
|
||||||
<PackageReference Include="NUnit" Version="4.2.2" />
|
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||||
<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;
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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,12 +21,10 @@ 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 =
|
private static readonly long[] POLY_REFS = { 281474976710696L, 281474976710773L, 281474976710680L, 281474976710753L, 281474976710733L };
|
||||||
{
|
|
||||||
281474976710696L, 281474976710773L, 281474976710680L, 281474976710753L, 281474976710733L
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly RcVec3f[] POLY_POS =
|
private static readonly RcVec3f[] POLY_POS =
|
||||||
{
|
{
|
||||||
|
@ -47,11 +44,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, $"index({i})");
|
Assert.That(status.Succeeded(), Is.True);
|
||||||
Assert.That(nearestRef, Is.EqualTo(POLY_REFS[i]), $"index({i})");
|
Assert.That(nearestRef, Is.EqualTo(POLY_REFS[i]));
|
||||||
Assert.That(nearestPt.X, Is.EqualTo(POLY_POS[i].X).Within(0.001f), $"index({i})");
|
Assert.That(nearestPt.X, Is.EqualTo(POLY_POS[i].X).Within(0.001f));
|
||||||
Assert.That(nearestPt.Y, Is.EqualTo(POLY_POS[i].Y).Within(0.001f), $"index({i})");
|
Assert.That(nearestPt.Y, Is.EqualTo(POLY_POS[i].Y).Within(0.001f));
|
||||||
Assert.That(nearestPt.Z, Is.EqualTo(POLY_POS[i].Z).Within(0.001f), $"index({i})");
|
Assert.That(nearestPt.Z, Is.EqualTo(POLY_POS[i].Z).Within(0.001f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,13 +16,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 =
|
||||||
|
@ -185,7 +184,6 @@ 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++) {
|
||||||
|
@ -194,8 +192,9 @@ 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);
|
||||||
query.FindStraightPath(startPos, endPos, path, path.Count, straightPath, out var nstraightPath, 256, 0);
|
var straightPath = new List<DtStraightPath>();
|
||||||
Assert.That(nstraightPath, Is.EqualTo(STRAIGHT_PATHS[i].Length));
|
query.FindStraightPath(startPos, endPos, path, ref straightPath, int.MaxValue, 0);
|
||||||
|
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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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,13 +16,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 =
|
||||||
|
@ -83,30 +82,28 @@ public class GetPolyWallSegmentsTest : AbstractDetourTest
|
||||||
[Test]
|
[Test]
|
||||||
public void TestFindDistanceToWall()
|
public void TestFindDistanceToWall()
|
||||||
{
|
{
|
||||||
const int MAX_SEGS = DtDetour.DT_VERTS_PER_POLYGON * 4;
|
var segmentVerts = new List<RcSegmentVert>();
|
||||||
Span<RcSegmentVert> segs = stackalloc RcSegmentVert[MAX_SEGS];
|
var segmentRefs = new List<long>();
|
||||||
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], filter, segs, refs, ref nsegs, MAX_SEGS);
|
var result = query.GetPolyWallSegments(startRefs[i], true, filter, ref segmentVerts, ref segmentRefs);
|
||||||
Assert.That(nsegs, Is.EqualTo(VERTICES[i].Length));
|
Assert.That(segmentVerts.Count, Is.EqualTo(VERTICES[i].Length));
|
||||||
Assert.That(nsegs, Is.EqualTo(REFS[i].Length));
|
Assert.That(segmentRefs.Count, 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(segs[v].vmin.X, Is.EqualTo(VERTICES[i][v].vmin.X).Within(0.001f));
|
Assert.That(segmentVerts[v].vmin.X, Is.EqualTo(VERTICES[i][v].vmin.X).Within(0.001f));
|
||||||
Assert.That(segs[v].vmin.Y, Is.EqualTo(VERTICES[i][v].vmin.Y).Within(0.001f));
|
Assert.That(segmentVerts[v].vmin.Y, Is.EqualTo(VERTICES[i][v].vmin.Y).Within(0.001f));
|
||||||
Assert.That(segs[v].vmin.Z, Is.EqualTo(VERTICES[i][v].vmin.Z).Within(0.001f));
|
Assert.That(segmentVerts[v].vmin.Z, Is.EqualTo(VERTICES[i][v].vmin.Z).Within(0.001f));
|
||||||
Assert.That(segs[v].vmax.X, Is.EqualTo(VERTICES[i][v].vmax.X).Within(0.001f));
|
Assert.That(segmentVerts[v].vmax.X, Is.EqualTo(VERTICES[i][v].vmax.X).Within(0.001f));
|
||||||
Assert.That(segs[v].vmax.Y, Is.EqualTo(VERTICES[i][v].vmax.Y).Within(0.001f));
|
Assert.That(segmentVerts[v].vmax.Y, Is.EqualTo(VERTICES[i][v].vmax.Y).Within(0.001f));
|
||||||
Assert.That(segs[v].vmax.Z, Is.EqualTo(VERTICES[i][v].vmax.Z).Within(0.001f));
|
Assert.That(segmentVerts[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(refs[v], Is.EqualTo(REFS[i][v]));
|
Assert.That(segmentRefs[v], Is.EqualTo(REFS[i][v]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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
|
||||||
|
@ -33,7 +32,8 @@ public class MeshDataReaderWriterTest
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp()
|
public void SetUp()
|
||||||
{
|
{
|
||||||
meshData = TestMeshDataFactory.Create();
|
RecastTestMeshBuilder rcBuilder = new RecastTestMeshBuilder();
|
||||||
|
meshData = rcBuilder.GetMeshData();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -117,8 +117,11 @@ 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));
|
||||||
Assert.That(readData.bvTree[i].bmin, Is.EqualTo(meshData.bvTree[i].bmin));
|
for (int j = 0; j < 3; j++)
|
||||||
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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,6 +24,7 @@ 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,35 +32,27 @@ public class MeshSetReaderTest
|
||||||
[Test]
|
[Test]
|
||||||
public void TestNavmesh()
|
public void TestNavmesh()
|
||||||
{
|
{
|
||||||
byte[] @is = RcIO.ReadFileIfFound("all_tiles_navmesh.bin");
|
byte[] @is = RcResources.Load("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);
|
||||||
const int MAX_NEIS = 32;
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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);
|
||||||
nneis = mesh.GetTilesAt(1, 6, tiles, MAX_NEIS);
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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);
|
||||||
nneis = mesh.GetTilesAt(6, 2, tiles, MAX_NEIS);
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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);
|
||||||
nneis = mesh.GetTilesAt(7, 6, tiles, MAX_NEIS);
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
@ -68,7 +60,7 @@ public class MeshSetReaderTest
|
||||||
[Test]
|
[Test]
|
||||||
public void TestDungeon()
|
public void TestDungeon()
|
||||||
{
|
{
|
||||||
byte[] @is = RcIO.ReadFileIfFound("dungeon_all_tiles_navmesh.bin");
|
byte[] @is = RcResources.Load("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);
|
||||||
|
|
||||||
|
@ -76,28 +68,20 @@ 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);
|
||||||
const int MAX_NEIS = 32;
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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);
|
||||||
nneis = mesh.GetTilesAt(2, 9, tiles, MAX_NEIS);
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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);
|
||||||
nneis = mesh.GetTilesAt(4, 3, tiles, MAX_NEIS);
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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);
|
||||||
nneis = mesh.GetTilesAt(2, 8, tiles, MAX_NEIS);
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
@ -105,7 +89,7 @@ public class MeshSetReaderTest
|
||||||
[Test]
|
[Test]
|
||||||
public void TestDungeon32Bit()
|
public void TestDungeon32Bit()
|
||||||
{
|
{
|
||||||
byte[] @is = RcIO.ReadFileIfFound("dungeon_all_tiles_navmesh_32bit.bin");
|
byte[] @is = RcResources.Load("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);
|
||||||
|
|
||||||
|
@ -113,28 +97,20 @@ 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);
|
||||||
const int MAX_NEIS = 32;
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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);
|
||||||
nneis = mesh.GetTilesAt(2, 9, tiles, MAX_NEIS);
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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);
|
||||||
nneis = mesh.GetTilesAt(4, 3, tiles, MAX_NEIS);
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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);
|
||||||
nneis = mesh.GetTilesAt(2, 8, tiles, MAX_NEIS);
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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
|
||||||
|
@ -29,6 +28,7 @@ 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,12 +66,11 @@ 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();
|
DtNavMesh mesh = new DtNavMesh(header.option, 6);
|
||||||
mesh.Init(header.option, 6);
|
|
||||||
|
|
||||||
RcVec3f bmin = geom.GetMeshBoundsMin();
|
RcVec3f bmin = geom.GetMeshBoundsMin();
|
||||||
RcVec3f bmax = geom.GetMeshBoundsMax();
|
RcVec3f bmax = geom.GetMeshBoundsMax();
|
||||||
RcRecast.CalcTileCount(bmin, bmax, m_cellSize, m_tileSize, m_tileSize, out var tw, out var th);
|
RcCommons.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)
|
||||||
|
@ -93,7 +92,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, out _);
|
mesh.AddTile(data, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,28 +107,20 @@ 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);
|
||||||
const int MAX_NEIS = 32;
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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);
|
||||||
nneis = mesh.GetTilesAt(2, 9, tiles, MAX_NEIS);
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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);
|
||||||
nneis = mesh.GetTilesAt(4, 3, tiles, MAX_NEIS);
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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);
|
||||||
nneis = mesh.GetTilesAt(2, 8, tiles, MAX_NEIS);
|
Assert.That(tiles.Count, Is.EqualTo(1));
|
||||||
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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,13 +16,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 =
|
||||||
|
@ -70,21 +69,20 @@ public class MoveAlongSurfaceTest : AbstractDetourTest
|
||||||
public void TestMoveAlongSurface()
|
public void TestMoveAlongSurface()
|
||||||
{
|
{
|
||||||
IDtQueryFilter filter = new DtQueryDefaultFilter();
|
IDtQueryFilter filter = new DtQueryDefaultFilter();
|
||||||
const int MAX_VISITED = 32;
|
var visited = new List<long>();
|
||||||
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, visited, out var nvisited, MAX_VISITED);
|
var status = query.MoveAlongSurface(startRef, startPos, endPos, filter, out var result, ref 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(nvisited, Is.EqualTo(VISITED[i].Length));
|
Assert.That(visited.Count, 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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,7 +21,6 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Test;
|
namespace DotRecast.Detour.Test;
|
||||||
|
|
||||||
using static DtDetour;
|
|
||||||
|
|
||||||
public class NavMeshBuilderTest
|
public class NavMeshBuilderTest
|
||||||
{
|
{
|
||||||
|
@ -31,7 +29,7 @@ public class NavMeshBuilderTest
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp()
|
public void SetUp()
|
||||||
{
|
{
|
||||||
nmd = TestMeshDataFactory.Create();
|
nmd = new RecastTestMeshBuilder().GetMeshData();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -54,12 +52,12 @@ public class NavMeshBuilderTest
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
Assert.That(RcVec.Create(nmd.verts, 223 * 3 + (i * 3)), Is.EqualTo(nmd.offMeshCons[0].pos[i]));
|
Assert.That(RcVecUtils.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(DT_OFFMESH_CON_BIDIR));
|
Assert.That(nmd.offMeshCons[0].flags, Is.EqualTo(DtNavMesh.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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -17,7 +17,6 @@ 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;
|
using DotRecast.Core.Numerics;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
@ -33,12 +32,9 @@ public class PolygonByCircleConstraintTest
|
||||||
{
|
{
|
||||||
float[] polygon = { -2, 0, 2, 2, 0, 2, 2, 0, -2, -2, 0, -2 };
|
float[] polygon = { -2, 0, 2, 2, 0, 2, 2, 0, -2, -2, 0, -2 };
|
||||||
RcVec3f center = new RcVec3f(1, 0, 1);
|
RcVec3f center = new RcVec3f(1, 0, 1);
|
||||||
var radius = 6;
|
float[] constrained = _constraint.Apply(polygon, center, 6);
|
||||||
|
|
||||||
float[] buffer = new float[128];
|
Assert.That(constrained, Is.EqualTo(polygon));
|
||||||
Span<float> constrained = _constraint.Apply(polygon, center, radius, buffer);
|
|
||||||
|
|
||||||
Assert.That(constrained.ToArray(), Is.EquivalentTo(polygon));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -47,13 +43,10 @@ public class PolygonByCircleConstraintTest
|
||||||
int expectedSize = 21;
|
int expectedSize = 21;
|
||||||
float[] polygon = { -2, 0, 2, 2, 0, 2, 2, 0, -2, -2, 0, -2 };
|
float[] polygon = { -2, 0, 2, 2, 0, 2, 2, 0, -2, -2, 0, -2 };
|
||||||
RcVec3f center = new RcVec3f(2, 0, 0);
|
RcVec3f center = new RcVec3f(2, 0, 0);
|
||||||
var radius = 3;
|
|
||||||
|
|
||||||
float[] buffer = new float[128];
|
|
||||||
Span<float> constrained = _constraint.Apply(polygon, center, radius, buffer);
|
|
||||||
|
|
||||||
|
float[] constrained = _constraint.Apply(polygon, center, 3);
|
||||||
Assert.That(constrained.Length, Is.EqualTo(expectedSize));
|
Assert.That(constrained.Length, Is.EqualTo(expectedSize));
|
||||||
Assert.That(constrained.ToArray(), Is.SupersetOf(new[] { 2f, 0f, 2f, 2f, 0f, -2f }));
|
Assert.That(constrained, Is.SupersetOf(new[] { 2f, 0f, 2f, 2f, 0f, -2f }));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -62,10 +55,7 @@ public class PolygonByCircleConstraintTest
|
||||||
int expectedSize = 12 * 3;
|
int expectedSize = 12 * 3;
|
||||||
float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
|
float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
|
||||||
RcVec3f center = new RcVec3f(-1, 0, -1);
|
RcVec3f center = new RcVec3f(-1, 0, -1);
|
||||||
var radius = 2;
|
float[] constrained = _constraint.Apply(polygon, center, 2);
|
||||||
|
|
||||||
float[] buffer = new float[128];
|
|
||||||
Span<float> constrained = _constraint.Apply(polygon, center, radius, buffer);
|
|
||||||
|
|
||||||
Assert.That(constrained.Length, Is.EqualTo(expectedSize));
|
Assert.That(constrained.Length, Is.EqualTo(expectedSize));
|
||||||
|
|
||||||
|
@ -83,13 +73,10 @@ public class PolygonByCircleConstraintTest
|
||||||
int expectedSize = 9 * 3;
|
int expectedSize = 9 * 3;
|
||||||
float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
|
float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
|
||||||
RcVec3f center = new RcVec3f(-2, 0, -1);
|
RcVec3f center = new RcVec3f(-2, 0, -1);
|
||||||
var radius = 3;
|
float[] constrained = _constraint.Apply(polygon, center, 3);
|
||||||
|
|
||||||
float[] buffer = new float[128];
|
|
||||||
Span<float> constrained = _constraint.Apply(polygon, center, radius, buffer);
|
|
||||||
|
|
||||||
Assert.That(constrained.Length, Is.EqualTo(expectedSize));
|
Assert.That(constrained.Length, Is.EqualTo(expectedSize));
|
||||||
Assert.That(constrained.ToArray(), Is.SupersetOf(new[] { -2f, 0f, -4f, -4f, 0f, 0f, -3.4641016f, 0.0f, 1.60769534f, -2.0f, 0.0f, 2.0f }));
|
Assert.That(constrained, Is.SupersetOf(new[] { -2f, 0f, -4f, -4f, 0f, 0f, -3.4641016f, 0.0f, 1.60769534f, -2.0f, 0.0f, 2.0f }));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -98,12 +85,9 @@ public class PolygonByCircleConstraintTest
|
||||||
int expectedSize = 7 * 3;
|
int expectedSize = 7 * 3;
|
||||||
float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
|
float[] polygon = { -4, 0, 0, -3, 0, 3, 2, 0, 3, 3, 0, -3, -2, 0, -4 };
|
||||||
RcVec3f center = new RcVec3f(4, 0, 0);
|
RcVec3f center = new RcVec3f(4, 0, 0);
|
||||||
var radius = 4;
|
float[] constrained = _constraint.Apply(polygon, center, 4);
|
||||||
|
|
||||||
float[] buffer = new float[128];
|
|
||||||
Span<float> constrained = _constraint.Apply(polygon, center, radius, buffer);
|
|
||||||
|
|
||||||
Assert.That(constrained.Length, Is.EqualTo(expectedSize));
|
Assert.That(constrained.Length, Is.EqualTo(expectedSize));
|
||||||
Assert.That(constrained.ToArray(), Is.SupersetOf(new[] { 1.53589869f, 0f, 3f, 2f, 0f, 3f, 3f, 0f, -3f }));
|
Assert.That(constrained, Is.SupersetOf(new[] { 1.53589869f, 0f, 3f, 2f, 0f, 3f, 3f, 0f, -3f }));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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
|
||||||
|
@ -20,22 +19,21 @@ 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);
|
||||||
|
@ -57,9 +55,6 @@ 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]
|
||||||
|
@ -108,7 +103,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 = RcVec.Dist2D(randomPt, nextRandomPt);
|
float distance = RcVecUtils.Dist2D(randomPt, nextRandomPt);
|
||||||
Assert.That(distance <= radius, Is.True);
|
Assert.That(distance <= radius, Is.True);
|
||||||
|
|
||||||
randomRef = nextRandomRef;
|
randomRef = nextRandomRef;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,13 +16,15 @@ 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 static class TestMeshDataFactory
|
public class RecastTestMeshBuilder
|
||||||
{
|
{
|
||||||
|
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;
|
||||||
|
@ -38,24 +39,27 @@ public static class TestMeshDataFactory
|
||||||
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 static DtMeshData Create()
|
public RecastTestMeshBuilder()
|
||||||
|
: 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,
|
||||||
|
@ -68,32 +72,32 @@ public static class TestMeshDataFactory
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
||||||
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);
|
||||||
RcPolyMesh pmesh = rcResult.Mesh;
|
RcPolyMesh m_pmesh = rcResult.GetMesh();
|
||||||
for (int i = 0; i < pmesh.npolys; ++i)
|
for (int i = 0; i < m_pmesh.npolys; ++i)
|
||||||
{
|
{
|
||||||
pmesh.flags[i] = 1;
|
m_pmesh.flags[i] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
RcPolyMeshDetail dmesh = rcResult.MeshDetail;
|
RcPolyMeshDetail m_dmesh = rcResult.GetMeshDetail();
|
||||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||||
option.verts = pmesh.verts;
|
option.verts = m_pmesh.verts;
|
||||||
option.vertCount = pmesh.nverts;
|
option.vertCount = m_pmesh.nverts;
|
||||||
option.polys = pmesh.polys;
|
option.polys = m_pmesh.polys;
|
||||||
option.polyAreas = pmesh.areas;
|
option.polyAreas = m_pmesh.areas;
|
||||||
option.polyFlags = pmesh.flags;
|
option.polyFlags = m_pmesh.flags;
|
||||||
option.polyCount = pmesh.npolys;
|
option.polyCount = m_pmesh.npolys;
|
||||||
option.nvp = pmesh.nvp;
|
option.nvp = m_pmesh.nvp;
|
||||||
option.detailMeshes = dmesh.meshes;
|
option.detailMeshes = m_dmesh.meshes;
|
||||||
option.detailVerts = dmesh.verts;
|
option.detailVerts = m_dmesh.verts;
|
||||||
option.detailVertsCount = dmesh.nverts;
|
option.detailVertsCount = m_dmesh.nverts;
|
||||||
option.detailTris = dmesh.tris;
|
option.detailTris = m_dmesh.tris;
|
||||||
option.detailTriCount = dmesh.ntris;
|
option.detailTriCount = m_dmesh.ntris;
|
||||||
option.walkableHeight = agentHeight;
|
option.walkableHeight = agentHeight;
|
||||||
option.walkableRadius = agentRadius;
|
option.walkableRadius = agentRadius;
|
||||||
option.walkableClimb = agentMaxClimb;
|
option.walkableClimb = agentMaxClimb;
|
||||||
option.bmin = pmesh.bmin;
|
option.bmin = m_pmesh.bmin;
|
||||||
option.bmax = pmesh.bmax;
|
option.bmax = m_pmesh.bmax;
|
||||||
option.cs = cellSize;
|
option.cs = cellSize;
|
||||||
option.ch = cellHeight;
|
option.ch = cellHeight;
|
||||||
option.buildBvTree = true;
|
option.buildBvTree = true;
|
||||||
|
@ -116,8 +120,11 @@ public static class TestMeshDataFactory
|
||||||
option.offMeshConUserID = new int[1];
|
option.offMeshConUserID = new int[1];
|
||||||
option.offMeshConUserID[0] = 0x4567;
|
option.offMeshConUserID[0] = 0x4567;
|
||||||
option.offMeshConCount = 1;
|
option.offMeshConCount = 1;
|
||||||
var meshData = DtNavMeshBuilder.CreateNavMeshData(option);
|
meshData = DtNavMeshBuilder.CreateNavMeshData(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DtMeshData GetMeshData()
|
||||||
|
{
|
||||||
return meshData;
|
return meshData;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,5 @@
|
||||||
/*
|
/*
|
||||||
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,8 +27,8 @@ public class TestDetourBuilder : DetourBuilder
|
||||||
float agentMaxClimb, int x, int y, bool applyRecastDemoFlags)
|
float agentMaxClimb, int x, int y, bool applyRecastDemoFlags)
|
||||||
{
|
{
|
||||||
RcBuilder rcBuilder = new RcBuilder();
|
RcBuilder rcBuilder = new RcBuilder();
|
||||||
RcBuilderResult rcResult = rcBuilder.Build(geom, rcConfig, false);
|
RcBuilderResult rcResult = rcBuilder.Build(geom, rcConfig);
|
||||||
RcPolyMesh pmesh = rcResult.Mesh;
|
RcPolyMesh pmesh = rcResult.GetMesh();
|
||||||
|
|
||||||
if (applyRecastDemoFlags)
|
if (applyRecastDemoFlags)
|
||||||
{
|
{
|
||||||
|
@ -59,7 +58,7 @@ public class TestDetourBuilder : DetourBuilder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RcPolyMeshDetail dmesh = rcResult.MeshDetail;
|
RcPolyMeshDetail dmesh = rcResult.GetMeshDetail();
|
||||||
DtNavMeshCreateParams option = GetNavMeshCreateParams(rcConfig.cfg, pmesh, dmesh, agentHeight, agentRadius,
|
DtNavMeshCreateParams option = GetNavMeshCreateParams(rcConfig.cfg, pmesh, dmesh, agentHeight, agentRadius,
|
||||||
agentMaxClimb);
|
agentMaxClimb);
|
||||||
return Build(option, x, y);
|
return Build(option, x, y);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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
|
||||||
|
@ -18,6 +17,7 @@ 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,8 +64,7 @@ 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();
|
navMesh = new DtNavMesh(navMeshParams, 6);
|
||||||
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),
|
||||||
|
@ -79,13 +78,13 @@ public class TestTiledNavMeshBuilder
|
||||||
true, true, true,
|
true, true, true,
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
||||||
RcBuilder rcBuilder = new RcBuilder();
|
RcBuilder rcBuilder = new RcBuilder();
|
||||||
List<RcBuilderResult> rcResult = rcBuilder.BuildTiles(geom, cfg, false, true);
|
List<RcBuilderResult> rcResult = rcBuilder.BuildTiles(geom, cfg, null);
|
||||||
|
|
||||||
// Add tiles to nav mesh
|
// Add tiles to nav mesh
|
||||||
|
|
||||||
foreach (RcBuilderResult result in rcResult)
|
foreach (RcBuilderResult result in rcResult)
|
||||||
{
|
{
|
||||||
RcPolyMesh pmesh = result.Mesh;
|
RcPolyMesh pmesh = result.GetMesh();
|
||||||
if (pmesh.npolys == 0)
|
if (pmesh.npolys == 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -104,7 +103,7 @@ public class TestTiledNavMeshBuilder
|
||||||
option.polyFlags = pmesh.flags;
|
option.polyFlags = pmesh.flags;
|
||||||
option.polyCount = pmesh.npolys;
|
option.polyCount = pmesh.npolys;
|
||||||
option.nvp = pmesh.nvp;
|
option.nvp = pmesh.nvp;
|
||||||
RcPolyMeshDetail dmesh = result.MeshDetail;
|
RcPolyMeshDetail dmesh = result.GetMeshDetail();
|
||||||
option.detailMeshes = dmesh.meshes;
|
option.detailMeshes = dmesh.meshes;
|
||||||
option.detailVerts = dmesh.verts;
|
option.detailVerts = dmesh.verts;
|
||||||
option.detailVertsCount = dmesh.nverts;
|
option.detailVertsCount = dmesh.nverts;
|
||||||
|
@ -117,10 +116,10 @@ public class TestTiledNavMeshBuilder
|
||||||
option.bmax = pmesh.bmax;
|
option.bmax = pmesh.bmax;
|
||||||
option.cs = cellSize;
|
option.cs = cellSize;
|
||||||
option.ch = cellHeight;
|
option.ch = cellHeight;
|
||||||
option.tileX = result.TileX;
|
option.tileX = result.tileX;
|
||||||
option.tileZ = result.TileZ;
|
option.tileZ = result.tileZ;
|
||||||
option.buildBvTree = true;
|
option.buildBvTree = true;
|
||||||
navMesh.AddTile(Detour.DtNavMeshBuilder.CreateNavMeshData(option), 0, 0, out _);
|
navMesh.AddTile(DtNavMeshBuilder.CreateNavMeshData(option), 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -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();
|
||||||
RcRecast.CalcTileCount(geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), m_cellSize, m_tileSize, m_tileSize, out var tw, out var th);
|
RcCommons.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,8 +64,7 @@ public class AbstractTileCacheTest
|
||||||
navMeshParams.maxTiles = 256;
|
navMeshParams.maxTiles = 256;
|
||||||
navMeshParams.maxPolys = 16384;
|
navMeshParams.maxPolys = 16384;
|
||||||
|
|
||||||
var navMesh = new DtNavMesh();
|
var navMesh = new DtNavMesh(navMeshParams, 6);
|
||||||
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,19 +7,19 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
<PackageReference Include="Moq" Version="4.20.72" />
|
<PackageReference Include="Moq" Version="4.20.70" />
|
||||||
<PackageReference Include="NUnit" Version="4.2.2" />
|
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.8" />
|
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.6" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -35,7 +35,7 @@ public class TileCacheReaderTest
|
||||||
[Test]
|
[Test]
|
||||||
public void TestNavmesh()
|
public void TestNavmesh()
|
||||||
{
|
{
|
||||||
using var ms = new MemoryStream(RcIO.ReadFileIfFound("all_tiles_tilecache.bin"));
|
using var ms = new MemoryStream(RcResources.Load("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(RcIO.ReadFileIfFound("dungeon_all_tiles_tilecache.bin"));
|
using var ms = new MemoryStream(RcResources.Load("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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -26,6 +26,7 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.TileCache.Test;
|
namespace DotRecast.Detour.TileCache.Test;
|
||||||
|
|
||||||
|
|
||||||
public class TempObstaclesTest : AbstractTileCacheTest
|
public class TempObstaclesTest : AbstractTileCacheTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -42,29 +43,21 @@ public class TempObstaclesTest : AbstractTileCacheTest
|
||||||
tc.BuildNavMeshTile(refs);
|
tc.BuildNavMeshTile(refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int MAX_NEIS = 32;
|
List<DtMeshTile> tiles = tc.GetNavMesh().GetTilesAt(1, 4);
|
||||||
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));
|
||||||
|
@ -84,32 +77,24 @@ public class TempObstaclesTest : AbstractTileCacheTest
|
||||||
tc.BuildNavMeshTile(refs);
|
tc.BuildNavMeshTile(refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int MAX_NEIS = 32;
|
List<DtMeshTile> tiles = tc.GetNavMesh().GetTilesAt(1, 4);
|
||||||
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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -73,7 +73,7 @@ public class TestTileLayerBuilder : DtTileCacheLayerBuilder
|
||||||
|
|
||||||
RcVec3f bmin = geom.GetMeshBoundsMin();
|
RcVec3f bmin = geom.GetMeshBoundsMin();
|
||||||
RcVec3f bmax = geom.GetMeshBoundsMax();
|
RcVec3f bmax = geom.GetMeshBoundsMax();
|
||||||
RcRecast.CalcTileCount(bmin, bmax, CellSize, m_tileSize, m_tileSize, out tw, out th);
|
RcCommons.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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -18,7 +18,6 @@ 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;
|
||||||
|
@ -30,6 +29,7 @@ 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(RcIO.ReadFileIfFound("dungeon_all_tiles_tilecache.bin"));
|
using var msr = new MemoryStream(RcResources.Load("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);
|
||||||
const int maxStraightPath = 256;
|
int maxStraightPath = 256;
|
||||||
int options = 0;
|
int options = 0;
|
||||||
|
|
||||||
Span<DtStraightPath> pathStr = stackalloc DtStraightPath[maxStraightPath];
|
var pathStr = new List<DtStraightPath>();
|
||||||
query.FindStraightPath(startPos, endPos, path, path.Count, pathStr, out var npathStr, maxStraightPath, options);
|
query.FindStraightPath(startPos, endPos, path, ref pathStr, maxStraightPath, options);
|
||||||
Assert.That(npathStr, Is.EqualTo(8));
|
Assert.That(pathStr.Count, 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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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-2024 Choi Ikpil ikpil@naver.com
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -1,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,15 +7,15 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
<PackageReference Include="Moq" Version="4.20.72" />
|
<PackageReference Include="Moq" Version="4.20.70" />
|
||||||
<PackageReference Include="NUnit" Version="4.2.2" />
|
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||||
<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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,6 +24,9 @@ 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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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
|
||||||
|
@ -26,9 +25,10 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Test;
|
namespace DotRecast.Recast.Test;
|
||||||
|
|
||||||
using static RcRecast;
|
using static RcConstants;
|
||||||
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 = RcRecast.MarkWalkableTriangles(m_ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
|
int[] m_triareas = RcCommons.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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,7 +21,8 @@ using DotRecast.Core;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Test;
|
namespace DotRecast.Recast.Test;
|
||||||
|
|
||||||
using static RcRecast;
|
using static RcConstants;
|
||||||
|
|
||||||
|
|
||||||
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 };
|
||||||
RcRecast.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, unwalkable_tri, nt, areas);
|
RcCommons.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 };
|
||||||
RcRecast.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
|
RcCommons.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;
|
||||||
RcRecast.ClearUnwalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
|
RcCommons.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,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,6 +27,7 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Recast.Test;
|
namespace DotRecast.Recast.Test;
|
||||||
|
|
||||||
|
|
||||||
public class RecastTileMeshTest
|
public class RecastTileMeshTest
|
||||||
{
|
{
|
||||||
private const float m_cellSize = 0.3f;
|
private const float m_cellSize = 0.3f;
|
||||||
|
@ -70,29 +70,29 @@ public class RecastTileMeshTest
|
||||||
true, true, true,
|
true, true, true,
|
||||||
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
||||||
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 7, 8);
|
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 7, 8);
|
||||||
RcBuilderResult rcResult = builder.Build(geom, bcfg, false);
|
RcBuilderResult rcResult = builder.Build(geom, bcfg);
|
||||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(1));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(1));
|
||||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(5));
|
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(5));
|
||||||
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 6, 9);
|
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 6, 9);
|
||||||
rcResult = builder.Build(geom, bcfg, false);
|
rcResult = builder.Build(geom, bcfg);
|
||||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(2));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
|
||||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(7));
|
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(7));
|
||||||
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 2, 9);
|
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 2, 9);
|
||||||
rcResult = builder.Build(geom, bcfg, false);
|
rcResult = builder.Build(geom, bcfg);
|
||||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(2));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
|
||||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(9));
|
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(9));
|
||||||
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 4, 3);
|
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 4, 3);
|
||||||
rcResult = builder.Build(geom, bcfg, false);
|
rcResult = builder.Build(geom, bcfg);
|
||||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(3));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(3));
|
||||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(6));
|
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(6));
|
||||||
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 2, 8);
|
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 2, 8);
|
||||||
rcResult = builder.Build(geom, bcfg, false);
|
rcResult = builder.Build(geom, bcfg);
|
||||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(5));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(5));
|
||||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(17));
|
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(17));
|
||||||
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 0, 8);
|
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 0, 8);
|
||||||
rcResult = builder.Build(geom, bcfg, false);
|
rcResult = builder.Build(geom, bcfg);
|
||||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(6));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(6));
|
||||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(15));
|
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(15));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -138,27 +138,28 @@ public class RecastTileMeshTest
|
||||||
private void Build(IInputGeomProvider geom, RcBuilder builder, RcConfig cfg, int threads, bool validate)
|
private void Build(IInputGeomProvider geom, RcBuilder builder, RcConfig cfg, int threads, bool validate)
|
||||||
{
|
{
|
||||||
CancellationTokenSource cts = new CancellationTokenSource();
|
CancellationTokenSource cts = new CancellationTokenSource();
|
||||||
List<RcBuilderResult> tiles = builder.BuildTiles(geom, cfg, false, true, threads, Task.Factory, cts.Token);
|
List<RcBuilderResult> tiles = new();
|
||||||
|
var task = builder.BuildTilesAsync(geom, cfg, threads, tiles, Task.Factory, cts.Token);
|
||||||
if (validate)
|
if (validate)
|
||||||
{
|
{
|
||||||
RcBuilderResult rcResult = GetTile(tiles, 7, 8);
|
RcBuilderResult rcResult = GetTile(tiles, 7, 8);
|
||||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(1));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(1));
|
||||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(5));
|
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(5));
|
||||||
rcResult = GetTile(tiles, 6, 9);
|
rcResult = GetTile(tiles, 6, 9);
|
||||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(2));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
|
||||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(7));
|
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(7));
|
||||||
rcResult = GetTile(tiles, 2, 9);
|
rcResult = GetTile(tiles, 2, 9);
|
||||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(2));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
|
||||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(9));
|
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(9));
|
||||||
rcResult = GetTile(tiles, 4, 3);
|
rcResult = GetTile(tiles, 4, 3);
|
||||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(3));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(3));
|
||||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(6));
|
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(6));
|
||||||
rcResult = GetTile(tiles, 2, 8);
|
rcResult = GetTile(tiles, 2, 8);
|
||||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(5));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(5));
|
||||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(17));
|
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(17));
|
||||||
rcResult = GetTile(tiles, 0, 8);
|
rcResult = GetTile(tiles, 0, 8);
|
||||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(6));
|
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(6));
|
||||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(15));
|
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(15));
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -174,6 +175,6 @@ public class RecastTileMeshTest
|
||||||
|
|
||||||
private RcBuilderResult GetTile(List<RcBuilderResult> tiles, int x, int z)
|
private RcBuilderResult GetTile(List<RcBuilderResult> tiles, int x, int z)
|
||||||
{
|
{
|
||||||
return tiles.FirstOrDefault(tile => tile.TileX == x && tile.TileZ == z);
|
return tiles.FirstOrDefault(tile => tile.tileX == x && tile.tileZ == z);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
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,15 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
|
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
|
@ -1,169 +0,0 @@
|
||||||
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