DotRecast icon indicating copy to clipboard operation
DotRecast copied to clipboard

How do I dynamically create an initial DtVoxelFile / DtDynamicNavMesh?

Open bryanedds opened this issue 9 months ago • 4 comments

Here's the code I'm currently modifying in an attempt to go from using a static DtNavMesh to DtDynamicNavMesh (F#) -

https://github.com/bryanedds/Nu/blob/nav-dynamic/Nu/Nu/World/WorldScreen.fs#L458-L494

            // attempt to execute 3d navigation mesh construction steps
            match geomProviderOpt with
            | Some geomProvider ->
                let rcConfig =
                    RcConfig
                        (true, 32, 32, 1,
                         config.PartitionType,
                         config.CellSize, config.CellHeight,
                         config.AgentSlopeMax, config.AgentHeight, config.AgentRadius, config.AgentClimbMax,
                         single config.RegionSizeMin, single config.RegionSizeMerge,
                         config.EdgeLengthMax, config.EdgeErrorMax,
                         config.VertsPerPolygon, config.DetailSampleDistance, config.DetailSampleErrorMax,
                         config.FilterLowHangingObstacles, config.FilterLedgeSpans, config.FilterWalkableLowHeightSpans,
                         SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true)
                let rcBuilderConfig = RcBuilderConfig (rcConfig, geomProvider.GetMeshBoundsMin (), geomProvider.GetMeshBoundsMax ())
                let rcBuilder = RcBuilder ()
                let rcBuilderResult = rcBuilder.Build (geomProvider, rcBuilderConfig, true) // NOTE: keeping intermediate results now! TODO: P0: try to get rid of any unnecessary intermediate results data!
                if notNull rcBuilderResult.MeshDetail then // NOTE: not sure why, but null here seems to be an indication of nav mesh build failure.
                    let navBuilderResultData = NavBuilderResultData.make rcBuilderResult
                    let voxelFile = DtVoxelFile.From (rcConfig, List [rcBuilderResult])
                    let dtNavMesh = DtDynamicNavMesh voxelFile
                    dtNavMesh.Build Task.Factory |> ignore<bool>
                    let dtQuery = DtNavMeshQuery (dtNavMesh.NavMesh ())
                    Some (navBuilderResultData, dtNavMesh, dtQuery)

                    //let dtCreateParams = DemoNavMeshBuilder.GetNavMeshCreateParams (geomProvider, config.CellSize, config.CellHeight, config.AgentHeight, config.AgentRadius, config.AgentClimbMax, rcBuilderResult)
                    //match DtNavMeshBuilder.CreateNavMeshData dtCreateParams with
                    //| null -> None // some sort of argument issue
                    //| dtMeshData ->
                    //    DemoNavMeshBuilder.UpdateAreaAndFlags dtMeshData |> ignore<DtMeshData> // ignoring flow-syntax
                    //    let dtNavMesh = DtNavMesh ()
                    //    if dtNavMesh.Init (dtMeshData, 6, 0) = DtStatus.DT_SUCCESS then // TODO: introduce constant?
                    //        let dtQuery = DtNavMeshQuery dtNavMesh
                    //        Some (navBuilderResultData, dtNavMesh, dtQuery)
                    //    else None

                else None

The issue appears to be that rcBuilderResult.MeshDetail is always null and thus I can't proceed.

All of the example code I find merely loads the data from a file on disk but doesn't seem to show how to create that file on disk in the first place :) Here I'm just attempting to create the whole thing dynamically at runtime, but if using DtDynamicNavMesh means I have to go to disk temporarily, I'm willing to do that too. I just need to know how to get my initial static scene that I build in my custom engine's editor into a DtDynamicNavMesh. Currently I have no way to proceed other than reversing the intent from reading lots of Dotrecast and trial and error.

bryanedds avatar Feb 23 '25 14:02 bryanedds