Skip to content

Commit

Permalink
feat(geometry): add frustum and intersection functions
Browse files Browse the repository at this point in the history
  • Loading branch information
mkuritsu committed Jan 26, 2025
1 parent da5f5e3 commit 08a9ff8
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 3 deletions.
1 change: 1 addition & 0 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ set(CUBOS_CORE_SOURCE

"src/geom/box.cpp"
"src/geom/capsule.cpp"
"src/geom/frustum.cpp"
"src/geom/intersections.cpp"
"src/geom/plane.cpp"
"src/geom/utils.cpp"
Expand Down
35 changes: 35 additions & 0 deletions core/include/cubos/core/geom/frustum.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/// @file
/// @brief Class @ref cubos::core::geom::Frustum.
/// @ingroup core-geom

#include <cubos/core/api.hpp>
#include <cubos/core/geom/plane.hpp>
#include <cubos/core/reflection/reflect.hpp>

namespace cubos::core::geom
{
/// @brief Represents a camera frustum.
/// @ingroup core-geom
struct CUBOS_CORE_API Frustum
{
CUBOS_REFLECT;

/// @brief Top plane of Frustum.
Plane top;

/// @brief Right plane of Frustum.
Plane right;

/// @brief Bottom plane of Frustum.
Plane bottom;

/// @brief Left plane of Frustum.
Plane left;

/// @brief Near plane of Frustum.
Plane near;

/// @brief Far plane of Frustum.
Plane far;
};
} // namespace cubos::core::geom
20 changes: 17 additions & 3 deletions core/include/cubos/core/geom/intersections.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

#include <cubos/core/ecs/entity/entity.hpp>
#include <cubos/core/geom/box.hpp>
#include <cubos/core/geom/capsule.hpp>
#include <cubos/core/geom/frustum.hpp>
#include <cubos/core/geom/plane.hpp>
#include <cubos/core/geom/polygonal_feature.hpp>
#include <cubos/core/reflection/reflect.hpp>
Expand All @@ -34,14 +36,26 @@ namespace cubos::core::geom
CUBOS_CORE_API bool intersects(const Box& box1, const glm::mat4& localToWorld1, const Box& box2,
const glm::mat4& localToWorld2, Intersection& intersect);

/// @brief Computes the intersection between a frustum and a box.
/// @param box Box shape of the entity.
/// @param localToWorld Local to world matrix of the entity.
/// @return True if there's intersection, false otherwise.
CUBOS_CORE_API bool intersects(const Frustum& frustum, const Box& box, const glm::mat4& localToWorld);

/// @brief Computes the intersection between a frustum and a capsule.
/// @param capsule Capsule shape of the entity.
/// @param localToWorld Local to world matrix of the entity.
/// @return True if there's intersection, false otherwise.
CUBOS_CORE_API bool intersects(const Frustum& frustum, const Capsule& capsule, const glm::mat4& localToWorld);

/// @brief Performs the Sutherland-Hodgman Clipping algorithm.
/// @param polygon The polygon to perform the clipping on.
/// @param numClipPlanes Number of cliping planes.
/// @param clipPlanes Clipping planes
/// @param removeNotClipToPlane Whether to remove the points if they're outside the plane.
CUBOS_CORE_API void sutherlandHodgmanClipping(PolygonalFeature& polygon, int numClipPlanes,
const cubos::core::geom::Plane* clipPlanes,
bool removeNotClipToPlane);
CUBOS_CORE_API
void sutherlandHodgmanClipping(PolygonalFeature& polygon, int numClipPlanes,
const cubos::core::geom::Plane* clipPlanes, bool removeNotClipToPlane);

/// @brief Compute the intersection between a plane and an edge.
/// @param plane The plane.
Expand Down
6 changes: 6 additions & 0 deletions core/include/cubos/core/geom/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ namespace cubos::core::geom
/// @return True is the point is on the plane or closer, false otherwise.
CUBOS_CORE_API bool pointInPlane(const glm::vec3& point, const cubos::core::geom::Plane& plane);

/// @brief Computes the signed distance from thene plane to a point.
/// @param point The position of the point in world coordinates.
/// @param plane The plane to use.
/// @return The signed distance.
CUBOS_CORE_API float pointDistanceToPlane(const glm::vec3& point, const cubos::core::geom::Plane& plane);

/// @brief Computes the vertex furthest along the axis.
/// @param vertices Array of vertices.
/// @param localAxis The direction of the axis in local coordinates.
Expand Down
20 changes: 20 additions & 0 deletions core/src/geom/frustum.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <cubos/core/geom/frustum.hpp>
#include <cubos/core/reflection/external/primitives.hpp>
#include <cubos/core/reflection/traits/constructible.hpp>
#include <cubos/core/reflection/traits/fields.hpp>
#include <cubos/core/reflection/type.hpp>

CUBOS_REFLECT_IMPL(cubos::core::geom::Frustum)
{
using namespace core::reflection;

return Type::create("cubos::core::geom::Frustum")
.with(ConstructibleTrait::typed<Frustum>().withBasicConstructors().build())
.with(FieldsTrait()
.withField("top", &Frustum::top)
.withField("right", &Frustum::right)
.withField("bottom", &Frustum::bottom)
.withField("left", &Frustum::left)
.withField("near", &Frustum::near)
.withField("far", &Frustum::far));
}
30 changes: 30 additions & 0 deletions core/src/geom/intersections.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <algorithm>
#include <array>
#include <limits>

#include <glm/glm.hpp>
Expand Down Expand Up @@ -150,6 +152,34 @@ bool cubos::core::geom::intersects(const Box& box1, const glm::mat4& localToWorl
return true;
}

bool cubos::core::geom::intersects(const Frustum& frustum, const Box& box, const glm::mat4& localToWorld)
{
std::array<glm::vec3, 8> corners;
box.corners(corners.data());
std::ranges::transform(corners, corners.begin(),
[localToWorld](glm::vec3& corner) { return localToWorld * glm::vec4{corner, 1.0F}; });
auto planes = {&frustum.top, &frustum.right, &frustum.bottom, &frustum.left, &frustum.near, &frustum.far};
return std::ranges::any_of(corners, [planes](const glm::vec3 corner) {
return std::ranges::all_of(
planes, [corner](const Plane* plane) { return pointDistanceToPlane(corner, *plane) > 0.0F; });
});
}

bool cubos::core::geom::intersects(const Frustum& frustum, const Capsule& capsule, const glm::mat4& localToWorld)
{
// capsule is a sphere
if (capsule.length == 0.0F)
{
glm::vec3 center = localToWorld * glm::vec4{0.0F, 0.0F, 0.0F, 1.0F};
auto planes = {&frustum.top, &frustum.right, &frustum.bottom, &frustum.left, &frustum.near, &frustum.far};
return std::ranges::all_of(planes, [center, capsule](const Plane* plane) {
return pointDistanceToPlane(center, *plane) + capsule.radius >= 0.0F;
});
}

return intersects(frustum, capsule.aabb().box(), localToWorld);
}

void cubos::core::geom::sutherlandHodgmanClipping(PolygonalFeature& polygon, int numClipPlanes,
const cubos::core::geom::Plane* clipPlanes, bool removeNotClipToPlane)
{
Expand Down
5 changes: 5 additions & 0 deletions core/src/geom/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ bool cubos::core::geom::pointInPlane(const glm::vec3& point, const cubos::core::
return glm::dot(point, plane.normal) + plane.d >= 0.0F;
}

float cubos::core::geom::pointDistanceToPlane(const glm::vec3& point, const cubos::core::geom::Plane& plane)
{
return glm::dot(plane.normal, point) - plane.d;
}

int cubos::core::geom::getMaxVertexInAxis(const int numVertices, const glm::vec3 vertices[], const glm::vec3& localAxis)
{
float maxValue = glm::dot(localAxis, vertices[0]);
Expand Down

0 comments on commit 08a9ff8

Please sign in to comment.