mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 07:03:25 +00:00
added trace line
This commit is contained in:
32
include/omath/Triangle3d.hpp
Normal file
32
include/omath/Triangle3d.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// Created by Orange on 11/13/2024.
|
||||
//
|
||||
#pragma once
|
||||
#include "omath/Vector3.hpp"
|
||||
|
||||
namespace omath
|
||||
{
|
||||
class Triangle3d
|
||||
{
|
||||
public:
|
||||
Triangle3d(const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3);
|
||||
Vector3 m_vertex1;
|
||||
Vector3 m_vertex2;
|
||||
Vector3 m_vertex3;
|
||||
|
||||
[[nodiscard]]
|
||||
Vector3 CalculateNormal() const;
|
||||
|
||||
[[nodiscard]]
|
||||
float SideALength() const;
|
||||
|
||||
[[nodiscard]]
|
||||
float SideBLength() const;
|
||||
|
||||
[[nodiscard]]
|
||||
Vector3 SideAVector() const;
|
||||
|
||||
[[nodiscard]]
|
||||
Vector3 SideBVector() const;
|
||||
};
|
||||
}
|
||||
22
include/omath/collision/LineTracer.hpp
Normal file
22
include/omath/collision/LineTracer.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Created by Orange on 11/13/2024.
|
||||
//
|
||||
#pragma once
|
||||
#include "omath/Vector3.hpp"
|
||||
#include "omath/Triangle3d.hpp"
|
||||
namespace omath::collision
|
||||
{
|
||||
struct Ray
|
||||
{
|
||||
Vector3 start;
|
||||
Vector3 end;
|
||||
};
|
||||
class LineTracer
|
||||
{
|
||||
public:
|
||||
LineTracer() = delete;
|
||||
|
||||
[[nodiscard]]
|
||||
static bool CanTraceLine(const Ray& ray, const Triangle3d& triangle);
|
||||
};
|
||||
}
|
||||
@@ -3,8 +3,11 @@ target_sources(omath PRIVATE
|
||||
Matrix.cpp
|
||||
color.cpp
|
||||
Vector4.cpp
|
||||
Vector2.cpp)
|
||||
Vector2.cpp
|
||||
Triangle3d.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(prediction)
|
||||
add_subdirectory(pathfinding)
|
||||
add_subdirectory(projection)
|
||||
add_subdirectory(projection)
|
||||
add_subdirectory(collision)
|
||||
36
source/Triangle3d.cpp
Normal file
36
source/Triangle3d.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "omath/Triangle3d.hpp"
|
||||
|
||||
|
||||
namespace omath
|
||||
{
|
||||
Triangle3d::Triangle3d(const Vector3 &vertex1, const Vector3 &vertex2, const Vector3 &vertex3)
|
||||
: m_vertex1(vertex1), m_vertex2(vertex2), m_vertex3(vertex3)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Vector3 Triangle3d::CalculateNormal() const
|
||||
{
|
||||
return (m_vertex1 - m_vertex2).Cross(m_vertex3 - m_vertex1).Normalized();
|
||||
}
|
||||
|
||||
float Triangle3d::SideALength() const
|
||||
{
|
||||
return m_vertex1.DistTo(m_vertex2);
|
||||
}
|
||||
|
||||
float Triangle3d::SideBLength() const
|
||||
{
|
||||
return m_vertex3.DistTo(m_vertex2);
|
||||
}
|
||||
|
||||
Vector3 Triangle3d::SideAVector() const
|
||||
{
|
||||
return m_vertex1 - m_vertex2;
|
||||
}
|
||||
|
||||
Vector3 Triangle3d::SideBVector() const
|
||||
{
|
||||
return m_vertex3 - m_vertex2;
|
||||
}
|
||||
}
|
||||
1
source/collision/CMakeLists.txt
Normal file
1
source/collision/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
||||
target_sources(omath PRIVATE LineTracer.cpp)
|
||||
40
source/collision/LineTracer.cpp
Normal file
40
source/collision/LineTracer.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Created by Orange on 11/13/2024.
|
||||
//
|
||||
#pragma once
|
||||
#include "omath/collision/LineTracer.hpp"
|
||||
|
||||
namespace omath::collision
|
||||
{
|
||||
bool LineTracer::CanTraceLine(const Ray &ray, const Triangle3d &triangle)
|
||||
{
|
||||
const auto sideA = triangle.SideAVector();
|
||||
const auto sideB = triangle.SideBVector();
|
||||
|
||||
const auto rayDir = ray.end - ray.start;
|
||||
|
||||
const auto p = rayDir.Cross(sideB);
|
||||
|
||||
const auto det = sideA.Dot(p);
|
||||
|
||||
if (std::abs(det) < 1e-6)
|
||||
return true;
|
||||
|
||||
const auto invDet = 1 / det;
|
||||
|
||||
const auto t = ray.start - triangle.m_vertex2;
|
||||
|
||||
const auto u = t.Dot(p) * invDet;
|
||||
|
||||
if (u < 0.f || u > 1.f)
|
||||
return true;
|
||||
|
||||
const auto q = t.Cross(sideA);
|
||||
const auto v = rayDir.Dot(q) * invDet;
|
||||
|
||||
if (v < 0.f || u + v > 1.f)
|
||||
return true;
|
||||
|
||||
return sideB.Dot(q) * invDet <= 0.f;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,9 @@ add_executable(unit-tests
|
||||
UnitTestVector3.cpp
|
||||
UnitTestVector2.cpp
|
||||
UnitTestColor.cpp
|
||||
UnitTestVector4.cpp)
|
||||
UnitTestVector4.cpp
|
||||
UnitTestLineTrace.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(unit-tests PRIVATE gtest gtest_main omath)
|
||||
|
||||
|
||||
67
tests/UnitTestLineTrace.cpp
Normal file
67
tests/UnitTestLineTrace.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "omath/collision/LineTracer.hpp"
|
||||
#include "omath/Triangle3d.hpp"
|
||||
#include "omath/Vector3.hpp"
|
||||
|
||||
using namespace omath;
|
||||
using namespace omath::collision;
|
||||
|
||||
class LineTracerTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
// Set up common variables for use in each test
|
||||
Vector3 vertex1{0.0f, 0.0f, 0.0f};
|
||||
Vector3 vertex2{1.0f, 0.0f, 0.0f};
|
||||
Vector3 vertex3{0.0f, 1.0f, 0.0f};
|
||||
Triangle3d triangle{vertex1, vertex2, vertex3};
|
||||
};
|
||||
|
||||
// Test that a ray intersecting the triangle returns false for CanTraceLine
|
||||
TEST_F(LineTracerTest, RayIntersectsTriangle)
|
||||
{
|
||||
constexpr Ray ray{{0.3f, 0.3f, -1.0f}, {0.3f, 0.3f, 1.0f}};
|
||||
EXPECT_FALSE(LineTracer::CanTraceLine(ray, triangle));
|
||||
}
|
||||
|
||||
// Test that a ray parallel to the triangle plane returns true for CanTraceLine
|
||||
TEST_F(LineTracerTest, RayParallelToTriangle)
|
||||
{
|
||||
constexpr Ray ray{{0.3f, 0.3f, 1.0f}, {0.3f, 0.3f, 2.0f}};
|
||||
EXPECT_TRUE(LineTracer::CanTraceLine(ray, triangle));
|
||||
}
|
||||
|
||||
// Test that a ray starting inside the triangle but pointing away returns true
|
||||
TEST_F(LineTracerTest, RayStartsInTriangleButDoesNotIntersect)
|
||||
{
|
||||
constexpr Ray ray{{0.3f, 0.3f, 0.0f}, {0.3f, 0.3f, -1.0f}};
|
||||
EXPECT_TRUE(LineTracer::CanTraceLine(ray, triangle));
|
||||
}
|
||||
|
||||
// Test that a ray not intersecting the triangle plane returns true
|
||||
TEST_F(LineTracerTest, RayMissesTriangle)
|
||||
{
|
||||
constexpr Ray ray{{2.0f, 2.0f, -1.0f}, {2.0f, 2.0f, 1.0f}};
|
||||
EXPECT_TRUE(LineTracer::CanTraceLine(ray, triangle));
|
||||
}
|
||||
|
||||
// Test that a ray lying exactly in the plane of the triangle without intersecting returns true
|
||||
TEST_F(LineTracerTest, RayInPlaneNotIntersecting)
|
||||
{
|
||||
constexpr Ray ray{{-1.0f, -1.0f, 0.0f}, {1.5f, 1.5f, 0.0f}};
|
||||
EXPECT_TRUE(LineTracer::CanTraceLine(ray, triangle));
|
||||
}
|
||||
|
||||
// Test edge case where the ray exactly intersects one of the triangle's vertices, expecting false
|
||||
TEST_F(LineTracerTest, RayIntersectsVertex)
|
||||
{
|
||||
const Ray ray{{-1.0f, -1.0f, -1.0f}, vertex1}; // Intersecting at vertex1
|
||||
EXPECT_FALSE(LineTracer::CanTraceLine(ray, triangle));
|
||||
}
|
||||
|
||||
// Test edge case where the ray exactly intersects one of the triangle's edges, expecting false
|
||||
TEST_F(LineTracerTest, RayIntersectsEdge)
|
||||
{
|
||||
constexpr Ray ray{{-1.0f, 0.0f, -1.0f}, {0.5f, 0.0f, 0.0f}};
|
||||
// Intersecting on the edge between vertex1 and vertex2
|
||||
EXPECT_FALSE(LineTracer::CanTraceLine(ray, triangle));
|
||||
}
|
||||
Reference in New Issue
Block a user