Skip to content

Commit

Permalink
Added Cone v Point intersect funcs. #24
Browse files Browse the repository at this point in the history
  • Loading branch information
MStachowicz committed Nov 19, 2023
1 parent 1a078be commit 7089496
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 8 deletions.
31 changes: 31 additions & 0 deletions source/Geometry/Intersect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,13 @@ namespace Geometry
// Ray intersects all 3 slabs. Return point intersection_point and length_along_ray
return Geometry::Point(ray.m_start + (ray.m_direction * farthestEntry));
}
std::optional<Point> get_intersection(const Cone& cone, const Point& point)
{
if (intersecting(cone, point))
return point;
else
return std::nullopt;
}
std::optional<Geometry::Point> get_intersection(const Line& line, const Triangle& triangle)
{
// Identical to the above function but uses u, v, w to determine the intersection point to return.
Expand Down Expand Up @@ -409,6 +416,30 @@ namespace Geometry
// Ray intersects all 3 slabs.
return true;
}
bool intersecting(const Cone& cone, const Point& point)
{
auto cone_height = glm::distance(cone.m_base, cone.m_top);

if (cone_height == 0.0f) // 0 height cone has no volume, so point cannot be inside it.
return false;

auto cone_direction = glm::normalize(cone.m_top - cone.m_base);
// Project tip_to_p onto the cone axis to get the point's distance along the axis
auto point_distance_along_axis = glm::dot(point.m_position - cone.m_base, cone_direction);

// Is the point orthogonally within the bounds of the cone's axis.
if (point_distance_along_axis >= 0.f && point_distance_along_axis <= cone_height)
{
// The distance from the point to the cone's axis.
auto orthogonal_distance = glm::distance(point.m_position, cone.m_base + (cone_direction * point_distance_along_axis));
// The radius of the cone at the point's distance along the axis.
auto cone_radius = cone.m_base_radius * ((cone_height - point_distance_along_axis) / cone_height);
// The point is inside the cone if the orthogonal distance is less than the cone's radius at that point along it's axis.
return orthogonal_distance <= cone_radius;
}
else
return false; // Outside the cone
}
bool intersecting(const Line& line, const Triangle& triangle)
{
// Below works for a double-sided triangle (both CW or CCW depending on which side it is viewed),
Expand Down
4 changes: 2 additions & 2 deletions source/Geometry/Intersect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ namespace Geometry
inline std::optional<Point> get_intersection(const Cone& cone, const Line& line) { LOG_WARN("[INTERSECT] Not implemented Cone v Line"); return std::nullopt; } // #TODO
inline std::optional<Point> get_intersection(const Cone& cone, const LineSegment& lineSegment) { LOG_WARN("[INTERSECT] Not implemented Cone v LineSegment"); return std::nullopt; } // #TODO
inline std::optional<Point> get_intersection(const Cone& cone, const Plane& plane) { LOG_WARN("[INTERSECT] Not implemented Cone v Plane"); return std::nullopt; } // #TODO
inline std::optional<Point> get_intersection(const Cone& cone, const Point& point) { LOG_WARN("[INTERSECT] Not implemented Cone v Point"); return std::nullopt; } // #TODO
std::optional<Point> get_intersection(const Cone& cone, const Point& point); // IMPLEMENTED
inline std::optional<Point> get_intersection(const Cone& cone, const Quad& quad) { LOG_WARN("[INTERSECT] Not implemented Cone v Quad"); return std::nullopt; } // #TODO
inline std::optional<Point> get_intersection(const Cone& cone, const Ray& ray) { LOG_WARN("[INTERSECT] Not implemented Cone v Ray"); return std::nullopt; } // #TODO
inline std::optional<Point> get_intersection(const Cone& cone, const Sphere& sphere) { LOG_WARN("[INTERSECT] Not implemented Cone v Sphere"); return std::nullopt; } // #TODO
Expand Down Expand Up @@ -294,7 +294,7 @@ namespace Geometry
inline bool intersecting(const Cone& cone, const Line& line) { return get_intersection(cone, line).has_value(); } // Expensive get_intersection call for lack of bespoke intersection function #TODO
inline bool intersecting(const Cone& cone, const LineSegment& lineSegment) { return get_intersection(cone, lineSegment).has_value(); } // Expensive get_intersection call for lack of bespoke intersection function #TODO
inline bool intersecting(const Cone& cone, const Plane& plane) { return get_intersection(cone, plane).has_value(); } // Expensive get_intersection call for lack of bespoke intersection function #TODO
inline bool intersecting(const Cone& cone, const Point& point) { return get_intersection(cone, point).has_value(); } // Expensive get_intersection call for lack of bespoke intersection function #TODO
bool intersecting(const Cone& cone, const Point& point); // IMPLEMENTED
inline bool intersecting(const Cone& cone, const Quad& quad) { return get_intersection(cone, quad).has_value(); } // Expensive get_intersection call for lack of bespoke intersection function #TODO
inline bool intersecting(const Cone& cone, const Ray& ray) { return get_intersection(cone, ray).has_value(); } // Expensive get_intersection call for lack of bespoke intersection function #TODO
inline bool intersecting(const Cone& cone, const Sphere& sphere) { return get_intersection(cone, sphere).has_value(); } // Expensive get_intersection call for lack of bespoke intersection function #TODO
Expand Down
83 changes: 77 additions & 6 deletions source/Test/Tests/GeometryTester.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#include "GeometryTester.hpp"

// GEOMETRY
#include "Intersect.hpp"
#include "AABB.hpp"
#include "Triangle.hpp"
#include "Geometry/Intersect.hpp"
#include "Geometry/AABB.hpp"
#include "Geometry/Triangle.hpp"
#include "Geometry/Frustrum.hpp"
#include "Geometry/Cone.hpp"

#include "Stopwatch.hpp"
#include "Utility.hpp"
#include "Utility/Stopwatch.hpp"
#include "Utility/Utility.hpp"

#include "glm/glm.hpp"
#include "glm/mat4x4.hpp"
Expand Down Expand Up @@ -509,6 +509,77 @@ namespace Test
CHECK_EQUAL(intersection->m_position, point_on_min_edge.m_position, "Point on min edge of AABB intersection position");
}
}
{// Point v Cone
const auto cone = Geometry::Cone(glm::vec3(0.f), glm::vec3(0.f, 1.f, 0.f), 1.f);

{// Test point inside the cone
auto point_inside = Geometry::Point(glm::vec3(0.f, 0.5f, 0.f));

auto inside = Geometry::intersecting(point_inside, cone);
CHECK_TRUE(inside, "Point inside cone");
CHECK_EQUAL(Geometry::intersecting(point_inside, cone), Geometry::intersecting(cone, point_inside), "Point inside cone overload");

auto intersection = Geometry::get_intersection(point_inside, cone);
CHECK_TRUE(intersection.has_value(), "Point inside cone intersection");
CHECK_EQUAL(Geometry::get_intersection(point_inside, cone), Geometry::get_intersection(cone, point_inside), "Point inside cone intersection overload");

if (intersection.has_value())
CHECK_EQUAL(intersection->m_position, point_inside.m_position, "Point inside cone intersection position");
}
{// Test point outside the cone
auto point_outside = Geometry::Point(glm::vec3(0.f, 1.5f, 0.f));

auto outside = Geometry::intersecting(point_outside, cone);
CHECK_TRUE(!outside, "Point outside cone");
CHECK_EQUAL(Geometry::intersecting(point_outside, cone), Geometry::intersecting(cone, point_outside), "Point outside cone overload");

auto intersection = Geometry::get_intersection(point_outside, cone);
CHECK_TRUE(!intersection.has_value(), "Point outside cone intersection");
CHECK_EQUAL(Geometry::get_intersection(point_outside, cone), Geometry::get_intersection(cone, point_outside), "Point outside cone intersection overload");
}
{// Test point on the cone surface (top)
auto point_on_surface = Geometry::Point(glm::vec3(0.f, 1.f, 0.f));

auto on_surface = Geometry::intersecting(point_on_surface, cone);
CHECK_TRUE(on_surface, "Point on surface of cone (top)");
CHECK_EQUAL(Geometry::intersecting(point_on_surface, cone), Geometry::intersecting(cone, point_on_surface), "Point on surface of cone (top) overload");

auto intersection = Geometry::get_intersection(point_on_surface, cone);
CHECK_TRUE(intersection.has_value(), "Point on surface of cone (top) intersection");
CHECK_EQUAL(Geometry::get_intersection(point_on_surface, cone), Geometry::get_intersection(cone, point_on_surface), "Point on surface of cone (top) intersection overload");

if (intersection.has_value())
CHECK_EQUAL(intersection->m_position, point_on_surface.m_position, "Point on surface of cone (top) intersection position");
}
{// Test point on the cone surface (base)
auto point_on_surface = Geometry::Point(glm::vec3(0.f));

auto on_surface = Geometry::intersecting(point_on_surface, cone);
CHECK_TRUE(on_surface, "Point on surface of cone (base)");
CHECK_EQUAL(Geometry::intersecting(point_on_surface, cone), Geometry::intersecting(cone, point_on_surface), "Point on surface of cone (base) overload");

auto intersection = Geometry::get_intersection(point_on_surface, cone);
CHECK_TRUE(intersection.has_value(), "Point on surface of cone (base) intersection");
CHECK_EQUAL(Geometry::get_intersection(point_on_surface, cone), Geometry::get_intersection(cone, point_on_surface), "Point on surface of cone (base) intersection overload");

if (intersection.has_value())
CHECK_EQUAL(intersection->m_position, point_on_surface.m_position, "Point on surface of cone (base) intersection position");
}
{// Test point on the cone surface (side)
auto point_on_surface = Geometry::Point(glm::vec3(0.f, 0.5f, 0.5f));

auto on_surface = Geometry::intersecting(point_on_surface, cone);
CHECK_TRUE(on_surface, "Point on surface of cone (side)");
CHECK_EQUAL(Geometry::intersecting(point_on_surface, cone), Geometry::intersecting(cone, point_on_surface), "Point on surface of cone (side) overload");

auto intersection = Geometry::get_intersection(point_on_surface, cone);
CHECK_TRUE(intersection.has_value(), "Point on surface of cone (side) intersection");
CHECK_EQUAL(Geometry::get_intersection(point_on_surface, cone), Geometry::get_intersection(cone, point_on_surface), "Point on surface of cone (side) intersection overload");

if (intersection.has_value())
CHECK_EQUAL(intersection->m_position, point_on_surface.m_position, "Point on surface of cone (side) intersection position");
}
}
}

void GeometryTester::draw_frustrum_debugger_UI(float aspect_ratio)
Expand Down

0 comments on commit 7089496

Please sign in to comment.