Add Vector2 test / Bug fixes.

This commit is contained in:
THoehne 2024-06-25 22:59:52 +02:00
parent 53d0728765
commit ed30070286
6 changed files with 288 additions and 65 deletions

View File

@ -25,11 +25,11 @@
namespace Phanes::Core::Math {
/**
/**
* A 2D Vector with components x and y with floating point precision.
*/
template<RealType T, bool A>
struct TVector2 {
@ -39,9 +39,9 @@ namespace Phanes::Core::Math {
// Using in combination with a struct and an array allows us the reflect changes of the x and y variables in the comp array and vise versa.
union
union
{
struct
{
/** X component of Vector
@ -50,22 +50,22 @@ namespace Phanes::Core::Math {
* @note x does not hold the component, but is a reference two the second item in the components array. The varibale exists wholly for convenience.
*/
Real x;
/** Y component of Vector
*
/** Y component of Vector
*
* @see [FIELD]components
*
*
* @note y does not hold the component, but is a reference two the second item in the components array. The varibale exists wholly for convenience.
*/
Real y;
};
/** Components array holding the data
*
/** Components array holding the data
*
* @see [FIELD]x
* @see [FIELD]y
*
* @note Components are split into x and y. Access and manipulation is possible by these variables.
*
* @note Components are split into x and y. Access and manipulation is possible by these variables.
*/
union
@ -86,7 +86,7 @@ namespace Phanes::Core::Math {
*/
TVector2() = default;
/**
* Copy constructor
*/
@ -95,7 +95,7 @@ namespace Phanes::Core::Math {
/**
* Construct Vector from xy components.
*
*
* @param(x) X component
* @param(y) Y component
*/
@ -113,15 +113,15 @@ namespace Phanes::Core::Math {
/// </summary>
/// <param name="s">Scalar</param>
TVector2(Real s);
};
};
// ====================== //
// TVector2 operators //
// ====================== //
/**
* Addition operation on same TVector2<T, S> (this) by a floating point value.
*
*
* @param(v1) Vector to add to
* @param(s) Floating point to add
*/
@ -160,7 +160,7 @@ namespace Phanes::Core::Math {
TVector2<T, S> operator-= (TVector2<T, S>& v1, const TVector2<T, S>& v2);
/**
* Multiplication of TVector2<T, S> (this) with a floating point.
* Multiplication of TVector2<T, S> (this) with a floating point.
*
* @param(v1) Vector to multiply with
* @param(s Floating point to multiply with
@ -169,6 +169,17 @@ namespace Phanes::Core::Math {
template<RealType T, bool S>
TVector2<T, S> operator*= (TVector2<T, S>& v1, T s);
/// <summary>
/// Componentwise multiplication of vector by other vector.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="S"></typeparam>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector2<T, S> operator*= (TVector2<T, S>& v1, const TVector2<T, S>& v2);
/**
* Devision of Vector (this) by floating point.
*
@ -179,72 +190,112 @@ namespace Phanes::Core::Math {
template<RealType T, bool S>
TVector2<T, S> operator/= (TVector2<T, S>& v1, T s);
/// <summary>
/// Componentwise division of vector by other vector.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="S"></typeparam>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector2<T, S> operator/= (TVector2<T, S>& v1, const TVector2<T, S>& v2);
/**
* Scale of Vector by floating point. (> Creates a new TVector2<T, S>)
*
* @param(v1) Vector to multiply with
* @param(s Floating point to multiply with
*
*
* @return Result Vector
*/
template<RealType T, bool S>
TVector2<T, S> operator* (const TVector2<T, S>& v1, T s);
/// <summary>
/// Componentwise multiplication with vector by vector.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="S"></typeparam>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
template<RealType T, bool S>
TVector2<T, S> operator* (const TVector2<T, S>& v1, const TVector2<T, S>& v2);
/**
* Division of Vector by floating point. (> Creates another TVector2<T, S>)
*
* @param(v1) Vector to multiply with
* @param(s Floating point to divide with
*
*
* @return Result Vector
*/
template<RealType T, bool S>
TVector2<T, S> operator/ (const TVector2<T, S>& v1, T s);
/// <summary>
/// Componentwise multiplication with vector by vector.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="S"></typeparam>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
template<RealType T, bool S>
TVector2<T, S> operator/ (const TVector2<T, S>& v1, const TVector2<T, S>& v2);
/**
* Scale of Vector by floating point. (> Creates a new TVector2<T, S>)
*
* @param(v1) Vector to multiply with
* @param(s Floating point to multiply with
*
*
* @return Result Vector
*/
template<RealType T, bool S>
inline TVector2<T, S> operator* (T s, const TVector2<T, S>& v1);
inline TVector2<T, S> operator* (T s, const TVector2<T, S>& v1)
{
return v1 * s;
}
/**
* Division of Vector by floating point. (> For convenience not arithmethicaly correct. Works like overloaded counterpart.)
*
* @param(v1) Vector to multiply with
* @param(s Floating point to divide with
*
*
* @return Result Vector
*/
template<RealType T, bool S>
inline TVector2<T, S> operator/ (T s, const TVector2<T, S>& v1);
inline TVector2<T, S> operator/ (T s, const TVector2<T, S>& v1)
{
return v1 / s;
}
/**
* Componentwise addition of Vector with floating point.
* Componentwise addition of Vector with floating point.
*
* @param(v1) Vector to add to
* @param(s Floating point to add
*
*
* @return Result Vector
*/
template<RealType T, bool S>
TVector2<T, S> operator+ (const TVector2<T, S>& v1, T s);
/**
* Componentwise addition of Vector with floating point.
* Componentwise addition of Vector with floating point.
*
* @param(v1) Vector to add to
* @param(s Floating point to add
*
*
* @return Result Vector
*/
@ -256,7 +307,7 @@ namespace Phanes::Core::Math {
*
* @param(v1) Vector to substract from
* @param(s Floating point to substract
*
*
* @return Result Vector
*/
@ -268,7 +319,7 @@ namespace Phanes::Core::Math {
*
* @param(v1) Vector to substract from
* @param(s Floating point to substract
*
*
* @return Result Vector
*/
@ -276,22 +327,12 @@ namespace Phanes::Core::Math {
TVector2<T, S> operator- (const TVector2<T, S>& v1, const TVector2<T, S>& v2);
/**
* Negate Vector.
* Compare Vector for equality.
*
* @param(v1) Vector to negate
*/
template<RealType T, bool S>
TVector2<T, S> operator- (const TVector2<T, S>& v1);
/**
* Compare Vector for equality.
*
* @see [FUNC]Equals
*
* @param(v1) Vector to negate
*
*
* @return true if equal, false if inequal
*/
@ -305,7 +346,7 @@ namespace Phanes::Core::Math {
* @see [FUNC]Equals
*
* @param(v1) Vector to negate
*
*
* @return true if inequal, false if equal
*/
@ -313,6 +354,8 @@ namespace Phanes::Core::Math {
bool operator!= (const TVector2<T, S>& v1, const TVector2<T, S>& v2);
// ============================================ //
// TVector2 static function implementation //
// ============================================ //
@ -410,7 +453,7 @@ namespace Phanes::Core::Math {
template<RealType T>
T CosineAngle(const TVector2<T, false>& v1, const TVector2<T, false>& v2)
{
return (v1 * v2) / Magnitude(v1) * Magnitude(v2);
return DotP(v1, v2) / (Magnitude(v1) * Magnitude(v2));
}
/**
@ -422,8 +465,8 @@ namespace Phanes::Core::Math {
template<RealType T>
TVector2<T, false> SignVectorV(TVector2<T, false>& v1)
{
v1.x = (v1.x >= 0) ? 1 : -1;
v1.y = (v1.y >= 0) ? 1 : -1;
v1.x = (v1.x >= (T)0.0) ? (T)1.0 : -(T)1.0;
v1.y = (v1.y >= (T)0.0) ? (T)1.0 : -(T)1.0;
return v1;
}
@ -521,9 +564,9 @@ namespace Phanes::Core::Math {
template<RealType T>
TVector2<T, false> GetPerpendicularV(TVector2<T, false>& v1)
{
T x = v1.x;
T x = -v1.x;
v1.x = v1.y;
v1.y = -v1.x;
v1.y = x;
return v1;
}
@ -543,7 +586,7 @@ namespace Phanes::Core::Math {
{
T x = v1.x;
v1.x = -v1.y;
v1.y = v1.x;
v1.y = x;
return v1;
}
@ -595,7 +638,7 @@ namespace Phanes::Core::Math {
template<RealType T>
TVector2<T, false> ReflectV(TVector2<T, false>& v1, const TVector2<T, false>& normal)
{
Set(v1, v1 - (2 * DotP(v1, normal) * normal));
v1 = (2.0f * DotP(v1, normal) * normal) - v1;
return v1;
}
@ -681,6 +724,8 @@ namespace Phanes::Core::Math {
{
v1.x = -v1.x;
v1.y = -v1.y;
return v1;
}
/**
@ -782,7 +827,7 @@ namespace Phanes::Core::Math {
template<RealType T>
TVector2<T, false> Reflect(const TVector2<T, false>& v1, const TVector2<T, false>& normal)
{
return TVector2<T, false>(v1 - (2 * DotP(v1, normal) * normal));
return TVector2<T, false>((2.0f * DotP(v1, normal) * normal) - v1);
}
/**
@ -927,7 +972,7 @@ namespace Phanes::Core::Math {
template<RealType T>
TVector2<T, false> SignVector(const TVector2<T, false>& v1)
{
return TVector2<T, false>((v1.x >= 0) ? 1 : -1, (v1.y >= 0) ? 1 : -1);
return TVector2<T, false>((v1.x >= (T)0.0) ? 1 : -1, (v1.y >= (T)0.0) ? (T)1.0 : (T)-1.0);
}
/**
@ -981,7 +1026,7 @@ namespace Phanes::Core::Math {
{
t = Phanes::Core::Math::Clamp(t, (T)0.0, (T)1.0);
return (t * destVec) + ((1 - t) * startVec);
return ((1 - t) * startVec) + (t * destVec);
}
/**
@ -1043,6 +1088,5 @@ namespace Phanes::Core::Math {
#endif // !VECTOR2_H
// Include operator impl.
#include "Core/public/Math/Vector2.inl"

View File

@ -95,7 +95,7 @@ namespace Phanes::Core::Math
}
template<RealType T, bool S>
TVector2<T, S> operator+(TVector2<T, S>& v1, const TVector2<T, S>& v2)
TVector2<T, S> operator+(const TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
TVector2<T, S> r;
Detail::compute_vec2_add<T, S>::map(r, v1, v2);
@ -103,7 +103,7 @@ namespace Phanes::Core::Math
}
template<RealType T, bool S>
TVector2<T, S> operator+(TVector2<T, S>& v1, T s)
TVector2<T, S> operator+(const TVector2<T, S>& v1, T s)
{
TVector2<T, S> r;
Detail::compute_vec2_add<T, S>::map(r, v1, s);
@ -111,7 +111,7 @@ namespace Phanes::Core::Math
}
template<RealType T, bool S>
TVector2<T, S> operator-(TVector2<T, S>& v1, const TVector2<T, S>& v2)
TVector2<T, S> operator-(const TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
TVector2<T, S> r;
Detail::compute_vec2_sub<T, S>::map(r, v1, v2);
@ -119,7 +119,7 @@ namespace Phanes::Core::Math
}
template<RealType T, bool S>
TVector2<T, S> operator-(TVector2<T, S>& v1, T s)
TVector2<T, S> operator-(const TVector2<T, S>& v1, T s)
{
TVector2<T, S> r;
Detail::compute_vec2_sub<T, S>::map(r, v1, s);
@ -127,7 +127,7 @@ namespace Phanes::Core::Math
}
template<RealType T, bool S>
TVector2<T, S> operator*(TVector2<T, S>& v1, const TVector2<T, S>& v2)
TVector2<T, S> operator*(const TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
TVector2<T, S> r;
Detail::compute_vec2_mul<T, S>::map(r, v1, v2);
@ -135,7 +135,7 @@ namespace Phanes::Core::Math
}
template<RealType T, bool S>
TVector2<T, S> operator*(TVector2<T, S>& v1, T s)
TVector2<T, S> operator*(const TVector2<T, S>& v1, T s)
{
TVector2<T, S> r;
Detail::compute_vec2_mul<T, S>::map(r, v1, s);
@ -143,7 +143,7 @@ namespace Phanes::Core::Math
}
template<RealType T, bool S>
TVector2<T, S> operator/(TVector2<T, S>& v1, const TVector2<T, S>& v2)
TVector2<T, S> operator/(const TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
TVector2<T, S> r;
Detail::compute_vec2_div<T, S>::map(r, v1, v2);
@ -151,7 +151,7 @@ namespace Phanes::Core::Math
}
template<RealType T, bool S>
TVector2<T, S> operator/(TVector2<T, S>& v1, T s)
TVector2<T, S> operator/(const TVector2<T, S>& v1, T s)
{
TVector2<T, S> r;
Detail::compute_vec2_div<T, S>::map(r, v1, s);

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn" version="1.8.1.7" targetFramework="native" />
</packages>

5
MathTestFPU/pch.cpp Normal file
View File

@ -0,0 +1,5 @@
//
// pch.cpp
//
#include "pch.h"

7
MathTestFPU/pch.h Normal file
View File

@ -0,0 +1,7 @@
//
// pch.h
//
#pragma once
#include "gtest/gtest.h"

163
MathTestFPU/test.cpp Normal file
View File

@ -0,0 +1,163 @@
#include "pch.h"
#include "Core/public/Math/Include.h"
namespace PMath = Phanes::Core::Math;
using namespace Phanes::Core::Math::UnitLiterals;
namespace VectorTests
{
TEST(Vector2, OperatorTests)
{
PMath::Vector2 v0(2.4f, 3.1f);
PMath::Vector2 v1(5.1f, 2.5f);
v0 += v1;
EXPECT_TRUE(v0 == PMath::Vector2(7.5f, 5.6f));
v0 -= v1;
EXPECT_TRUE(v0 == PMath::Vector2(2.4f, 3.1f));
v0 *= v1;
EXPECT_TRUE(v0 == PMath::Vector2(12.24f, 7.75f));
v0 /= v1;
EXPECT_TRUE(v0 == PMath::Vector2(2.4f, 3.1f));
v0 += 4.0f;
EXPECT_TRUE(v0 == PMath::Vector2(6.4f, 7.1f));
v0 -= 4.0f;
EXPECT_TRUE(v0 == PMath::Vector2(2.4f, 3.1f));
v0 *= 4.0f;
EXPECT_TRUE(v0 == PMath::Vector2(9.6f, 12.4f));
v0 /= 4.0f;
EXPECT_TRUE(v0 == PMath::Vector2(2.4f, 3.1f));
// ------------------------------------------
PMath::Vector2 r;
r = v0 + v1;
EXPECT_TRUE(r == PMath::Vector2(7.5f, 5.6f));
r = v0 - v1;
EXPECT_TRUE(r == PMath::Vector2(-2.7f, 0.6f));
r = v0 * v1;
EXPECT_TRUE(r == PMath::Vector2(12.24f, 7.75f));
r = v0 / v1;
EXPECT_TRUE(r == PMath::Vector2(0.470588f, 1.24f));
r = v0 + 4.0f;
EXPECT_TRUE(r == PMath::Vector2(6.4f, 7.1f));
r = v0 - 4.0f;
EXPECT_TRUE(r == PMath::Vector2(-1.6f, -0.9f));
r = v0 * 4.0f;
EXPECT_TRUE(r == PMath::Vector2(9.6f, 12.4f));
r = v0 / 4.0f;
EXPECT_TRUE(r == PMath::Vector2(0.6f, 0.775f));
// --------------------------------------------
EXPECT_TRUE(r != PMath::Vector2(0.480588f, 3.24f));
EXPECT_FALSE(r != PMath::Vector2(0.6f, 0.775f));
}
TEST(Vector2, FunctionTest)
{
PMath::Vector2 v0(2.4f, 3.1f);
PMath::Vector2 v1(5.1f, 2.5f);
PMath::Vector2 v2(0.0f, 0.0f);
EXPECT_FLOAT_EQ(PMath::Magnitude(v0), 3.9204591f);
EXPECT_FLOAT_EQ(PMath::SqrMagnitude(v0), 15.37f);
EXPECT_TRUE(PMath::NormalizeV(v0) == PMath::Vector2(0.612173f, 0.790724f));
EXPECT_TRUE(PMath::NormalizeV(v2) == PMath::Vector2(0.0f, 0.0f));
EXPECT_TRUE(PMath::IsNormalized(v0));
EXPECT_TRUE(PMath::Abs(PMath::Angle(v0, v1) - 26.13928198243463_deg) < P_FLT_INAC);
EXPECT_FLOAT_EQ(PMath::CosineAngle(v0,v1), 0.897725742f);
EXPECT_TRUE(PMath::SignVectorV(v0) == PMath::Vector2(1, 1));
EXPECT_TRUE(PMath::BindToSquareV(v1, 2.0f) == PMath::Vector2(2.0f, 0.9803921568f));
// Re-init vectors.
v0 = PMath::Vector2(2.4f, 3.1f);
v1 = PMath::Vector2(5.1f, 2.5f);
EXPECT_TRUE(PMath::ClampToSquareV(v0, 2.0f) == PMath::Vector2(1.5483870968f, 2.0f));
EXPECT_FLOAT_EQ(PMath::DotP(v0, v1), 12.89677419368f);
// Re-init vector
v0 = PMath::Vector2(2.4f, 3.1f);
EXPECT_TRUE(PMath::MaxV(v0, v1) == PMath::Vector2(5.1f, 3.1f));
// Re-init vector
v0 = PMath::Vector2(2.4f, 3.1f);
EXPECT_TRUE(PMath::MinV(v0, v1) == PMath::Vector2(2.4f, 2.5f));
EXPECT_TRUE(PMath::GetPerpendicularV(v0) == PMath::Vector2(2.5f, -2.4f));
EXPECT_TRUE(PMath::GetReversePerpendicularV(v1) == PMath::Vector2(-2.5f, 5.1f));
EXPECT_TRUE(PMath::ScaleV(v0, v1) == PMath::Vector2(-6.25f, -12.24f));
EXPECT_TRUE(PMath::CompInverseV(v0) == PMath::Vector2(1.0f/-6.25f, 1.0f/-12.24f));
// re-init vectors.
v0 = PMath::Vector2(2.4f, 3.1f);
v1 = PMath::Vector2(5.1f, 2.5f);
PMath::Vector2 n(0.8320502943f, 0.554700196f);
// std::cerr << PMath::ToString(PMath::Reflect(v0, n)) << std::endl;
EXPECT_TRUE(PMath::ReflectV(v0, n) == PMath::Vector2(3.784616f, 1.023077f));
// Re-init vectors.
v0 = PMath::Vector2(2.4f, 3.1f);
EXPECT_TRUE(PMath::RotateV(v0, (float)30.0_deg) == PMath::Vector2(0.528460969082653f, 3.88467875173176f));
EXPECT_TRUE(PMath::ClockwiseRotateV(v0, (float)30.0_deg) == PMath::Vector2(2.4f, 3.1f));
EXPECT_TRUE(PMath::NegateV(v0) == PMath::Vector2(-2.4f, -3.1f));
EXPECT_TRUE(PMath::IsPerpendicular(v0, PMath::GetPerpendicular(v0))); // Tests GetPerpendicular too.
EXPECT_TRUE(PMath::IsNormalized(n));
EXPECT_FALSE(PMath::IsNormalized(v0));
// Re-init vectors.
v0 = PMath::Vector2(2.4f, 3.1f);
v1 = PMath::Vector2(5.1f, 2.5f);
EXPECT_TRUE(PMath::IsParallel(v0, PMath::Vector2(-7.2f, -9.3f)));
EXPECT_TRUE(PMath::IsCoincident(v0, PMath::Vector2(7.2f, 9.3f)));
EXPECT_FALSE(PMath::IsCoincident(v0, PMath::Vector2(-7.2f, -9.3f)));
EXPECT_TRUE(PMath::Reflect(v0, n) == PMath::Vector2(3.784616f, 1.023077f));
EXPECT_TRUE(PMath::Scale(v0, v1) == PMath::Vector2(12.24f, 7.75f));
EXPECT_TRUE(PMath::CompInverse(v0) == PMath::Vector2(1.0f / 2.4f, 1.0f / 3.1f));
EXPECT_TRUE(PMath::Negate(v0) == PMath::Vector2(-2.4f, -3.1f));
EXPECT_TRUE(PMath::GetPerpendicular(v0) == PMath::Vector2(3.1f, -2.4f));
EXPECT_TRUE(PMath::GetReversePerpendicular(v0) == PMath::Vector2(-3.1f, 2.4f));
EXPECT_TRUE(PMath::Max(v0, v1) == PMath::Vector2(5.1f, 3.1f));
EXPECT_TRUE(PMath::Min(v0, v1) == PMath::Vector2(2.4f, 2.5f));
EXPECT_TRUE(PMath::Normalize(v0) == PMath::Vector2(0.612173f, 0.790724f));
EXPECT_TRUE(PMath::SignVector(v0) == PMath::Vector2(1.0f, 1.0f));
EXPECT_TRUE(PMath::BindToSquare(v1, 2.0f) == PMath::Vector2(2.0f, 0.9803921568f));
EXPECT_TRUE(PMath::ClampToSquare(v0, 2.0f) == PMath::Vector2(1.5483870968f, 2.0f));
std::cerr << PMath::ToString(PMath::Lerp(v0, v1, 0.7f)) << std::endl;
EXPECT_TRUE(PMath::Lerp(v0, v1, 0.7f) == PMath::Vector2(4.29f, 2.68f));
EXPECT_TRUE(PMath::Rotate(v0, (float)30.0_deg) == PMath::Vector2(0.528460969082653f, 3.88467875173176f));
EXPECT_TRUE(PMath::ClockwiseRotate(v0, (float)30.0_deg) == PMath::Vector2(3.628461f, 1.484679f));
}
}