@@ -200,6 +200,9 @@ void Application::load_octree_geometry(bool initialize) {
200200 m_worlds.push_back (
201201 world::create_random_world (2 , {10 .0f , 0 .0f , 0 .0f }, initialize ? std::optional (60 ) : std::nullopt ));
202202
203+ // Reserve memory for collision checks
204+ m_collision_candidates.reserve (m_worlds.size ());
205+
203206 m_octree_vertices.clear ();
204207 for (const auto &world : m_worlds) {
205208 for (const auto &polygons : world->polygons (true )) {
@@ -575,22 +578,49 @@ void Application::process_mouse_input() {
575578}
576579
577580void Application::check_octree_collisions () {
578- // Check for collision between camera ray and every octree
579- for (const auto &world : m_worlds) {
580- const auto collision = ray_cube_collision_check (*world, m_camera->position (), m_camera->front ());
581+ std::size_t candidate_count = 0 ;
582+
583+ for (std::size_t i = 0 ; i < m_worlds.size (); i++) {
584+ if (!ray_cube_collision_check (*m_worlds[i], m_camera->position (), m_camera->front ())) {
585+ continue ;
586+ }
581587
582- if (collision) {
583- const auto intersection = collision.value ().intersection ();
584- const auto face_normal = collision.value ().face ();
585- const auto corner = collision.value ().corner ();
586- const auto edge = collision.value ().edge ();
588+ // Calculate the square of the distance between the octree root's center and the camera
589+ const float squared_distance = glm::distance2 (m_worlds[i]->center (), m_camera->position ());
587590
588- spdlog::trace (" pos {} {} {} | face {} {} {} | corner {} {} {} | edge {} {} {}" , intersection.x ,
589- intersection.y , intersection.z , face_normal.x , face_normal.y , face_normal.z , corner.x ,
590- corner.y , corner.z , edge.x , edge.y , edge.z );
591+ // We use the current candidate count as index for filling the vector
592+ m_collision_candidates[candidate_count] = std::make_pair (i, squared_distance);
591593
592- // Break after one collision.
593- break ;
594+ // Increment candidate count
595+ candidate_count++;
596+ }
597+
598+ // Sort candidates for collisions between camera ray and root octrees by increasing square of the distance between
599+ // camera and the root octree's center
600+ std::sort (m_collision_candidates.begin (), m_collision_candidates.end (),
601+ [](const auto &lhs, const auto &rhs) { return lhs.second < rhs.second ; });
602+
603+ // Loop through all collision candidates in order of increasing square of distance between camera and otree' center
604+ // Note that we are only looping through every element of m_worlds in the worst case
605+ // This would be the case if all root octrees are in collision with the camera ray
606+ for (std::size_t candidate_index = 0 ; candidate_index < candidate_count; candidate_index++) {
607+ if (const auto collision = ray_cube_collision_check (*m_worlds[m_collision_candidates[candidate_index].first ],
608+ m_camera->position (), m_camera->front ())) {
609+ if (collision) {
610+ const auto &coll = collision.value ();
611+ const auto intersection = coll.intersection ();
612+ const auto face_normal = coll.face ();
613+ const auto corner = coll.corner ();
614+ const auto edge = coll.edge ();
615+
616+ spdlog::trace (" octree #{} | pos {} {} {} | face {} {} {} | corner {} {} {} | edge {} {} {}" ,
617+ m_collision_candidates[candidate_index].first , intersection.x , intersection.y ,
618+ intersection.z , face_normal.x , face_normal.y , face_normal.z , corner.x , corner.y , corner.z ,
619+ edge.x , edge.y , edge.z );
620+
621+ // Stop after one collision
622+ break ;
623+ }
594624 }
595625 }
596626}
0 commit comments