added trace line

This commit is contained in:
2024-11-14 06:37:41 +03:00
parent 455e8d2509
commit 918036605b
8 changed files with 206 additions and 3 deletions

View 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;
};
}

View 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);
};
}

View File

@@ -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
View 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;
}
}

View File

@@ -0,0 +1 @@
target_sources(omath PRIVATE LineTracer.cpp)

View 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;
}
}

View File

@@ -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)

View 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));
}