@@ -45,10 +45,26 @@ RWLock NavMeshGenerator3D::generator_parsers_rwlock;
4545bool NavMeshGenerator3D::use_threads = true ;
4646bool NavMeshGenerator3D::baking_use_multiple_threads = true ;
4747bool NavMeshGenerator3D::baking_use_high_priority_threads = true ;
48- HashSet <Ref<NavigationMesh>> NavMeshGenerator3D::baking_navmeshes;
48+ HashMap <Ref<NavigationMesh>, NavMeshGenerator3D::NavMeshGeneratorTask3D * > NavMeshGenerator3D::baking_navmeshes;
4949HashMap<WorkerThreadPool::TaskID, NavMeshGenerator3D::NavMeshGeneratorTask3D *> NavMeshGenerator3D::generator_tasks;
5050LocalVector<NavMeshGeometryParser3D *> NavMeshGenerator3D::generator_parsers;
5151
52+ static const char *_navmesh_bake_state_msgs[(size_t )NavMeshGenerator3D::NavMeshBakeState::BAKE_STATE_MAX] = {
53+ " " ,
54+ " Setting up configuration..." ,
55+ " Calculating grid size..." ,
56+ " Creating heightfield..." ,
57+ " Marking walkable triangles..." ,
58+ " Constructing compact heightfield..." , // step 5
59+ " Eroding walkable area..." ,
60+ " Sample partitioning..." ,
61+ " Creating contours..." ,
62+ " Creating polymesh..." ,
63+ " Converting to native navigation mesh..." , // step 10
64+ " Baking cleanup..." ,
65+ " Baking finished." ,
66+ };
67+
5268NavMeshGenerator3D *NavMeshGenerator3D::get_singleton () {
5369 return singleton;
5470}
@@ -158,10 +174,15 @@ void NavMeshGenerator3D::bake_from_source_geometry_data(Ref<NavigationMesh> p_na
158174 ERR_FAIL_MSG (" NavigationMesh is already baking. Wait for current bake to finish." );
159175 }
160176 baking_navmesh_mutex.lock ();
161- baking_navmeshes.insert (p_navigation_mesh);
177+ NavMeshGeneratorTask3D generator_task;
178+ baking_navmeshes.insert (p_navigation_mesh, &generator_task);
162179 baking_navmesh_mutex.unlock ();
163180
164- generator_bake_from_source_geometry_data (p_navigation_mesh, p_source_geometry_data);
181+ generator_task.navigation_mesh = p_navigation_mesh;
182+ generator_task.source_geometry_data = p_source_geometry_data;
183+ generator_task.status = NavMeshGeneratorTask3D::TaskStatus::BAKING_STARTED;
184+
185+ generator_bake_from_source_geometry_data (&generator_task);
165186
166187 baking_navmesh_mutex.lock ();
167188 baking_navmeshes.erase (p_navigation_mesh);
@@ -197,16 +218,16 @@ void NavMeshGenerator3D::bake_from_source_geometry_data_async(Ref<NavigationMesh
197218 return ;
198219 }
199220 baking_navmesh_mutex.lock ();
200- baking_navmeshes.insert (p_navigation_mesh);
221+ NavMeshGeneratorTask3D *generator_task = memnew (NavMeshGeneratorTask3D);
222+ baking_navmeshes.insert (p_navigation_mesh, generator_task);
201223 baking_navmesh_mutex.unlock ();
202224
203- MutexLock generator_task_lock (generator_task_mutex);
204- NavMeshGeneratorTask3D *generator_task = memnew (NavMeshGeneratorTask3D);
205225 generator_task->navigation_mesh = p_navigation_mesh;
206226 generator_task->source_geometry_data = p_source_geometry_data;
207227 generator_task->callback = p_callback;
208228 generator_task->status = NavMeshGeneratorTask3D::TaskStatus::BAKING_STARTED;
209229 generator_task->thread_task_id = WorkerThreadPool::get_singleton ()->add_native_task (&NavMeshGenerator3D::generator_thread_bake, generator_task, NavMeshGenerator3D::baking_use_high_priority_threads, SNAME (" NavMeshGeneratorBake3D" ));
230+ MutexLock generator_task_lock (generator_task_mutex);
210231 generator_tasks.insert (generator_task->thread_task_id , generator_task);
211232}
212233
@@ -215,10 +236,21 @@ bool NavMeshGenerator3D::is_baking(Ref<NavigationMesh> p_navigation_mesh) {
215236 return baking_navmeshes.has (p_navigation_mesh);
216237}
217238
239+ String NavMeshGenerator3D::get_baking_state_msg (Ref<NavigationMesh> p_navigation_mesh) {
240+ String bake_state_msg;
241+ MutexLock baking_navmesh_lock (baking_navmesh_mutex);
242+ if (baking_navmeshes.has (p_navigation_mesh)) {
243+ bake_state_msg = _navmesh_bake_state_msgs[baking_navmeshes[p_navigation_mesh]->bake_state ];
244+ } else {
245+ bake_state_msg = _navmesh_bake_state_msgs[NavMeshBakeState::BAKE_STATE_NONE];
246+ }
247+ return bake_state_msg;
248+ }
249+
218250void NavMeshGenerator3D::generator_thread_bake (void *p_arg) {
219251 NavMeshGeneratorTask3D *generator_task = static_cast <NavMeshGeneratorTask3D *>(p_arg);
220252
221- generator_bake_from_source_geometry_data (generator_task-> navigation_mesh , generator_task-> source_geometry_data );
253+ generator_bake_from_source_geometry_data (generator_task);
222254
223255 generator_task->status = NavMeshGeneratorTask3D::TaskStatus::BAKING_FINISHED;
224256}
@@ -269,7 +301,10 @@ void NavMeshGenerator3D::generator_parse_source_geometry_data(const Ref<Navigati
269301 }
270302}
271303
272- void NavMeshGenerator3D::generator_bake_from_source_geometry_data (Ref<NavigationMesh> p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data) {
304+ void NavMeshGenerator3D::generator_bake_from_source_geometry_data (NavMeshGeneratorTask3D *p_generator_task) {
305+ Ref<NavigationMesh> p_navigation_mesh = p_generator_task->navigation_mesh ;
306+ const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data = p_generator_task->source_geometry_data ;
307+
273308 if (p_navigation_mesh.is_null () || p_source_geometry_data.is_null ()) {
274309 return ;
275310 }
@@ -294,10 +329,7 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
294329 rcPolyMeshDetail *detail_mesh = nullptr ;
295330 rcContext ctx;
296331
297- // added to keep track of steps, no functionality right now
298- String bake_state = " " ;
299-
300- bake_state = " Setting up Configuration..." ; // step #1
332+ p_generator_task->bake_state = NavMeshBakeState::BAKE_STATE_CONFIGURATION; // step #1
301333
302334 const float *verts = source_geometry_vertices.ptr ();
303335 const int nverts = source_geometry_vertices.size () / 3 ;
@@ -373,7 +405,7 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
373405 cfg.bmax [2 ] = cfg.bmin [2 ] + baking_aabb.size [2 ];
374406 }
375407
376- bake_state = " Calculating grid size... " ; // step #2
408+ p_generator_task-> bake_state = NavMeshBakeState::BAKE_STATE_CALC_GRID_SIZE ; // step #2
377409 rcCalcGridSize (cfg.bmin , cfg.bmax , cfg.cs , &cfg.width , &cfg.height );
378410
379411 // ~30000000 seems to be around sweetspot where Editor baking breaks
@@ -387,13 +419,13 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
387419 return ;
388420 }
389421
390- bake_state = " Creating heightfield... " ; // step #3
422+ p_generator_task-> bake_state = NavMeshBakeState::BAKE_STATE_CREATE_HEIGHTFIELD ; // step #3
391423 hf = rcAllocHeightfield ();
392424
393425 ERR_FAIL_NULL (hf);
394426 ERR_FAIL_COND (!rcCreateHeightfield (&ctx, *hf, cfg.width , cfg.height , cfg.bmin , cfg.bmax , cfg.cs , cfg.ch ));
395427
396- bake_state = " Marking walkable triangles... " ; // step #4
428+ p_generator_task-> bake_state = NavMeshBakeState::BAKE_STATE_MARK_WALKABLE_TRIANGLES ; // step #4
397429 {
398430 Vector<unsigned char > tri_areas;
399431 tri_areas.resize (ntris);
@@ -416,7 +448,7 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
416448 rcFilterWalkableLowHeightSpans (&ctx, cfg.walkableHeight , *hf);
417449 }
418450
419- bake_state = " Constructing compact heightfield... " ; // step #5
451+ p_generator_task-> bake_state = NavMeshBakeState::BAKE_STATE_CONSTRUCT_COMPACT_HEIGHTFIELD ; // step #5
420452
421453 chf = rcAllocCompactHeightfield ();
422454
@@ -443,7 +475,7 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
443475 }
444476 }
445477
446- bake_state = " Eroding walkable area... " ; // step #6
478+ p_generator_task-> bake_state = NavMeshBakeState::BAKE_STATE_ERODE_WALKABLE_AREA ; // step #6
447479
448480 ERR_FAIL_COND (!rcErodeWalkableArea (&ctx, cfg.walkableRadius , *chf));
449481
@@ -464,7 +496,7 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
464496 }
465497 }
466498
467- bake_state = " Partitioning... " ; // step #7
499+ p_generator_task-> bake_state = NavMeshBakeState::BAKE_STATE_SAMPLE_PARTITIONING ; // step #7
468500
469501 if (p_navigation_mesh->get_sample_partition_type () == NavigationMesh::SAMPLE_PARTITION_WATERSHED) {
470502 ERR_FAIL_COND (!rcBuildDistanceField (&ctx, *chf));
@@ -475,14 +507,14 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
475507 ERR_FAIL_COND (!rcBuildLayerRegions (&ctx, *chf, cfg.borderSize , cfg.minRegionArea ));
476508 }
477509
478- bake_state = " Creating contours... " ; // step #8
510+ p_generator_task-> bake_state = NavMeshBakeState::BAKE_STATE_CREATING_CONTOURS ; // step #8
479511
480512 cset = rcAllocContourSet ();
481513
482514 ERR_FAIL_NULL (cset);
483515 ERR_FAIL_COND (!rcBuildContours (&ctx, *chf, cfg.maxSimplificationError , cfg.maxEdgeLen , *cset));
484516
485- bake_state = " Creating polymesh... " ; // step #9
517+ p_generator_task-> bake_state = NavMeshBakeState::BAKE_STATE_CREATING_POLYMESH ; // step #9
486518
487519 poly_mesh = rcAllocPolyMesh ();
488520 ERR_FAIL_NULL (poly_mesh);
@@ -497,7 +529,7 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
497529 rcFreeContourSet (cset);
498530 cset = nullptr ;
499531
500- bake_state = " Converting to native navigation mesh... " ; // step #10
532+ p_generator_task-> bake_state = NavMeshBakeState::BAKE_STATE_CONVERTING_NATIVE_NAVMESH ; // step #10
501533
502534 Vector<Vector3> nav_vertices;
503535 Vector<Vector<int >> nav_polygons;
@@ -544,14 +576,14 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
544576
545577 p_navigation_mesh->set_data (nav_vertices, nav_polygons);
546578
547- bake_state = " Cleanup... " ; // step #11
579+ p_generator_task-> bake_state = NavMeshBakeState::BAKE_STATE_BAKE_CLEANUP ; // step #11
548580
549581 rcFreePolyMesh (poly_mesh);
550582 poly_mesh = nullptr ;
551583 rcFreePolyMeshDetail (detail_mesh);
552584 detail_mesh = nullptr ;
553585
554- bake_state = " Baking finished. " ; // step #12
586+ p_generator_task-> bake_state = NavMeshBakeState::BAKE_STATE_BAKE_FINISHED ; // step #12
555587}
556588
557589bool NavMeshGenerator3D::generator_emit_callback (const Callable &p_callback) {
0 commit comments