Skip to content

Commit 5724269

Browse files
committed
[collision-solver] Avoid code duplication
1 parent 6942ba9 commit 5724269

File tree

2 files changed

+37
-46
lines changed

2 files changed

+37
-46
lines changed

include/inexor/vulkan-renderer/world/collision_solver.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,24 @@ class OctreeCollisionSolver {
1919
std::vector<std::pair<std::shared_ptr<world::Cube>, float>> m_collision_candidates{};
2020
std::shared_mutex m_collision_solver_mutex;
2121

22+
/// @brief Find all collisions between the given ray and the given octrees, sorted by increasing distance between
23+
/// the octree and the camera.
24+
/// @param worlds The octrees to check for collision
25+
/// @param position The start position of the ray
26+
/// @param direction The direction vector of the ray
27+
/// @return A vector of the found collisions. If no collisions were found, the vector is empty.
28+
[[nodiscard]] std::vector<RayCubeCollision<Cube>>
29+
find_all_ray_octree_collisions(const std::vector<std::shared_ptr<world::Cube>> &worlds, glm::vec3 position,
30+
glm::vec3 direction, bool find_only_one_collision = true);
31+
2232
public:
2333
/// @brief Default constructor.
2434
/// @param octree_count The number of octrees
2535
explicit OctreeCollisionSolver(std::size_t octree_count);
2636

37+
// TODO: Implement min/max collision distance if required.
38+
// TODO: Start sorting only after a certain number of worlds.
39+
2740
/// @brief Find a collision between a ray and an octree which is closest to the camera.
2841
/// @param worlds The octrees to check for collision
2942
/// @param position The start position of the ray

src/vulkan-renderer/world/collision_solver.cpp

Lines changed: 24 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -14,52 +14,10 @@ OctreeCollisionSolver::OctreeCollisionSolver(const std::size_t octree_count) {
1414
m_collision_candidates.reserve(octree_count);
1515
}
1616

17-
std::optional<RayCubeCollision<Cube>>
18-
OctreeCollisionSolver::find_ray_octree_collision(const std::vector<std::shared_ptr<world::Cube>> &worlds,
19-
const glm::vec3 position, const glm::vec3 direction) {
20-
21-
if (worlds.empty()) {
22-
return std::nullopt;
23-
}
24-
25-
// We need a critical section because we are modifying m_collision_candidates.
26-
std::scoped_lock lock(m_collision_solver_mutex);
27-
{
28-
for (const auto &world : worlds) {
29-
if (!is_bounding_box_and_bounding_sphere_hit(world, position, direction)) {
30-
continue;
31-
}
32-
33-
// TODO: Implement min/max collision distance if required.
34-
m_collision_candidates.emplace_back(std::make_pair(world, glm::distance2(position, direction)));
35-
}
36-
37-
// TODO: Start sorting only after a certain number of worlds.
38-
// Sort the octree collision candidates by increasing square of distance between cube center and camera.
39-
std::sort(m_collision_candidates.begin(), m_collision_candidates.end(),
40-
[](const auto &lhs, const auto &rhs) { return lhs.second < rhs.second; });
41-
42-
// Check for collision between camera ray and every octree whose bounding box and bounding sphere is hit in
43-
// order of increasing squared distance between camera and octree's center.
44-
for (const auto &collision_candidate : m_collision_candidates) {
45-
46-
// Do not make this const auto as we want to return it. This could prevent automatic move semantics.
47-
auto collision = ray_cube_collision_check(collision_candidate.first, position, direction);
48-
49-
if (collision) {
50-
return collision;
51-
}
52-
}
53-
}
54-
// End of critical section.
55-
56-
// No collision found with the bounding sphere or bounding box of any of the octrees.
57-
return std::nullopt;
58-
}
59-
6017
std::vector<RayCubeCollision<Cube>>
6118
OctreeCollisionSolver::find_all_ray_octree_collisions(const std::vector<std::shared_ptr<world::Cube>> &worlds,
62-
const glm::vec3 position, const glm::vec3 direction) {
19+
const glm::vec3 position, const glm::vec3 direction,
20+
bool find_only_one_collision) {
6321
if (worlds.empty()) {
6422
return {};
6523
}
@@ -76,11 +34,9 @@ OctreeCollisionSolver::find_all_ray_octree_collisions(const std::vector<std::sha
7634
continue;
7735
}
7836

79-
// TODO: Implement min/max collision distance if required.
8037
m_collision_candidates.emplace_back(std::make_pair(world, glm::distance2(position, direction)));
8138
}
8239

83-
// TODO: Start sorting only after a certain number of worlds.
8440
// Sort the octree collision candidates by increasing square of distance between cube center and camera.
8541
std::sort(m_collision_candidates.begin(), m_collision_candidates.end(),
8642
[](const auto &lhs, const auto &rhs) { return lhs.second < rhs.second; });
@@ -94,6 +50,10 @@ OctreeCollisionSolver::find_all_ray_octree_collisions(const std::vector<std::sha
9450

9551
if (collision) {
9652
found_collisions.emplace_back(collision.value());
53+
54+
if (find_only_one_collision) {
55+
return std::move(found_collisions);
56+
}
9757
}
9858
}
9959
}
@@ -102,4 +62,22 @@ OctreeCollisionSolver::find_all_ray_octree_collisions(const std::vector<std::sha
10262
return std::move(found_collisions);
10363
}
10464

65+
std::optional<RayCubeCollision<Cube>>
66+
OctreeCollisionSolver::find_ray_octree_collision(const std::vector<std::shared_ptr<world::Cube>> &worlds,
67+
const glm::vec3 position, const glm::vec3 direction) {
68+
const auto result = find_all_ray_octree_collisions(worlds, position, direction, true);
69+
70+
if (!result.empty()) {
71+
return result[0];
72+
}
73+
74+
return std::nullopt;
75+
}
76+
77+
std::vector<RayCubeCollision<Cube>>
78+
OctreeCollisionSolver::find_all_ray_octree_collisions(const std::vector<std::shared_ptr<world::Cube>> &worlds,
79+
const glm::vec3 position, const glm::vec3 direction) {
80+
return find_all_ray_octree_collisions(worlds, position, direction, false);
81+
}
82+
10583
} // namespace inexor::vulkan_renderer::world

0 commit comments

Comments
 (0)