Migrating to Linux

This commit is contained in:
Thorben Höhne
2025-02-17 22:31:17 +01:00
parent c65b1c8139
commit 14f3339eee
75 changed files with 125 additions and 71 deletions

View File

@@ -0,0 +1,101 @@
// Math is independent from the rest of the library, to ensure seamless usage with other client.
#pragma once
#ifdef P_BUILD_LIB
#include "PhanesEnginePCH.h"
#else
#include <type_traits>
#include <memory>
#endif
#ifdef P_WIN_BUILD
#ifdef P_DEBUG
#define P_DEBUGBREAK DebugBreak();
#else
#define P_DEBUGBREAK
#endif // P_DEBUG
#define FORCEINLINE __forceinline
#elif defined(P_LINUX_BUILD)
#ifdef P_DEBUG
#define P_DEBUGBREAK __builtin_trap();
#else
#define P_DEBUGBREAK
#endif // P_DEBUG
#define FORCEINLINE inline __attribute__((always_inline))
#elif defined(P_ARM_BUILD)
#error Only Windows is supported at the moment.
#else
#error The target system must be defined. (See https://github.com/scorpioblood/PhanesEngine for more information)
#endif // P_WIN_BUILD
namespace Phanes::Core::Math
{
// Typenames with RealType constrain have to be floating point numbers.
template<typename T>
concept RealType = std::is_floating_point_v<T>;
// Typenames with IntType constrain have to be integer number.
template<typename T>
concept IntType = std::is_integral_v<T>;
// Typenames with Arithmethic constrain have to be number.
template<typename T>
concept Arithmethic = std::is_arithmetic_v<T>;
// Alias for shared_ptr
template<typename T>
using Ref = std::shared_ptr<T>;
// Alias for make_shared
template<typename T, typename ...Args>
constexpr Ref<T> MakeRef(Args&& ...args)
{
return std::make_shared<T>(std::forward<Args>(args)...);
}
// Alias for unique ptr
template<typename T>
using Scope = std::unique_ptr<T>;
// Alias for make_unique
template<typename T, typename ...Args>
constexpr Scope<T> MakeScope(Args&& ...args)
{
return std::make_unique<T>(std::forward<Args>(args)...);
}
}

View File

@@ -0,0 +1,301 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
namespace Phanes::Core::Math::Detail
{
template<IntType T, bool S>
struct construct_ivec2 {};
template<IntType T, bool S>
struct compute_ivec2_add {};
template<IntType T, bool S>
struct compute_ivec2_sub {};
template<IntType T, bool S>
struct compute_ivec2_mul {};
template<IntType T, bool S>
struct compute_ivec2_div {};
template<IntType T, bool S>
struct compute_ivec2_mod {};
template<IntType T, bool S>
struct compute_ivec2_eq {};
template<IntType T, bool S>
struct compute_ivec2_ieq {};
template<IntType T, bool S>
struct compute_ivec2_inc {};
template<IntType T, bool S>
struct compute_ivec2_dec {};
template<IntType T, bool S>
struct compute_ivec2_and {};
template<IntType T, bool S>
struct compute_ivec2_or {};
template<IntType T, bool S>
struct compute_ivec2_xor {};
template<IntType T, bool S>
struct compute_ivec2_left_shift {};
template<IntType T, bool S>
struct compute_ivec2_right_shift {};
template<IntType T, bool S>
struct compute_ivec2_bnot {};
template<IntType T>
struct construct_ivec2<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& v1, const TIntVector2<T, false>& v2)
{
v1.x = v2.x;
v1.y = v2.y;
}
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& v1, T s)
{
v1.x = s;
v1.y = s;
}
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& v1, T x, T y)
{
v1.x = x;
v1.y = y;
}
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& v1, const T* comp)
{
v1.x = comp[0];
v1.y = comp[1];
}
};
template<IntType T>
struct compute_ivec2_add<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, const Phanes::Core::Math::TIntVector2<T, false>& v2)
{
r.x = v1.x + v2.x;
r.y = v1.y + v2.y;
}
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, T s)
{
r.x = v1.x + s;
r.y = v1.y + s;
}
};
template<IntType T>
struct compute_ivec2_sub<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, const Phanes::Core::Math::TIntVector2<T, false>& v2)
{
r.x = v1.x - v2.x;
r.y = v1.y - v2.y;
}
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, T s)
{
r.x = v1.x - s;
r.y = v1.y - s;
}
};
template<IntType T>
struct compute_ivec2_mul<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, const Phanes::Core::Math::TIntVector2<T, false>& v2)
{
r.x = v1.x * v2.x;
r.y = v1.y * v2.y;
}
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, T s)
{
r.x = v1.x * s;
r.y = v1.y * s;
}
};
template<IntType T>
struct compute_ivec2_div<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, const Phanes::Core::Math::TIntVector2<T, false>& v2)
{
r.x = v1.x / v2.x;
r.y = v1.y / v2.y;
}
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, T s)
{
r.x = v1.x / s;
r.y = v1.y / s;
}
};
template<IntType T>
struct compute_ivec2_mod<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, const Phanes::Core::Math::TIntVector2<T, false>& v2)
{
r.x = v1.x % v2.x;
r.y = v1.y % v2.y;
}
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, T s)
{
r.x = v1.x % s;
r.y = v1.y % s;
}
};
template<IntType T>
struct compute_ivec2_eq<T, false>
{
static constexpr bool map(const Phanes::Core::Math::TIntVector2<T, false>& v1, const Phanes::Core::Math::TIntVector2<T, false>& v2)
{
return (Phanes::Core::Math::Abs(v1.x - v2.x) < P_FLT_INAC &&
Phanes::Core::Math::Abs(v1.y - v2.y) < P_FLT_INAC);
}
};
template<IntType T>
struct compute_ivec2_ieq<T, false>
{
static constexpr bool map(const Phanes::Core::Math::TIntVector2<T, false>& v1, const Phanes::Core::Math::TIntVector2<T, false>& v2)
{
return (Phanes::Core::Math::Abs(v1.x - v2.x) > P_FLT_INAC ||
Phanes::Core::Math::Abs(v1.y - v2.y) > P_FLT_INAC);
}
};
template<IntType T>
struct compute_ivec2_inc<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1)
{
r.x = v1.x + 1;
r.y = v1.y + 1;
}
};
template<IntType T>
struct compute_ivec2_dec<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1)
{
r.x = v1.x - 1;
r.y = v1.y - 1;
}
};
template<IntType T>
struct compute_ivec2_and<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, const Phanes::Core::Math::TIntVector2<T, false>& v2)
{
r.x = v1.x & v2.x;
r.y = v1.y & v2.y;
}
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, T s)
{
r.x = v1.x & s;
r.y = v1.y & s;
}
};
template<IntType T>
struct compute_ivec2_or<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, const Phanes::Core::Math::TIntVector2<T, false>& v2)
{
r.x = v1.x | v2.x;
r.y = v1.y | v2.y;
}
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, const T s)
{
r.x = v1.x | s;
r.y = v1.y | s;
}
};
template<IntType T>
struct compute_ivec2_xor<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, const Phanes::Core::Math::TIntVector2<T, false>& v2)
{
r.x = v1.x ^ v2.x;
r.y = v1.y ^ v2.y;
}
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, const T s)
{
r.x = v1.x ^ s;
r.y = v1.y ^ s;
}
};
template<IntType T>
struct compute_ivec2_left_shift<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, const Phanes::Core::Math::TIntVector2<T, false>& v2)
{
r.x = v1.x << v2.x;
r.y = v1.y << v2.y;
}
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, const T s)
{
r.x = v1.x << s;
r.y = v1.y << s;
}
};
template<IntType T>
struct compute_ivec2_right_shift<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, const Phanes::Core::Math::TIntVector2<T, false>& v2)
{
r.x = v1.x >> v2.x;
r.y = v1.y >> v2.y;
}
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1, const T s)
{
r.x = v1.x >> s;
r.y = v1.y >> s;
}
};
template<IntType T>
struct compute_ivec2_bnot<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector2<T, false>& r, const Phanes::Core::Math::TIntVector2<T, false>& v1)
{
r.x = ~v1.x;
r.y = ~v1.y;
}
};
}

View File

@@ -0,0 +1,342 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
namespace Phanes::Core::Math::Detail
{
template<IntType T, bool S>
struct construct_ivec3 {};
template<IntType T, bool S>
struct compute_ivec3_add {};
template<IntType T, bool S>
struct compute_ivec3_sub {};
template<IntType T, bool S>
struct compute_ivec3_mul {};
template<IntType T, bool S>
struct compute_ivec3_div {};
template<IntType T, bool S>
struct compute_ivec3_mod {};
template<IntType T, bool S>
struct compute_ivec3_eq {};
template<IntType T, bool S>
struct compute_ivec3_ieq {};
template<IntType T, bool S>
struct compute_ivec3_inc {};
template<IntType T, bool S>
struct compute_ivec3_dec {};
template<IntType T, bool S>
struct compute_ivec3_and {};
template<IntType T, bool S>
struct compute_ivec3_or {};
template<IntType T, bool S>
struct compute_ivec3_xor {};
template<IntType T, bool S>
struct compute_ivec3_left_shift {};
template<IntType T, bool S>
struct compute_ivec3_right_shift {};
template<IntType T, bool S>
struct compute_ivec3_bnot {};
template<IntType T>
struct construct_ivec3<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2)
{
v1.x = v2.x;
v1.y = v2.y;
v1.z = v2.z;
v1.w = (T)0;
}
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& v1, T s)
{
v1.x = s;
v1.y = s;
v1.z = s;
v1.w = (T)0;
}
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& v1, T x, T y, T z)
{
v1.x = x;
v1.y = y;
v1.z = z;
v1.w = (T)0;
}
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& v1, const T* comp)
{
v1.x = comp[0];
v1.y = comp[1];
v1.z = comp[2];
v1.w = (T)0;
}
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& v1, const Phanes::Core::Math::TIntVector2<T, false>& v2, const T s)
{
v1.x = v2.x;
v1.y = v2.y;
v1.z = s;
v1.w = (T)0;
}
};
template<IntType T>
struct compute_ivec3_add<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, const Phanes::Core::Math::TIntVector3<T, false>& v2)
{
r.x = v1.x + v2.x;
r.y = v1.y + v2.y;
r.z = v1.z + v2.z;
}
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, T s)
{
r.x = v1.x + s;
r.y = v1.y + s;
r.z = v1.z + s;
}
};
template<IntType T>
struct compute_ivec3_sub<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, const Phanes::Core::Math::TIntVector3<T, false>& v2)
{
r.x = v1.x - v2.x;
r.y = v1.y - v2.y;
r.z = v1.z - v2.z;
}
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, T s)
{
r.x = v1.x - s;
r.y = v1.y - s;
r.z = v1.z - s;
}
};
template<IntType T>
struct compute_ivec3_mul<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, const Phanes::Core::Math::TIntVector3<T, false>& v2)
{
r.x = v1.x * v2.x;
r.y = v1.y * v2.y;
r.z = v1.z * v2.z;
}
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, T s)
{
r.x = v1.x * s;
r.y = v1.y * s;
r.z = v1.z * s;
}
};
template<IntType T>
struct compute_ivec3_div<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, const Phanes::Core::Math::TIntVector3<T, false>& v2)
{
r.x = v1.x / v2.x;
r.y = v1.y / v2.y;
r.z = v1.z / v2.z;
}
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, T s)
{
r.x = v1.x / s;
r.y = v1.y / s;
r.z = v1.z / s;
}
};
template<IntType T>
struct compute_ivec3_mod<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, const Phanes::Core::Math::TIntVector3<T, false>& v2)
{
r.x = v1.x % v2.x;
r.y = v1.y % v2.y;
r.z = v1.z % v2.z;
}
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, T s)
{
r.x = v1.x % s;
r.y = v1.y % s;
r.z = v1.z % s;
}
};
template<IntType T>
struct compute_ivec3_eq<T, false>
{
static constexpr bool map(const Phanes::Core::Math::TIntVector3<T, false>& v1, const Phanes::Core::Math::TIntVector3<T, false>& v2)
{
return (Phanes::Core::Math::Abs(v1.x - v2.x) < P_FLT_INAC &&
Phanes::Core::Math::Abs(v1.y - v2.y) < P_FLT_INAC &&
Phanes::Core::Math::Abs(v1.z - v2.z) < P_FLT_INAC);
}
};
template<IntType T>
struct compute_ivec3_ieq<T, false>
{
static constexpr bool map(const Phanes::Core::Math::TIntVector3<T, false>& v1, const Phanes::Core::Math::TIntVector3<T, false>& v2)
{
return (Phanes::Core::Math::Abs(v1.x - v2.x) > P_FLT_INAC ||
Phanes::Core::Math::Abs(v1.y - v2.y) > P_FLT_INAC ||
Phanes::Core::Math::Abs(v1.y - v2.y) > P_FLT_INAC);
}
};
template<IntType T>
struct compute_ivec3_inc<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1)
{
r.x = v1.x + 1;
r.y = v1.y + 1;
r.z = v1.z + 1;
}
};
template<IntType T>
struct compute_ivec3_dec<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1)
{
r.x = v1.x - 1;
r.y = v1.y - 1;
r.z = v1.z - 1;
}
};
template<IntType T>
struct compute_ivec3_and<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, const Phanes::Core::Math::TIntVector3<T, false>& v2)
{
r.x = v1.x & v2.x;
r.y = v1.y & v2.y;
r.z = v1.z & v2.y;
}
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, T s)
{
r.x = v1.x & s;
r.y = v1.y & s;
r.z = v1.z & s;
}
};
template<IntType T>
struct compute_ivec3_or<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, const Phanes::Core::Math::TIntVector3<T, false>& v2)
{
r.x = v1.x | v2.x;
r.y = v1.y | v2.y;
r.z = v1.z | v2.z;
}
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, T s)
{
r.x = v1.x | s;
r.y = v1.y | s;
r.z = v1.z | s;
}
};
template<IntType T>
struct compute_ivec3_xor<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, const Phanes::Core::Math::TIntVector3<T, false>& v2)
{
r.x = v1.x ^ v2.x;
r.y = v1.y ^ v2.y;
r.z = v1.z ^ v2.z;
}
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, T s)
{
r.x = v1.x ^ s;
r.y = v1.y ^ s;
r.z = v1.z ^ s;
}
};
template<IntType T>
struct compute_ivec3_left_shift<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, const Phanes::Core::Math::TIntVector3<T, false>& v2)
{
r.x = v1.x << v2.x;
r.y = v1.y << v2.y;
r.z = v1.z << v2.z;
}
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, T s)
{
r.x = v1.x << s;
r.y = v1.y << s;
r.z = v1.z << s;
}
};
template<IntType T>
struct compute_ivec3_right_shift<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, const Phanes::Core::Math::TIntVector3<T, false>& v2)
{
r.x = v1.x >> v2.x;
r.y = v1.y >> v2.y;
r.z = v1.z >> v2.z;
}
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1, T s)
{
r.x = v1.x >> s;
r.y = v1.y >> s;
r.z = v1.z >> s;
}
};
template<IntType T>
struct compute_ivec3_bnot<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector3<T, false>& r, const Phanes::Core::Math::TIntVector3<T, false>& v1)
{
r.x = ~v1.x;
r.y = ~v1.y;
r.z = ~v1.z;
}
};
}

View File

@@ -0,0 +1,365 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
namespace Phanes::Core::Math::Detail
{
template<IntType T, bool S>
struct construct_ivec4 {};
template<IntType T, bool S>
struct compute_ivec4_add {};
template<IntType T, bool S>
struct compute_ivec4_sub {};
template<IntType T, bool S>
struct compute_ivec4_mul {};
template<IntType T, bool S>
struct compute_ivec4_div {};
template<IntType T, bool S>
struct compute_ivec4_mod {};
template<IntType T, bool S>
struct compute_ivec4_eq {};
template<IntType T, bool S>
struct compute_ivec4_ieq {};
template<IntType T, bool S>
struct compute_ivec4_inc {};
template<IntType T, bool S>
struct compute_ivec4_dec {};
template<IntType T, bool S>
struct compute_ivec4_and {};
template<IntType T, bool S>
struct compute_ivec4_or {};
template<IntType T, bool S>
struct compute_ivec4_xor {};
template<IntType T, bool S>
struct compute_ivec4_left_shift {};
template<IntType T, bool S>
struct compute_ivec4_right_shift {};
template<IntType T, bool S>
struct compute_ivec4_bnot {};
template<IntType T>
struct construct_ivec4<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& v1, const TIntVector4<T, false>& v2)
{
v1.x = v2.x;
v1.y = v2.y;
v1.z = v2.z;
v1.w = v2.w;
}
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& v1, T s)
{
v1.x = s;
v1.y = s;
v1.z = s;
v1.w = s;
}
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& v1, T x, T y, T z, T w)
{
v1.x = x;
v1.y = y;
v1.z = z;
v1.w = w;
}
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& v1, const T* comp)
{
v1.x = comp[0];
v1.y = comp[1];
v1.z = comp[2];
v1.w = comp[3];
}
static constexpr void map(Phanes::Core::Math::TIntVector4<int, false>& r, const Phanes::Core::Math::TIntVector2<int, false>& v1, const Phanes::Core::Math::TIntVector2<int, false>& v2)
{
r.x = v1.x;
r.y = v1.y;
r.x = v2.x;
r.y = v2.y;
}
};
template<IntType T>
struct compute_ivec4_add<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, const Phanes::Core::Math::TIntVector4<T, false>& v2)
{
r.x = v1.x + v2.x;
r.y = v1.y + v2.y;
r.z = v1.z + v2.z;
r.w = v1.w + v2.w;
}
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, T s)
{
r.x = v1.x + s;
r.y = v1.y + s;
r.z = v1.z + s;
r.w = v1.w + s;
}
};
template<IntType T>
struct compute_ivec4_sub<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, const Phanes::Core::Math::TIntVector4<T, false>& v2)
{
r.x = v1.x - v2.x;
r.y = v1.y - v2.y;
r.z = v1.z - v2.z;
r.w = v1.w - v2.w;
}
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, T s)
{
r.x = v1.x - s;
r.y = v1.y - s;
r.z = v1.z - s;
r.w = v1.w - s;
}
};
template<IntType T>
struct compute_ivec4_mul<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, const Phanes::Core::Math::TIntVector4<T, false>& v2)
{
r.x = v1.x * v2.x;
r.y = v1.y * v2.y;
r.z = v1.z * v2.z;
r.w = v1.w * v2.w;
}
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, T s)
{
r.x = v1.x * s;
r.y = v1.y * s;
r.z = v1.z * s;
r.w = v1.w * s;
}
};
template<IntType T>
struct compute_ivec4_div<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, const Phanes::Core::Math::TIntVector4<T, false>& v2)
{
r.x = v1.x / v2.x;
r.y = v1.y / v2.y;
r.z = v1.z / v2.z;
r.w = v1.w / v2.w;
}
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, T s)
{
r.x = v1.x / s;
r.y = v1.y / s;
r.z = v1.z / s;
r.w = v1.w / s;
}
};
template<IntType T>
struct compute_ivec4_mod<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, const Phanes::Core::Math::TIntVector4<T, false>& v2)
{
r.x = v1.x % v2.x;
r.y = v1.y % v2.y;
r.z = v1.z % v2.z;
r.w = v1.w % v2.w;
}
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, T s)
{
r.x = v1.x % s;
r.y = v1.y % s;
r.z = v1.z % s;
r.w = v1.w % s;
}
};
template<IntType T>
struct compute_ivec4_eq<T, false>
{
static constexpr bool map(const Phanes::Core::Math::TIntVector4<T, false>& v1, const Phanes::Core::Math::TIntVector4<T, false>& v2)
{
return (v1.x == v2.x &&
v1.y == v2.y &&
v1.z == v2.z &&
v1.w == v2.w);
}
};
template<IntType T>
struct compute_ivec4_ieq<T, false>
{
static constexpr bool map(const Phanes::Core::Math::TIntVector4<T, false>& v1, const Phanes::Core::Math::TIntVector4<T, false>& v2)
{
return (v1.x != v2.x ||
v1.y != v2.y ||
v1.z != v2.z ||
v1.w != v2.w);
}
};
template<IntType T>
struct compute_ivec4_inc<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1)
{
r.x = v1.x + 1;
r.y = v1.y + 1;
r.z = v1.z + 1;
r.w = v1.w + 1;
}
};
template<IntType T>
struct compute_ivec4_dec<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1)
{
r.x = v1.x - 1;
r.y = v1.y - 1;
r.z = v1.z - 1;
r.w = v1.w - 1;
}
};
template<IntType T>
struct compute_ivec4_and<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, const Phanes::Core::Math::TIntVector4<T, false>& v2)
{
r.x = v1.x & v2.x;
r.y = v1.y & v2.y;
r.z = v1.z & v2.z;
r.w = v1.w & v2.w;
}
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, T s)
{
r.x = v1.x & s;
r.y = v1.y & s;
r.z = v1.z & s;
r.w = v1.w & s;
}
};
template<IntType T>
struct compute_ivec4_or<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, const Phanes::Core::Math::TIntVector4<T, false>& v2)
{
r.x = v1.x | v2.x;
r.y = v1.y | v2.y;
r.z = v1.z | v2.z;
r.w = v1.w | v2.w;
}
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, T s)
{
r.x = v1.x | s;
r.y = v1.y | s;
r.z = v1.z | s;
r.w = v1.w | s;
}
};
template<IntType T>
struct compute_ivec4_xor<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, const Phanes::Core::Math::TIntVector4<T, false>& v2)
{
r.x = v1.x ^ v2.x;
r.y = v1.y ^ v2.y;
r.z = v1.z ^ v2.z;
r.w = v1.w ^ v2.w;
}
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, T s)
{
r.x = v1.x ^ s;
r.y = v1.y ^ s;
r.z = v1.z ^ s;
r.w = v1.w ^ s;
}
};
template<IntType T>
struct compute_ivec4_left_shift<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, const Phanes::Core::Math::TIntVector4<T, false>& v2)
{
r.x = v1.x << v2.x;
r.y = v1.y << v2.y;
r.z = v1.z << v2.z;
r.w = v1.w << v2.w;
}
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, T s)
{
r.x = v1.x << s;
r.y = v1.y << s;
r.z = v1.z << s;
r.w = v1.w << s;
}
};
template<IntType T>
struct compute_ivec4_right_shift<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, const Phanes::Core::Math::TIntVector4<T, false>& v2)
{
r.x = v1.x >> v2.x;
r.y = v1.y >> v2.y;
r.z = v1.z >> v2.z;
r.w = v1.w >> v2.w;
}
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1, T s)
{
r.x = v1.x >> s;
r.y = v1.y >> s;
r.z = v1.z >> s;
r.w = v1.w >> s;
}
};
template<IntType T>
struct compute_ivec4_bnot<T, false>
{
static constexpr void map(Phanes::Core::Math::TIntVector4<T, false>& r, const Phanes::Core::Math::TIntVector4<T, false>& v1)
{
r.x = ~v1.x;
r.y = ~v1.y;
}
};
}

View File

@@ -0,0 +1,53 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathCommon.hpp"
namespace Phanes::Core::Math::Detail
{
template<RealType T, bool S>
struct compute_mat3_transpose {};
template<RealType T, bool S>
struct compute_mat3_mul {};
template<RealType T>
struct compute_mat3_transpose<T, false>
{
static constexpr void map(Phanes::Core::Math::TMatrix3<T, false>& r, const TMatrix3<T, false>& m1)
{
r = TMatrix3<T, false>(m1(0, 0), m1(1, 0), m1(2, 0),
m1(0, 1), m1(1, 1), m1(2, 1),
m1(0, 2), m1(1, 2), m1(2, 2)
);
}
};
template<RealType T>
struct compute_mat3_mul<T, false>
{
static constexpr void map(Phanes::Core::Math::TMatrix3<T, false>& r, const TMatrix3<T, false>& m1, const TMatrix3<T, false>& m2)
{
r(0, 0) = m1(0, 0) * m2(0, 0) + m1(0, 1) * m2(1, 0) + m1(0, 2) * m2(2, 0);
r(0, 1) = m1(0, 0) * m2(0, 1) + m1(0, 1) * m2(1, 1) + m1(0, 2) * m2(2, 1);
r(0, 2) = m1(0, 0) * m2(0, 2) + m1(0, 1) * m2(1, 2) + m1(0, 2) * m2(2, 2);
r(1, 0) = m1(1, 0) * m2(0, 0) + m1(1, 1) * m2(1, 0) + m1(1, 2) * m2(2, 0);
r(1, 1) = m1(1, 0) * m2(0, 1) + m1(1, 1) * m2(1, 1) + m1(1, 2) * m2(2, 1);
r(1, 2) = m1(1, 0) * m2(0, 2) + m1(1, 1) * m2(1, 2) + m1(1, 2) * m2(2, 2);
r(2, 0) = m1(2, 0) * m2(0, 0) + m1(2, 1) * m2(1, 0) + m1(2, 2) * m2(2, 0);
r(2, 1) = m1(2, 0) * m2(0, 1) + m1(2, 1) * m2(1, 1) + m1(2, 2) * m2(2, 1);
r(2, 2) = m1(2, 0) * m2(0, 2) + m1(2, 1) * m2(1, 2) + m1(2, 2) * m2(2, 2);
}
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const TMatrix3<T, false>& m1, const TVector3<T, false>& v)
{
r.x = m1(0, 0) * v.x + m1(0, 1) * v.y + m1(0, 2) * v.z;
r.y = m1(1, 0) * v.x + m1(1, 1) * v.y + m1(1, 2) * v.z;
r.z = m1(2, 0) * v.x + m1(2, 1) * v.y + m1(2, 2) * v.z;
}
};
}

View File

@@ -0,0 +1,136 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathCommon.hpp"
namespace Phanes::Core::Math::Detail
{
template<RealType T, bool S>
struct compute_mat4_det {};
template<RealType T, bool S>
struct compute_mat4_inv {};
template<RealType T, bool S>
struct compute_mat4_transpose {};
template<RealType T, bool S>
struct compute_mat4_mul {};
template<RealType T>
struct compute_mat4_det<T, false>
{
static constexpr T map(const Phanes::Core::Math::TMatrix4<T, false>& m)
{
const TVector3<T, false>& a = reinterpret_cast<const TVector3<T, false>&>(m[0]);
const TVector3<T, false>& b = reinterpret_cast<const TVector3<T, false>&>(m[1]);
const TVector3<T, false>& c = reinterpret_cast<const TVector3<T, false>&>(m[2]);
const TVector3<T, false>& d = reinterpret_cast<const TVector3<T, false>&>(m[3]);
const float& x = m(3, 0);
const float& y = m(3, 1);
const float& z = m(3, 2);
const float& w = m(3, 3);
TVector3<T, false> s = CrossP(a, b);
TVector3<T, false> t = CrossP(c, d);
TVector3<T, false> u = a * y - b * x;
TVector3<T, false> v = c * w - d * z;
return DotP(s, v) + DotP(t, u);
}
};
template<RealType T>
struct compute_mat4_inv<T, false>
{
static constexpr bool map(Phanes::Core::Math::TMatrix4<T, false>& r, const Phanes::Core::Math::TMatrix4<T, false>& m)
{
const TVector3<T, false>& a = reinterpret_cast<const TVector3<T, false>&>(m[0]);
const TVector3<T, false>& b = reinterpret_cast<const TVector3<T, false>&>(m[1]);
const TVector3<T, false>& c = reinterpret_cast<const TVector3<T, false>&>(m[2]);
const TVector3<T, false>& d = reinterpret_cast<const TVector3<T, false>&>(m[3]);
const float& x = m(3, 0);
const float& y = m(3, 1);
const float& z = m(3, 2);
const float& w = m(3, 3);
TVector3<T, false> s = CrossP(a, b);
TVector3<T, false> t = CrossP(c, d);
TVector3<T, false> u = a * y - b * x;
TVector3<T, false> v = c * w - d * z;
float _1_det = (T)1.0 / (DotP(s, v) + DotP(t, u));
if (_1_det == (T)0.0)
{
return false;
}
s *= _1_det;
t *= _1_det;
u *= _1_det;
v *= _1_det;
TVector3<T, false> r0 = CrossP(b, v) + t * y;
TVector3<T, false> r1 = CrossP(v, a) - t * x;
TVector3<T, false> r2 = CrossP(d, u) + s * w;
TVector3<T, false> r3 = CrossP(u, c) - s * z;
r = TMatrix4<T, false>(r0.x, r0.y, r0.z, -DotP(b, t),
r1.x, r1.y, r1.z, DotP(a, t),
r2.x, r2.y, r2.z, -DotP(d, s),
r3.x, r3.y, r3.z, DotP(c, s));
return true;
}
};
template<RealType T>
struct compute_mat4_transpose<T, false>
{
static constexpr void map(Phanes::Core::Math::TMatrix4<T, false>& r, const Phanes::Core::Math::TMatrix4<T, false>& m)
{
r = Phanes::Core::Math::TMatrix4<T, false>(m(0, 0), m(1, 0), m(2, 0), m(3, 0),
m(0, 1), m(1, 1), m(2, 1), m(3, 1),
m(0, 2), m(1, 2), m(2, 2), m(3, 2),
m(0, 3), m(1, 3), m(2, 3), m(3, 3));
}
};
template<RealType T>
struct compute_mat4_mul<T, false>
{
static constexpr void map(Phanes::Core::Math::TMatrix4<T, false>& r, const Phanes::Core::Math::TMatrix4<T, false>& m1, const Phanes::Core::Math::TMatrix4<T, false>& m2)
{
r(0, 0) = m1(0, 0) * m2(0, 0) + m1(0, 1) * m2(1, 0) + m1(0, 2) * m2(2, 0) + m1(0, 3) * m2(3, 0);
r(0, 1) = m1(0, 0) * m2(0, 1) + m1(0, 1) * m2(1, 1) + m1(0, 2) * m2(2, 1) + m1(0, 3) * m2(3, 1);
r(0, 2) = m1(0, 0) * m2(0, 2) + m1(0, 1) * m2(1, 2) + m1(0, 2) * m2(2, 2) + m1(0, 3) * m2(3, 2);
r(0, 3) = m1(0, 0) * m2(0, 3) + m1(0, 1) * m2(1, 3) + m1(0, 2) * m2(2, 3) + m1(0, 3) * m2(3, 3);
r(1, 0) = m1(1, 0) * m2(0, 0) + m1(1, 1) * m2(1, 0) + m1(1, 2) * m2(2, 0) + m1(1, 3) * m2(3, 0);
r(1, 1) = m1(1, 0) * m2(0, 1) + m1(1, 1) * m2(1, 1) + m1(1, 2) * m2(2, 1) + m1(1, 3) * m2(3, 1);
r(1, 2) = m1(1, 0) * m2(0, 2) + m1(1, 1) * m2(1, 2) + m1(1, 2) * m2(2, 2) + m1(1, 3) * m2(3, 2);
r(1, 3) = m1(1, 0) * m2(0, 3) + m1(1, 1) * m2(1, 3) + m1(1, 2) * m2(2, 3) + m1(1, 3) * m2(3, 3);
r(2, 0) = m1(2, 0) * m2(0, 0) + m1(2, 1) * m2(1, 0) + m1(2, 2) * m2(2, 0) + m1(2, 3) * m2(3, 0);
r(2, 1) = m1(2, 0) * m2(0, 1) + m1(2, 1) * m2(1, 1) + m1(2, 2) * m2(2, 1) + m1(2, 3) * m2(3, 1);
r(2, 2) = m1(2, 0) * m2(0, 2) + m1(2, 1) * m2(1, 2) + m1(2, 2) * m2(2, 2) + m1(2, 3) * m2(3, 2);
r(2, 3) = m1(2, 0) * m2(0, 3) + m1(2, 1) * m2(1, 3) + m1(2, 2) * m2(2, 3) + m1(2, 3) * m2(3, 3);
r(3, 0) = m1(3, 0) * m2(0, 0) + m1(3, 1) * m2(1, 0) + m1(3, 2) * m2(2, 0) + m1(3, 3) * m2(3, 0);
r(3, 1) = m1(3, 0) * m2(0, 1) + m1(3, 1) * m2(1, 1) + m1(3, 2) * m2(2, 1) + m1(3, 3) * m2(3, 1);
r(3, 2) = m1(3, 0) * m2(0, 2) + m1(3, 1) * m2(1, 2) + m1(3, 2) * m2(2, 2) + m1(3, 3) * m2(3, 2);
r(3, 3) = m1(3, 0) * m2(0, 3) + m1(3, 1) * m2(1, 3) + m1(3, 2) * m2(2, 3) + m1(3, 3) * m2(3, 3);
}
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TMatrix4<T, false>& m1, const Phanes::Core::Math::TVector4<T, false>& v)
{
r.x = m1(0, 0) * v.x + m1(0, 1) * v.y + m1(0, 2) * v.z + m1(0, 3) * v.w;
r.y = m1(1, 0) * v.x + m1(1, 1) * v.y + m1(1, 2) * v.z + m1(1, 3) * v.w;
r.z = m1(2, 0) * v.x + m1(2, 1) * v.y + m1(2, 2) * v.z + m1(2, 3) * v.w;
r.w = m1(3, 0) * v.x + m1(3, 1) * v.y + m1(3, 2) * v.z + m1(3, 3) * v.w;
}
};
}

View File

@@ -0,0 +1,107 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
namespace Phanes::Core::Math::Detail
{
template<RealType T, bool S>
struct construct_plane {};
template<RealType T, bool S>
struct compute_plane_add {};
template<RealType T, bool S>
struct compute_plane_sub {};
template<RealType T, bool S>
struct compute_plane_mul {};
template<RealType T, bool S>
struct compute_plane_div {};
template<RealType T>
struct construct_plane<T, false>
{
static constexpr void map(TPlane<T, false>& r, const TVector3<T, false>& normal, T d)
{
r.normal = normal;
r.d = d;
}
static constexpr void map(TPlane<T, false>& r, const TVector3<T, false>& normal, const TVector3<T, false>& base)
{
r.normal = std::copy(normal);
r.d = DotP(r.normal, base);
}
static constexpr void map(TPlane<T, false>& r, T x, T y, T z, T d)
{
r.normal = TVector3<T, false>(x, y, z);
r.d = d;
}
static constexpr void map(TPlane<T, false>& r, const TVector3<T, false>& v1, const TVector3<T, false>& v2, const TVector3<T, false>& v3)
{
r.normal = Normalize(CrossP(v1, v2));
r.d = DotP(r.normal, v3);
}
};
template<RealType T>
struct compute_plane_add<T, false>
{
static constexpr void map(TPlane<T, false>& r, const TPlane<T, false>& pl1, const TPlane<T, false>& pl2)
{
r.comp = pl1.comp + pl2.comp;
}
static constexpr void map(TPlane<T, false>& r, const TPlane<T, false>& pl1, T s)
{
r.comp = pl1.comp + s;
}
};
template<RealType T>
struct compute_plane_sub<T, false>
{
static constexpr void map(TPlane<T, false>& r, const TPlane<T, false>& pl1, const TPlane<T, false>& pl2)
{
r.comp = pl1.comp - pl2.comp;
}
static constexpr void map(TPlane<T, false>& r, const TPlane<T, false>& pl1, T s)
{
r.comp = pl1.comp - s;
}
};
template<RealType T>
struct compute_plane_mul<T, false>
{
static constexpr void map(TPlane<T, false>& r, const TPlane<T, false>& pl1, const TPlane<T, false>& pl2)
{
r.comp = pl1.comp * pl2.comp;
}
static constexpr void map(TPlane<T, false>& r, const TPlane<T, false>& pl1, T s)
{
r.comp = pl1.comp * s;
}
};
template<RealType T>
struct compute_plane_div<T, false>
{
static constexpr void map(TPlane<T, false>& r, const TPlane<T, false>& pl1, const TPlane<T, false>& pl2)
{
r.comp = pl1.comp / pl2.comp;
}
static constexpr void map(TPlane<T, false>& r, const TPlane<T, false>& pl1, T s)
{
r.comp = pl1.comp / s;
}
};
}

View File

@@ -0,0 +1,266 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include <iostream>
namespace Phanes::Core::Math::Detail
{
template<RealType T, bool S>
struct construct_vec2 {};
template<RealType T, bool S>
struct compute_vec2_add {};
template<RealType T, bool S>
struct compute_vec2_sub {};
template<RealType T, bool S>
struct compute_vec2_mul {};
template<RealType T, bool S>
struct compute_vec2_div {};
template<RealType T, bool S>
struct compute_vec2_inc {};
template<RealType T, bool S>
struct compute_vec2_dec {};
// Magnitude
template<RealType T, bool S>
struct compute_vec2_mag {};
// Dot product
template<RealType T, bool S>
struct compute_vec2_dotp {};
// Max
template<RealType T, bool S>
struct compute_vec2_max {};
// Min
template<RealType T, bool S>
struct compute_vec2_min {};
// Set
template<RealType T, bool S>
struct compute_vec2_set {};
template<RealType T>
struct construct_vec2<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& v1, const TVector2<T, false>& v2)
{
v1.x = v2.x;
v1.y = v2.y;
}
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& v1, T s)
{
v1.x = s;
v1.y = s;
}
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& v1, T x, T y)
{
v1.x = x;
v1.y = y;
}
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& v1, const T* comp)
{
v1.x = comp[0];
v1.y = comp[1];
}
};
template<RealType T>
struct compute_vec2_add<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& r, const Phanes::Core::Math::TVector2<T, false>& v1, const Phanes::Core::Math::TVector2<T, false>& v2)
{
r.x = v1.x + v2.x;
r.y = v1.y + v2.y;
}
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& r, const Phanes::Core::Math::TVector2<T, false>& v1, T s)
{
r.x = v1.x + s;
r.y = v1.y + s;
}
};
template<RealType T>
struct compute_vec2_sub<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& r, const Phanes::Core::Math::TVector2<T, false>& v1, const Phanes::Core::Math::TVector2<T, false>& v2)
{
r.x = v1.x - v2.x;
r.y = v1.y - v2.y;
}
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& r, const Phanes::Core::Math::TVector2<T, false>& v1, T s)
{
r.x = v1.x - s;
r.y = v1.y - s;
}
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& r, T s, const Phanes::Core::Math::TVector2<T, false>& v1)
{
r.x = s - v1.x;
r.y = s - v1.y;
}
};
template<RealType T>
struct compute_vec2_mul<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& r, const Phanes::Core::Math::TVector2<T, false>& v1, const Phanes::Core::Math::TVector2<T, false>& v2)
{
r.x = v1.x * v2.x;
r.y = v1.y * v2.y;
}
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& r, const Phanes::Core::Math::TVector2<T, false>& v1, T s)
{
r.x = v1.x * s;
r.y = v1.y * s;
}
};
template<RealType T>
struct compute_vec2_div<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& r, const Phanes::Core::Math::TVector2<T, false>& v1, const Phanes::Core::Math::TVector2<T, false>& v2)
{
r.x = v1.x / v2.x;
r.y = v1.y / v2.y;
}
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& r, const Phanes::Core::Math::TVector2<T, false>& v1, T s)
{
s = (T)1.0 / s;
r.x = v1.x * s;
r.y = v1.y * s;
}
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& r, T s, const Phanes::Core::Math::TVector2<T, false>& v1)
{
r.x = s / v1.x;
r.y = s / v1.y;
}
};
template<RealType T, bool S>
struct compute_vec2_eq
{
static constexpr bool map(const Phanes::Core::Math::TVector2<T, S>& v1, const Phanes::Core::Math::TVector2<T, S>& v2)
{
return (Phanes::Core::Math::Abs(v1.x - v2.x) < P_FLT_INAC &&
Phanes::Core::Math::Abs(v1.y - v2.y) < P_FLT_INAC);
}
};
template<RealType T, bool S>
struct compute_vec2_ieq
{
static constexpr bool map(const Phanes::Core::Math::TVector2<T, S>& v1, const Phanes::Core::Math::TVector2<T, S>& v2)
{
return (Phanes::Core::Math::Abs(v1.x - v2.x) > P_FLT_INAC ||
Phanes::Core::Math::Abs(v1.y - v2.y) > P_FLT_INAC);
}
};
template<RealType T>
struct compute_vec2_inc<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& r, const Phanes::Core::Math::TVector2<T, false>& v1)
{
r.x = v1.x + 1;
r.y = v1.y + 1;
}
};
template<RealType T>
struct compute_vec2_dec<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& r, const Phanes::Core::Math::TVector2<T, false>& v1)
{
r.x = v1.x - 1;
r.y = v1.y - 1;
}
};
template<RealType T>
struct compute_vec2_mag<T, false>
{
static constexpr T map(const Phanes::Core::Math::TVector2<T, false>& v1)
{
return sqrt(v1.x * v1.x + v1.y * v1.y);
}
};
template<RealType T>
struct compute_vec2_dotp<T, false>
{
static constexpr T map(const Phanes::Core::Math::TVector2<T, false>& v1, const Phanes::Core::Math::TVector2<T, false>& v2)
{
return v1.x * v2.x + v1.y * v2.y;
}
};
template<RealType T>
struct compute_vec2_max<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& r, const Phanes::Core::Math::TVector2<T, false>& v1, const Phanes::Core::Math::TVector2<T, false>& v2)
{
r.x = (v1.x > v2.x) ? v1.x : v2.x;
r.y = (v1.y > v2.y) ? v1.y : v2.y;
}
};
template<RealType T>
struct compute_vec2_min<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& r, const Phanes::Core::Math::TVector2<T, false>& v1, const Phanes::Core::Math::TVector2<T, false>& v2)
{
r.x = (v1.x < v2.x) ? v1.x : v2.x;
r.y = (v1.y < v2.y) ? v1.y : v2.y;
}
};
template<RealType T>
struct compute_vec2_set<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector2<T, false>& v1, T x, T y)
{
v1.x = x;
v1.y = y;
}
};
}

View File

@@ -0,0 +1,320 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
namespace Phanes::Core::Math::Detail
{
template<RealType T, bool S>
struct construct_vec3 {};
template<RealType T, bool S>
struct move_vec3 {};
template<RealType T, bool S>
struct compute_vec3_add {};
template<RealType T, bool S>
struct compute_vec3_sub {};
template<RealType T, bool S>
struct compute_vec3_mul {};
template<RealType T, bool S>
struct compute_vec3_div {};
template<RealType T, bool S>
struct compute_vec3_eq {};
template<RealType T, bool S>
struct compute_vec3_ieq {};
template<RealType T, bool S>
struct compute_vec3_inc {};
template<RealType T, bool S>
struct compute_vec3_dec {};
// Cross product
template<RealType T, bool S>
struct compute_vec3_cross_p {};
// Magnitude
template<RealType T, bool S>
struct compute_vec3_mag {};
// dot product
template<RealType T, bool S>
struct compute_vec3_dotp {};
// set
template<RealType T, bool S>
struct compute_vec3_set {};
// clamp to cube
template<RealType T, bool S>
struct compute_vec3_clamp {};
// max
template<RealType T, bool S>
struct compute_vec3_max {};
// min
template<RealType T, bool S>
struct compute_vec3_min {};
template<RealType T>
struct construct_vec3<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const TVector3<T, false>& v1)
{
memcpy(r.data, v1.data, 4 * sizeof(T));
}
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, T s)
{
r.x = s;
r.y = s;
r.z = s;
r.w = (T)0.0;
}
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, T x, T y, T z)
{
r.x = x;
r.y = y;
r.z = z;
r.w = (T)0.0;
}
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector2<T, false>& v1, T s)
{
r.x = v1.x;
r.y = v1.y;
r.z = s;
r.w = (T)0.0;
}
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const T* comp)
{
memcpy(r.data, comp, 3 * sizeof(T));
r.w = (T)0.0;
}
};
template<RealType T>
struct compute_vec3_add<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector3<T, false>& v1, const Phanes::Core::Math::TVector3<T, false>& v2)
{
r.x = v1.x + v2.x;
r.y = v1.y + v2.y;
r.z = v1.z + v2.z;
}
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector3<T, false>& v1, T s)
{
r.x = v1.x + s;
r.y = v1.y + s;
r.z = v1.z + s;
}
};
template<RealType T>
struct compute_vec3_sub<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector3<T, false>& v1, const Phanes::Core::Math::TVector3<T, false>& v2)
{
r.x = v1.x - v2.x;
r.y = v1.y - v2.y;
r.z = v1.z - v2.z;
}
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector3<T, false>& v1, T s)
{
r.x = v1.x - s;
r.y = v1.y - s;
r.z = v1.z - s;
}
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, T s, const Phanes::Core::Math::TVector3<T, false>& v1)
{
r.x = s - v1.x;
r.y = s - v1.y;
r.z = s - v1.z;
}
};
template<RealType T>
struct compute_vec3_mul<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector3<T, false>& v1, const Phanes::Core::Math::TVector3<T, false>& v2)
{
r.x = v1.x * v2.x;
r.y = v1.y * v2.y;
r.z = v1.z * v2.z;
}
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector3<T, false>& v1, T s)
{
r.x = v1.x * s;
r.y = v1.y * s;
r.z = v1.z * s;
}
};
template<RealType T>
struct compute_vec3_div<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector3<T, false>& v1, const Phanes::Core::Math::TVector3<T, false>& v2)
{
r.x = v1.x / v2.x;
r.y = v1.y / v2.y;
r.z = v1.z / v2.z;
}
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector3<T, false>& v1, T s)
{
s = (T)1.0 / s;
r.x = v1.x * s;
r.y = v1.y * s;
r.z = v1.z * s;
}
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, T s, const Phanes::Core::Math::TVector3<T, false>& v1)
{
r.x = s / v1.x;
r.y = s / v1.y;
r.z = s / v1.z;
}
};
template<RealType T>
struct compute_vec3_eq<T, false>
{
static constexpr bool map(const Phanes::Core::Math::TVector3<T, false>& v1, const Phanes::Core::Math::TVector3<T, false>& v2)
{
return (Phanes::Core::Math::Abs(v1.x - v2.x) < P_FLT_INAC &&
Phanes::Core::Math::Abs(v1.y - v2.y) < P_FLT_INAC &&
Phanes::Core::Math::Abs(v1.z - v2.z) < P_FLT_INAC);
}
};
template<RealType T>
struct compute_vec3_ieq<T, false>
{
static constexpr bool map(const Phanes::Core::Math::TVector3<T, false>& v1, const Phanes::Core::Math::TVector3<T, false>& v2)
{
return (Phanes::Core::Math::Abs(v1.x - v2.x) > P_FLT_INAC ||
Phanes::Core::Math::Abs(v1.y - v2.y) > P_FLT_INAC ||
Phanes::Core::Math::Abs(v1.z - v2.z) > P_FLT_INAC);
}
};
template<RealType T>
struct compute_vec3_inc<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector3<T, false>& v1)
{
r.x = v1.x + 1;
r.y = v1.y + 1;
r.z = v1.z + 1;
}
};
template<RealType T>
struct compute_vec3_dec<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector3<T, false>& v1)
{
r.x = v1.x - 1;
r.y = v1.y - 1;
r.z = v1.z - 1;
}
};
template<RealType T>
struct compute_vec3_cross_p<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector3<T, false> v1, const Phanes::Core::Math::TVector3<T, false>& v2)
{
// V1 has to be copied, as otherwise changes to r affect calculation -> r is v1.
r.x = (v1.y * v2.z) - (v1.z * v2.y);
r.y = (v1.z * v2.x) - (v1.x * v2.z);
r.z = (v1.x * v2.y) - (v1.y * v2.x);
}
};
template<RealType T>
struct compute_vec3_mag<T, false>
{
static constexpr T map(const Phanes::Core::Math::TVector3<T, false>& v1)
{
return sqrt(v1.x * v1.x + v1.y * v1.y + v1.z * v1.z);
}
};
template<RealType T>
struct compute_vec3_dotp<T, false>
{
static constexpr T map(const Phanes::Core::Math::TVector3<T, false>& v1, const Phanes::Core::Math::TVector3<T, false>& v2)
{
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}
};
template<RealType T>
struct compute_vec3_set<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& v1, T x, T y, T z)
{
v1.x = x;
v1.y = y;
v1.z = z;
}
};
template<RealType T>
struct compute_vec3_clamp<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector3<T, false>& v1, T radius)
{
r.x = Clamp(v1.x, -radius, radius);
r.y = Clamp(v1.y, -radius, radius);
r.z = Clamp(v1.z, -radius, radius);
}
};
template<RealType T>
struct compute_vec3_max<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector3<T, false>& v1, const Phanes::Core::Math::TVector3<T, false>& v2)
{
r.x = (v1.x > v2.x) ? v1.x : v2.x;
r.y = (v1.y > v2.y) ? v1.y : v2.y;
r.z = (v1.z > v2.z) ? v1.z : v2.z;
}
};
template<RealType T>
struct compute_vec3_min<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector3<T, false>& r, const Phanes::Core::Math::TVector3<T, false>& v1, const Phanes::Core::Math::TVector3<T, false>& v2)
{
r.x = (v1.x < v2.x) ? v1.x : v2.x;
r.y = (v1.y < v2.y) ? v1.y : v2.y;
r.z = (v1.z < v2.z) ? v1.z : v2.z;
}
};
}

View File

@@ -0,0 +1,328 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
namespace Phanes::Core::Math::Detail
{
template<RealType T, bool S>
struct construct_vec4 {};
template<RealType T, bool S>
struct move_vec4 {};
template<RealType T, bool S>
struct compute_vec4_add {};
template<RealType T, bool S>
struct compute_vec4_sub {};
template<RealType T, bool S>
struct compute_vec4_mul {};
template<RealType T, bool S>
struct compute_vec4_div {};
template<RealType T, bool S>
struct compute_vec4_eq {};
template<RealType T, bool S>
struct compute_vec4_ieq {};
template<RealType T, bool S>
struct compute_vec4_inc {};
template<RealType T, bool S>
struct compute_vec4_dec {};
// Magnitude
template<RealType T, bool S>
struct compute_vec4_mag {};
// dot product
template<RealType T, bool S>
struct compute_vec4_dotp {};
// set
template<RealType T, bool S>
struct compute_vec4_set {};
// max
template<RealType T, bool S>
struct compute_vec4_max {};
// min
template<RealType T, bool S>
struct compute_vec4_min {};
// perspective divide
template<RealType T, bool S>
struct compute_vec4_pdiv {};
template<RealType T>
struct construct_vec4<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const TVector4<T, false>& v1)
{
memcpy(r.data, v1.data, 4 * sizeof(T));
}
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, T s)
{
r.x = s;
r.y = s;
r.z = s;
r.w = s;
}
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, T x, T y, T z, T w)
{
r.x = x;
r.y = y;
r.z = z;
r.w = w;
}
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector2<T, false>& v2, const Phanes::Core::Math::TVector2<T, false>& v3)
{
r.x = v2.x;
r.y = v2.y;
r.z = v3.x;
r.w = v3.y;
}
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector3<T, false>& v, T w)
{
r.x = v.x;
r.y = v.y;
r.z = v.z;
r.w = w;
}
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const T* comp)
{
memcpy(r.data, comp, 4 * sizeof(T));
}
};
template<RealType T>
struct compute_vec4_add<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector4<T, false>& v1, const Phanes::Core::Math::TVector4<T, false>& v2)
{
r.x = v1.x + v2.x;
r.y = v1.y + v2.y;
r.z = v1.z + v2.z;
r.w = v1.w + v2.w;
}
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector4<T, false>& v1, T s)
{
r.x = v1.x + s;
r.y = v1.y + s;
r.z = v1.z + s;
r.w = v1.w + s;
}
};
template<RealType T>
struct compute_vec4_sub<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector4<T, false>& v1, const Phanes::Core::Math::TVector4<T, false>& v2)
{
r.x = v1.x - v2.x;
r.y = v1.y - v2.y;
r.z = v1.z - v2.z;
r.w = v1.w - v2.w;
}
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector4<T, false>& v1, T s)
{
r.x = v1.x - s;
r.y = v1.y - s;
r.z = v1.z - s;
r.w = v1.w - s;
}
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, T s, const Phanes::Core::Math::TVector4<T, false>& v1)
{
r.x = s - v1.x;
r.y = s - v1.y;
r.z = s - v1.z;
r.w = s - v1.w;
}
};
template<RealType T>
struct compute_vec4_mul<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector4<T, false>& v1, const Phanes::Core::Math::TVector4<T, false>& v2)
{
r.x = v1.x * v2.x;
r.y = v1.y * v2.y;
r.z = v1.z * v2.z;
r.w = v1.w * v2.w;
}
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector4<T, false>& v1, T s)
{
r.x = v1.x * s;
r.y = v1.y * s;
r.z = v1.z * s;
r.w = v1.w * s;
}
};
template<RealType T>
struct compute_vec4_div<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector4<T, false>& v1, const Phanes::Core::Math::TVector4<T, false>& v2)
{
r.x = v1.x / v2.x;
r.y = v1.y / v2.y;
r.z = v1.z / v2.z;
r.w = v1.w / v2.w;
}
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector4<T, false>& v1, T s)
{
s = (T)1.0 / s;
r.x = v1.x * s;
r.y = v1.y * s;
r.z = v1.z * s;
r.w = v1.w * s;
}
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, T s, const Phanes::Core::Math::TVector4<T, false>& v1)
{
r.x = s / v1.x;
r.y = s / v1.y;
r.z = s / v1.z;
r.w = s / v1.w;
}
};
template<RealType T>
struct compute_vec4_eq<T, false>
{
static constexpr bool map(const Phanes::Core::Math::TVector4<T, false>& v1, const Phanes::Core::Math::TVector4<T, false>& v2)
{
return (Phanes::Core::Math::Abs(v1.x - v2.x) < P_FLT_INAC &&
Phanes::Core::Math::Abs(v1.y - v2.y) < P_FLT_INAC &&
Phanes::Core::Math::Abs(v1.z - v2.z) < P_FLT_INAC &&
Phanes::Core::Math::Abs(v1.w - v2.w) < P_FLT_INAC);
}
};
template<RealType T>
struct compute_vec4_ieq<T, false>
{
static constexpr bool map(const Phanes::Core::Math::TVector4<T, false>& v1, const Phanes::Core::Math::TVector4<T, false>& v2)
{
return (Phanes::Core::Math::Abs(v1.x - v2.x) > P_FLT_INAC ||
Phanes::Core::Math::Abs(v1.y - v2.y) > P_FLT_INAC ||
Phanes::Core::Math::Abs(v1.z - v2.z) > P_FLT_INAC ||
Phanes::Core::Math::Abs(v1.w - v2.w) > P_FLT_INAC);
}
};
template<RealType T>
struct compute_vec4_inc<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector4<T, false>& v1)
{
r.x = v1.x + 1;
r.y = v1.y + 1;
r.z = v1.z + 1;
r.w = v1.w + 1;
}
};
template<RealType T>
struct compute_vec4_dec<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector4<T, false>& v1)
{
r.x = v1.x - 1;
r.y = v1.y - 1;
r.z = v1.z - 1;
r.w = v1.w - 1;
}
};
template<RealType T>
struct compute_vec4_mag<T, false>
{
static constexpr T map(const Phanes::Core::Math::TVector4<T, false>& v1)
{
return sqrt(v1.x * v1.x + v1.y * v1.y + v1.z * v1.z + v1.w * v1.w);
}
};
template<RealType T>
struct compute_vec4_dotp<T, false>
{
static constexpr T map(const Phanes::Core::Math::TVector4<T, false>& v1, const Phanes::Core::Math::TVector4<T, false>& v2)
{
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
}
};
template<RealType T>
struct compute_vec4_set<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& v1, T x, T y, T z, T w)
{
v1.x = x;
v1.y = y;
v1.z = z;
v1.w = w;
}
};
template<RealType T>
struct compute_vec4_max<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector4<T, false>& v1, const Phanes::Core::Math::TVector4<T, false>& v2)
{
r.x = (v1.x > v2.x) ? v1.x : v2.x;
r.y = (v1.y > v2.y) ? v1.y : v2.y;
r.z = (v1.z > v2.z) ? v1.z : v2.z;
r.w = (v1.w > v2.w) ? v1.w : v2.w;
}
};
template<RealType T>
struct compute_vec4_min<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector4<T, false>& v1, const Phanes::Core::Math::TVector4<T, false>& v2)
{
r.x = (v1.x < v2.x) ? v1.x : v2.x;
r.y = (v1.y < v2.y) ? v1.y : v2.y;
r.z = (v1.z < v2.z) ? v1.z : v2.z;
r.w = (v1.w < v2.w) ? v1.w : v2.w;
}
};
template<RealType T>
struct compute_vec4_pdiv<T, false>
{
static constexpr void map(Phanes::Core::Math::TVector4<T, false>& r, const Phanes::Core::Math::TVector4<T, false>& v1)
{
T _1_w = (T)1.0 / v1.w;
r.x = v1.x * _1_w;
r.y = v1.y * _1_w;
r.z = v1.z * _1_w;
r.w = (T)0.0;
}
};
}

View File

@@ -0,0 +1,39 @@
#pragma once
#ifndef P_DEBUG
#pragma warning(disable : 4244)
#endif
#include "Core/public/Math/MathFwd.h"
// --- Vectors ------------------------
#include "Core/public/Math/Vector2.hpp"
#include "Core/public/Math/Vector3.hpp"
#include "Core/public/Math/Vector4.hpp"
#include "Core/public/Math/IntVector2.hpp"
#include "Core/public/Math/IntVector3.hpp"
#include "Core/public/Math/IntVector4.hpp"
#include "Core/public/Math/Point.hpp"
#include "Core/public/Math/IntPoint.hpp"
// --- Matrices ------------------------
#include "Core/public/Math/Matrix2.hpp"
#include "Core/public/Math/Matrix3.hpp"
#include "Core/public/Math/Matrix4.hpp"
// --- Other Math ----------------------
#include "Core/public/Math/Plane.hpp"
#include "Core/public/Math/Line.hpp"
// --- Misc -----------------
#include "Core/public/Math/MathTypeConversion.hpp"
#include "Core/public/Math/MathUnitConversion.hpp"

View File

@@ -0,0 +1,146 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathCommon.hpp"
#include "Core/public/Math/MathAbstractTypes.h"
#include "Core/public/Math/MathFwd.h"
#include "Core/public/Math/IntVector2.hpp"
#include "Core/public/Math/IntVector3.hpp"
#include "Core/public/Math/IntVector4.hpp"
#ifndef P_DEBUG
#pragma warning(disable : 4244)
#endif
/**
* General annonation: The Point is the same as a vector. The type exists, to ensure a
* easy differentiation between the two.
*/
#ifndef INTPOINT_H
#define INTPOINT_H
namespace Phanes::Core::Math {
/**
* A 2D Point with components x and y with integer precision.
*/
template<IntType T>
struct TIntPoint2 : public TIntVector2<T, false> {
using TIntVector2<T, false>::TIntVector2;
/**
* Creates IntPoint2 from IntPoint3's xy
*
* @param a IntPoint3 one
*/
TIntPoint2(const TIntPoint3<T>& a)
{
this->x = a.x;
this->y = a.y;
}
/**
* Creates IntPoint2 from IntPoint4's xy
*
* @param a IntPoint4 one
*/
//TIntPoint2(const TIntPoint4<T>& a)
//{
// this->x = a.x;
// this->y = a.y;
//}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* A 3D Point with components x and y with integer precision.
*/
template<IntType T>
struct TIntPoint3 : public TIntVector3<T, false> {
using TIntVector3<T, false>::TIntVector3;
/**
* Creates IntPoint3 from IntPoint2's xy and zero
*
* @param a IntPoint2 one
*/
TIntPoint3(const TIntPoint2<T>& a)
{
this->x = a.x;
this->y = a.y;
this->z = 0;
}
/**
* Creates IntPoint3 from IntPoint4's xyz
*
* @param a IntPoint4 one
*/
//TIntPoint3(const TIntPoint4<T>& a)
//{
// this->components[0] = a.components[0];
// this->components[1] = a.components[1];
// this->components[2] = a.components[2];
//}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* A 4D Point with components x and y with integer precision.
*/
template<IntType T>
struct TIntPoint4 : public TIntVector4<T, false> {
using TIntVector4<T, false>::TIntVector4;
/**
* Creates IntPoint4 from IntPoint2's xy and the last two zero
*
* @param a IntPoint2 one
*/
TIntPoint4(const TIntPoint2<T>& a)
{
this->data[0] = a.data[0];
this->data[1] = a.data[1];
this->data[2] = 0;
this->data[3] = 0;
}
/**
* Creates IntPoint4 from IntPoint3's xyz and zero
*
* @param a IntPoint3 one
*/
TIntPoint4(const TIntPoint3<T>& a)
{
this->data[0] = a.data[0];
this->data[1] = a.data[1];
this->data[2] = a.data[2];
this->data[3] = 0;
}
};
} // phanes::core::math::coretypes
#endif // !INTPOINT_H

View File

@@ -0,0 +1,630 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathCommon.hpp"
#include "Core/public/Math/MathFwd.h"
#include "Core/public/Math/SIMD/Storage.h"
#ifndef P_DEBUG
#pragma warning(disable : 4244)
#endif
/**
* Note: Some function are deleted, because, their unusable with int types, except very specific cases.
* To keep the library verbose, these functions are explicitly marked as deleted.
*/
#ifndef INTVECTOR2_H
#define INTVECTOR2_H
#define PIntZeroVector2(type, aligned) TIntVector2<##type, ##aligned>(0,0)
#define PIntVectorSouth2(type, aligned) TIntVector2<##type, ##aligned>(0,-1)
#define PIntVectorNorth2(type, aligned) TIntVector2<##type, ##aligned>(0,1)
#define PIntVectorEast2(type, aligned) TIntVector2<##type, ##aligned>(1,0)
#define PIntVectorWest2(type, aligned) TIntVector2<##type, ##aligned>(-1,0)
namespace Phanes::Core::Math {
/**
* A 2D Vector with components x and y with integer precision.
*/
template<IntType T, bool A>
struct TIntVector2 {
public:
// 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
{
struct
{
/** X component of Vector
*
* @ref [FIELD]components
* @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.
*/
T x;
/** Y component of Vector
*
* @ref [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.
*/
T y;
};
/** Components array holding the data
*
* @ref [FIELD]x
* @ref [FIELD]y
*
* @note Components are split into x and y. Access and manipulation is possible by these variables.
*/
union
{
typename SIMD::Storage<2, T, SIMD::use_simd<T, 2, A>::value>::type comp;
typename SIMD::Storage<2, T, SIMD::use_simd<T, 2, A>::value>::type data;
};
};
public:
/**
* Default constructor without initialization
*/
TIntVector2() = default;
/**
* Copy constructor
*/
TIntVector2(const TIntVector2<T, A>& v);
/**
* Construct Vector from xy components.
*
* @param x X component
* @param y Y component
*/
TIntVector2(const T x, const T y);
/**
* Construct Vector from two component array.
*
* @param comp Array of components
*/
TIntVector2(const T* comp);
/**
* Construct Vector from 3D integer Vector's xy.
*
* @param v 3D IntVector to copy from
*/
TIntVector2(const T s);
};
// ======================== //
// IntVector2 operators //
// ======================== //
/**
* Addition operation on same TIntVector2<T, A> (this) by a scalar value.
*
* @param(v1) Vector to add to
* @param(s) Scalar to add
*/
template<IntType T, bool A>
TIntVector2<T, A>& operator+= (TIntVector2<T, A>& v1, T s);
/**
* Addition operation on same TIntVector2<T, A> (this) by a another TIntVector2<T, A>.
*
* @param(v1) Vector to add to
* @param(v2) Vector to add
*/
template<IntType T, bool A>
TIntVector2<T, A>& operator+= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
/**
* Substraction operation on same TIntVector2<T, A> (this) by a scalar.
*
* @param(v1) Vector to substract from
* @param(v2) Scalar to substract
*/
template<IntType T, bool A>
TIntVector2<T, A>& operator-= (TIntVector2<T, A>& v1, T s);
/**
* Substraction operation on same TIntVector2<T, A> (this) by a another TIntVector2<T, A>.
*
* @param(v1) Vector to substract from
* @param(v2) Vector to substract
*/
template<IntType T, bool A>
TIntVector2<T, A>& operator-= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
/**
* Multiplication of TIntVector2<T, A> (this) with a scalar.
*
* @param(v1) Vector to multiply with
* @param(s) scalar to multiply with
*/
template<IntType T, bool A>
TIntVector2<T, A>& operator*= (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
TIntVector2<T, A>& operator*= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
/**
* Devision of Vector
*
* @param(v1) Vector to divide with
* @param(s) Scalar to divide with
*
* @note Result is rounded
*/
template<IntType T, bool A>
TIntVector2<T, A>& operator/= (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
TIntVector2<T, A>& operator/= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
/**
* Stores the remainder of division by a scalar.
*
* @param(v1) Vector to divide with
* @param(s) Scalar to divide with
*/
template<IntType T, bool A>
TIntVector2<T, A>& operator%= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
TIntVector2<T, A>& operator%= (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator&= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator&= (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator|= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator|= (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator^= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator^= (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator<<= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator<<= (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator>>= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator>>= (TIntVector2<T, A>& v1, T s);
/**
* Scale of Vector by floating point. (> Creates a new TIntVector2<T, A>)
*
* @param(v1) Vector to multiply with
* @param(s Floating point to multiply with
*
* @return Result Vector
*/
template<IntType T, bool A>
TIntVector2<T, A> operator* (const TIntVector2<T, A>& v1, T s);
/**
* Division of Vector by floating point. (> Creates another TIntVector2<T, A>)
*
* @see [FUNC]DivideFloat
*
* @param(v1) Vector to multiply with
* @param(s Floating point to divide with
*
* @return Result Vector
* @note Deleted, because the returntype might not implicitly be obvious, when using in code or reading.
*/
template<IntType T, bool A>
TIntVector2<T, A> operator/ (const TIntVector2<T, A>& v1, T s);
/**
* Scale of Vector by floating point. (> Creates a new TIntVector2<T, A>)
*
* @param(v1) Vector to multiply with
* @param(s Floating point to multiply with
*
* @return Result Vector
*/
template<IntType T, bool A>
FORCEINLINE TIntVector2<T, A> operator* (T s, const TIntVector2<T, A>& v1) { return v1 * s; };
/**
* Division of Vector by floating point. (> For convenience not arithmethicaly correct. Works like overloaded counterpart.)
*
* @see [FUNC]DivideFloat
*
* @param(v1) Vector to multiply with
* @param(s Floating point to divide with
*
* @return Result Vector
*
* @note Deleted, because the returntype might not implicitly be obvious, when using in code or reading.
*/
template<IntType T, bool A>
FORCEINLINE TIntVector2<T, A> operator/ (T s, const TIntVector2<T, A>& v1) { return v1 / s; };
/**
* Dot product between two Vectors.
*
* @see [FUNC]DotP
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @result Dot product
*/
template<IntType T, bool A>
T operator* (const TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
/**
* Componentwise addition of Vector with floating point.
*
* @param(v1) Vector to add to
* @param(s Floating point to add
*
* @return Result Vector
*/
template<IntType T, bool A>
TIntVector2<T, A> operator+ (const TIntVector2<T, A>& v1, T s);
/**
* Componentwise addition of Vector with floating point.
*
* @param(v1) Vector to add to
* @param(s Floating point to add
*
* @return Result Vector
*/
template<IntType T, bool A>
TIntVector2<T, A> operator+ (const TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
/**
* Componentwise substraction of Vector with floating point.
*
* @param(v1) Vector to substract from
* @param(s Floating point to substract
*
* @return Result Vector
*/
template<IntType T, bool A>
TIntVector2<T, A> operator- (const TIntVector2<T, A>& v1, T s);
/**
* Componentwise substraction of Vector with Vector.
*
* @param(v1) Vector to substract from
* @param(s Floating point to substract
*
* @return Result Vector
*/
template<IntType T, bool A>
TIntVector2<T, A> operator- (const TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
/**
* Scale of Vector by floating point. (> Creates a new TIntVector2<T, A>)
*
* @param(v1) Vector to multiply with
* @param(s Floating point to multiply with
*
* @return Result Vector
*/
template<IntType T, bool A>
inline TIntVector2<T, A> operator% (const TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A> operator% (const TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A> operator& (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A> operator& (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A> operator| (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A> operator| (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A> operator^ (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A> operator^ (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A> operator<< (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A> operator<< (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A> operator>> (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A> operator>> (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A> operator~ (TIntVector2<T, A>& v1);
/**
* Compare Vector for equality.
*
* @see [FUNC]Equals
*
* @param(v1) Vector to negate
*
* @return true if equal, false if inequal
*/
template<IntType T, bool A>
bool operator== (const TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
/**
* Compare Vector for inequality.
*
* @see [FUNC]Equals
*
* @param(v1) Vector to negate
*
* @return true if inequal, false if equal
*/
template<IntType T, bool A>
bool operator!= (const TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
// ============================================== //
// TIntVector2 static function implementation //
// ============================================== //
template<IntType T>
T DotP(const TIntVector2<T, false>& v, const TIntVector2<T, false>& v1)
{
return v.x * v1.x + v.y * v1.y;
}
template<IntType T>
TIntVector2<T, false>& MaxV(TIntVector2<T, false>& v1, const TIntVector2<T, false>& v2)
{
v1.x = Phanes::Core::Math::Max(v1.x, v2.x);
v1.y = Phanes::Core::Math::Max(v1.y, v2.y);
return v1;
}
/**
* Creates Vector, with component wise smallest values.
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @note Stores new Vector to v1
*/
template<IntType T>
TIntVector2<T, false>& MinV(TIntVector2<T, false>& v1, const TIntVector2<T, false>& v2)
{
v1.x = Phanes::Core::Math::Min(v1.x, v2.x);
v1.y = Phanes::Core::Math::Min(v1.y, v2.y);
return v1;
}
/// <summary>
/// Returns signs of numbers (1 / -1). <br>
/// Returns 1 for zero.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="v1"></param>
/// <returns></returns>
template<IntType T>
TIntVector2<T, false>& SignVectorV(TIntVector2<T, false>& v1)
{
v1.x = (v1.x >= 0) ? 1 : -1;
v1.y = (v1.y >= 0) ? 1 : -1;
return v1;
}
/**
* Copies one Vector two another
*
* @param(v1) Vector to copy to
* @param(v2) Vector to copy
*/
template<IntType T>
TIntVector2<T, false>& Set(TIntVector2<T, false>& v1, const TIntVector2<T, false>& v2)
{
v1 = v2;
return v1;
}
/**
* Sets components of a vector.
*
* @param(v1) Vector to copy to
* @param(v2) Vector to copy
*/
template<IntType T>
TIntVector2<T, false>& Set(TIntVector2<T, false>& v1, T x, T y)
{
v1.x = x;
v1.y = y;
return v1;
}
/**
* Negates Vector
*
* @param(v1) Vector one
*/
template<IntType T>
TIntVector2<T, false>& NegateV(TIntVector2<T, false>& v1)
{
v1.x = -v1.x;
v1.y = -v1.y;
return v1;
}
/**
* Tests if 2 vectors are perpendicular to each other.
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @return true if perpendicular, false if not
*
* @note Requires v1 and v2 to be normal vectors.
*/
template<IntType T>
inline bool IsPerpendicular(const TIntVector2<T, false>& v1, const TIntVector2<T, false>& v2)
{
return (Abs(DotP(v1, v2)) == 0);
}
/**
* Gets outer product of to vectors.
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @return Resulting matrix
*/
//template<IntType T>
//Matrix2<T> OuterProduct(const TIntVector2<T, false>& v1, const TIntVector2<T, false>& v2);
// ================================================================ //
// IntVector2 static function implementation with return values //
// ================================================================ //
/**
* Negates Vector
*
* @param(v1) Vector one
*
* @return Componentwise inverted vector
*/
template<IntType T>
TIntVector2<T, false> Negate(const TIntVector2<T, false>& v1)
{
return TIntVector2<T, false>(-v1.x, -v1.y);
}
/**
* Creates a new Vector by the component wise minimals of both vectors
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @return Minimal vector
*/
template<IntType T>
TIntVector2<T, false> Min(const TIntVector2<T, false>& v1, const TIntVector2<T, false>& v2)
{
return TIntVector2<T, false>(Phanes::Core::Math::Min(v1.x, v2.x), Phanes::Core::Math::Min(v1.y, v2.y));
}
/**
* Creates a new Vector by the component wise maxima of both vectors
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @return Maximal vector
*/
template<IntType T>
TIntVector2<T, false> Max(const TIntVector2<T, false>& v1, const TIntVector2<T, false>& v2)
{
return TIntVector2<T, false>(Phanes::Core::Math::Max(v1.x, v2.x), Phanes::Core::Math::Max(v1.y, v2.y));
}
template<IntType T>
TIntVector2<T, false> SignVector(const TIntVector2<T, false>& v1)
{
return TIntVector2<T, false>((v1.x >= 0) ? 1 : -1, (v1.y >= 0) ? 1 : -1);
}
} // phanes::core::math::coretypes
#endif // !INTVECTOR2_H
#include "Core/public/Math/IntVector2.inl"

View File

@@ -0,0 +1,401 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/Detail/IntVector2Decl.inl"
#include "Core/public/Math/SIMD/SIMDIntrinsics.h"
#include "Core/public/Math/SIMD/PhanesSIMDTypes.h"
namespace Phanes::Core::Math
{
template<IntType T, bool S>
TIntVector2<T, S>::TIntVector2(const TIntVector2<T, S>& v)
{
Detail::construct_ivec2<T, S>::map(*this, v);
}
template<IntType T, bool S>
TIntVector2<T, S>::TIntVector2(const T _x, const T _y)
{
Detail::construct_ivec2<T, S>::map(*this, _x, _y);
}
template<IntType T, bool S>
TIntVector2<T, S>::TIntVector2(const T s)
{
Detail::construct_ivec2<T, S>::map(*this, s);
}
template<IntType T, bool S>
TIntVector2<T, S>::TIntVector2(const T* comp)
{
Detail::construct_ivec2<T, S>::map(*this, comp);
}
template<IntType T, bool S>
TIntVector2<T, S>& operator+=(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
Detail::compute_ivec2_add<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator+=(TIntVector2<T, S>& v1, T s)
{
Detail::compute_ivec2_add<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator-=(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
Detail::compute_ivec2_sub<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator-=(TIntVector2<T, S>& v1, T s)
{
Detail::compute_ivec2_sub<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator*=(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
Detail::compute_ivec2_mul<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator*=(TIntVector2<T, S>& v1, T s)
{
Detail::compute_ivec2_mul<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator/=(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
Detail::compute_ivec2_div<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator/=(TIntVector2<T, S>& v1, T s)
{
Detail::compute_ivec2_div<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator%=(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
Detail::compute_ivec2_mod<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator%=(TIntVector2<T, S>& v1, T s)
{
Detail::compute_ivec2_mod<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S> operator+(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_add<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator+(TIntVector2<T, S>& v1, T s)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_add<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator-(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_sub<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator-(TIntVector2<T, S>& v1, T s)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_sub<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator*(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_mul<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator*(TIntVector2<T, S>& v1, T s)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_mul<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator/(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_div<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator/(TIntVector2<T, S>& v1, T s)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_div<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator%(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_mod<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator%(TIntVector2<T, S>& v1, T s)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_mod<T, S>::map(r, v1, s);
return r;
}
// Bitwise operators
template<IntType T, bool S>
TIntVector2<T, S>& operator&=(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
Detail::compute_ivec2_and<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator&=(TIntVector2<T, S>& v1, T s)
{
Detail::compute_ivec2_and<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator|=(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
Detail::compute_ivec2_or<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator|=(TIntVector2<T, S>& v1, T s)
{
Detail::compute_ivec2_or<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator^=(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
Detail::compute_ivec2_xor<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator^=(TIntVector2<T, S>& v1, T s)
{
Detail::compute_ivec2_xor<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator<<=(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
Detail::compute_ivec2_left_shift<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator<<=(TIntVector2<T, S>& v1, T s)
{
Detail::compute_ivec2_left_shift<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator>>=(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
Detail::compute_ivec2_right_shift<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator>>=(TIntVector2<T, S>& v1, T s)
{
Detail::compute_ivec2_right_shift<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S> operator&(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_and<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator&(TIntVector2<T, S>& v1, T s)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_and<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator|(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_or<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator|(TIntVector2<T, S>& v1, T s)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_or<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator^(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_xor<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator^(TIntVector2<T, S>& v1, T s)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_xor<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator<<(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_left_shift<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator<<(TIntVector2<T, S>& v1, T s)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_left_shift<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator>>(TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_right_shift<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator>>(TIntVector2<T, S>& v1, T s)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_right_shift<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector2<T, S> operator~(TIntVector2<T, S>& v1)
{
TIntVector2<T, S> r;
Detail::compute_ivec2_bnot<T, S>::map(r, v1);
return r;
}
// Comparision
template<IntType T, bool S>
bool operator==(const TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
return Detail::compute_ivec2_eq<T, S>::map(v1, v2);
}
template<IntType T, bool S>
bool operator!=(const TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
return Detail::compute_ivec2_ieq<T, S>::map(v1, v2);
}
// Inc- / Decrement
template<IntType T, bool S>
TIntVector2<T, S>& operator++(TIntVector2<T, S>& v1)
{
Detail::compute_ivec2_inc<T, S>::map(v1, v1);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator--(TIntVector2<T, S>& v1)
{
Detail::compute_ivec2_dec<T, S>::map(v1, v1);
return v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator++(TIntVector2<T, S>& v1, int)
{
return ++v1;
}
template<IntType T, bool S>
TIntVector2<T, S>& operator--(TIntVector2<T, S>& v1, int)
{
return --v1;
}
}

View File

@@ -0,0 +1,689 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathCommon.hpp"
#include "Core/public/Math/MathFwd.h"
#include "Core/public/Math/SIMD/Storage.h"
#include "Core/public/Math/IntVector4.hpp"
#ifndef P_DEBUG
#pragma warning(disable : 4244)
#endif
#ifndef INTVECTOR3_H
#define INTVECTOR3_H
#define PIntZeroVector3(type) TIntVector3<##type>(0,0,0)
#define PIntVectorForward3(type) TIntVector3<##type>(1,0,0)
#define PIntVectorBackward3(type) TIntVector3<##type>(-1,0,0)
#define PIntVectorEast3(type) TIntVector3<##type>(0,1,0)
#define PIntVectorWest3(type) TIntVector3<##type>(0,-1,0)
#define PIntVectorUp3(type) TIntVector3<##type>(0,0,1)
#define PIntVectorDown3(type) TIntVector3<##type>(0,0,-1)
namespace Phanes::Core::Math {
/**
* A 3D Vector with components x, y and z with integer precision.
*/
template<IntType T, bool A>
struct TIntVector3 : public TIntVector4<T, A> {
public:
/**
* Default constructor without initialization
*/
TIntVector3() = default;
/**
* Copy constructor
*/
TIntVector3(const TIntVector3<T, A>& v);
/**
* Construct Vector from xyz components.
*
* @param(x) X component
* @param(y) Y component
* @param(z) Z component
*/
TIntVector3(const T x, const T y, const T z);
/// <summary>
/// Broadcast s into all components.
/// </summary>
/// <param name="s"></param>
TIntVector3(const T s);
/**
* Construct Vector from two component array.
*
* @param(comp) Array of components
*/
TIntVector3(const T* comp);
TIntVector3(const TIntVector2<T, A>& v1, const T s);
};
// ======================== //
// IntVector3 operators //
// ======================== //
/**
* Coponentwise addition of scalar to 3D vector
*
* @param(v1) vector to add to
* @param(s) scalar to add
*/
template<IntType T, bool A>
inline TIntVector3<T, A>& operator+= (TIntVector3<T, A>& v1, T s);
/**
* Coponentwise addition of 3D vector to 3D vector
*
* @param(v1) vector to add to
* @param(v2) vector to add
*/
template<IntType T, bool A>
inline TIntVector3<T, A>& operator+= (TIntVector3<T, A>& v1, const TIntVector3<T, A>& v2);
/**
* Coponentwise substraction of scalar of 3D vector
*
* @param(v1) vector to substract from
* @param(s) scalar to substract
*/
template<IntType T, bool A>
inline TIntVector3<T, A>& operator-= (TIntVector3<T, A>& v1, T s);
/**
* Coponentwise substraction of 3D vector to 3D vector
*
* @param(v1) vector to substract from
* @param(v2) vector to substract with
*/
template<IntType T, bool A>
inline TIntVector3<T, A>& operator-= (TIntVector3<T, A>& v1, const TIntVector3<T, A>& v2);
/**
* Dot product between two 3D Vectors
*
* @param(v1) vector one
* @param(s) scalar
*/
template<IntType T, bool A>
inline TIntVector3<T, A>& operator*= (TIntVector3<T, A>& v1, T s);
/**
* Division of vector by scalar
*
* @param(v1) vector one
* @param(s) scalar
*/
template<IntType T, bool A>
inline TIntVector3<T, A>& operator/= (TIntVector3<T, A>& v1, T s);
template<IntType T, bool A>
TIntVector2<T, A>& operator%= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
TIntVector2<T, A>& operator%= (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator&= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator&= (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator|= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator|= (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator^= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator^= (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator<<= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator<<= (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator>>= (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A>& operator>>= (TIntVector2<T, A>& v1, T s);
/**
* Coponentwise multiplication of 3D Vectors with scalar
*
* @param(v1) vector one
* @param(s) scalar
*
* @return Resulting vector
*/
template<IntType T, bool A>
TIntVector3<T, A> operator* (const TIntVector3<T, A>& v1, T s);
/**
* Coponentwise multiplication of 3D Vectors with scalar
*
* @param(s) scalar
* @param(v2) vector
*
* @return Solution vector
*/
template<IntType T, bool A>
FORCEINLINE TIntVector3<T, A> operator* (T s, const TIntVector3<T, A>& v1) { return v1 / s; };
/**
* Division by scalar
*
* @param(s) scalar
* @param(v2) vector
*
* @return Solution vector
*/
template<IntType T, bool A>
inline TIntVector3<T, A> operator/ (const TIntVector3<T, A>& v1, T s);
template<IntType T, bool A>
FORCEINLINE TIntVector3<T, A> operator/ (T s, const TIntVector3<T, A>& v1) { return v1 / s; };
template<IntType T, bool A>
inline TIntVector2<T, A> operator% (const TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A> operator% (const TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A> operator& (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A> operator& (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A> operator| (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A> operator| (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A> operator^ (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A> operator^ (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A> operator<< (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A> operator<< (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A> operator>> (TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
template<IntType T, bool A>
inline TIntVector2<T, A> operator>> (TIntVector2<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector2<T, A> operator~ (TIntVector2<T, A>& v1);
/**
* Dot product between two 3D Vectors
*
* @param(v1) vector one
* @param(v2) vector two
*
* @return Dot product of Vectors
*/
template<IntType T, bool A>
TIntVector3<T, A> operator* (const TIntVector3<T, A>& v1, const TIntVector3<T, A>& v2);
/**
* Coponentwise addition of scalar to 3D vector
*
* @param(v1) vector to add to
* @param(s) scalar to add
*
* @return Resulting vector
*/
template<IntType T, bool A>
TIntVector3<T, A> operator+ (const TIntVector3<T, A>& v1, T s);
/**
* Coponentwise addition of 3D vector to 3D vector
*
* @param(v1) vector to add to
* @param(v2) vector to add
*
* @return Resulting vector
*/
template<IntType T, bool A>
TIntVector3<T, A> operator+ (const TIntVector3<T, A>& v1, const TIntVector3<T, A>& v2);
/**
* Coponentwise substraction of scalar of 3D vector
*
* @param(v1) vector to substract from
* @param(s) scalar to substract
*
* @return Resulting vector
*/
template<IntType T, bool A>
TIntVector3<T, A> operator- (const TIntVector3<T, A>& v1, T s);
/**
* Coponentwise substraction of scalar of 3D vector
*
* @param(v1) vector to substract from
* @param(v2) vector to substract with
*
* @return Resulting vector
*/
template<IntType T, bool A>
TIntVector3<T, A> operator- (const TIntVector3<T, A>& v1, const TIntVector3<T, A>& v2);
/**
* Tests two 3D vectors for equality.
*
* @ref [FUNC]Equals
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @return True if equal, false if not.
*
* @note Uses [MACRO]P_FLT_INAC
*/
template<IntType T, bool A>
inline bool operator== (const TIntVector3<T, A>& v1, const TIntVector3<T, A>& v2);
/**
* Tests two 3D vectors for inequality.
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @return True if inequal, false if not.
*/
template<IntType T, bool A>
inline bool operator!= (const TIntVector3<T, A>& v1, const TIntVector3<T, A>& v2);
// ============================================== //
// IntVector3 static function implementation //
// ============================================== //
/**
* Dot product of two vectors
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @return Dot product of vectors
*/
template<IntType T>
T DotP(const TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2)
{
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}
/**
* Tests two vectors for equality.
*
* @param(v1) Vector one
* @param(v2) Vector two
* @param(threshold) Allowed T inaccuracy.
*
* @return True if equal, false if not.
*/
template<IntType T>
inline bool Equals(const TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2, T threshold = P_FLT_INAC)
{
return (abs(v1.x - v2.x) < threshold && abs(v1.y - v2.y) < threshold && abs(v1.z - v2.z) < threshold);
}
/**
* Calculates the cross product between two vectors.
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @note result is stored in v1.
*/
template<IntType T>
TIntVector3<T, false>& CrossPV(TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2)
{
T x = v1.x;
T y = v1.y;
T z = v1.z;
v1.x = (y * v2.z) - (z * v2.y);
v1.y = (z * v2.x) - (x * v2.z);
v1.z = (x * v2.y) - (y * v2.x);
return v1;
}
/**
* Gets the componentwise max of both vectors.
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @note result is stored in v1.
*/
template<IntType T>
TIntVector3<T, false>& MaxV(TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2)
{
v1.x = Phanes::Core::Math::Max(v1.x, v2.x);
v1.y = Phanes::Core::Math::Max(v1.y, v2.y);
v1.z = Phanes::Core::Math::Max(v1.z, v2.z);
return v1;
}
/**
* Gets the componentwise min of both vectors.
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @note result is stored in v1.
*/
template<IntType T>
TIntVector3<T, false>& MinV(TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2)
{
v1.x = Phanes::Core::Math::Min(v1.x, v2.x);
v1.y = Phanes::Core::Math::Min(v1.y, v2.y);
v1.z = Phanes::Core::Math::Min(v1.z, v2.z);
return v1;
}
/**
* Gets reversed vector.
*
* @param(v1) Vector one
*
* @note result is stored in v1.
*/
template<IntType T>
TIntVector3<T, false>& NegateV(TIntVector3<T, false>& v1)
{
v1.x = -v1.x;
v1.y = -v1.y;
v1.z = -v1.z;
return v1;
}
/**
* Copies v1 vector
*
* @param(v1) Vector to copy to
* @param(v2) Vector to copy
*/
template<IntType T>
TIntVector3<T, false>& Set(TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2)
{
v1 = v2;
return v1;
}
/**
* Sets vector.
*
* @param(v1) Vector to copy to
* @param(x) X component
* @param(y) Y component
* @param(z) Z component
*/
template<IntType T>
TIntVector3<T, false>& Set(TIntVector3<T, false>& v1, T x, T y, T z)
{
v1.x = x;
v1.y = y;
v1.z = z;
return v1;
}
/**
* Returns signs of components in vector: -1 / +1 / 0.
*
* @param(v1) Vector one
*/
template<IntType T>
TIntVector3<T, false>& SignVectorV(TIntVector3<T, false>& v1)
{
v1.x = (v1.x >= 0) ? 1 : -1;
v1.y = (v1.y >= 0) ? 1 : -1;
v1.z = (v1.z >= 0) ? 1 : -1;
return v1;
}
/**
* Gets scalar triple product ((v1 x v2) * v3). (Volume of parallelepiped.)
*
* @param(v1) Vector one
* @param(v2) Vector two
* @param(v3) Vector three
*
* @return Vector triple product
*/
template<IntType T>
T ScalarTriple(const TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2, const TIntVector3<T, false>& v3)
{
return DotP(CrossP(v1, v2), v3);
}
/**
* Gets vector triple product ((v1 x v2) x v3).
*
* @param(v1) Vector one
* @param(v2) Vector two
* @param(v3) Vector three
*
* @note result is stored in v1
*/
template<IntType T>
TIntVector3<T, false>& VectorTripleV(TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2, const TIntVector3<T, false>& v3)
{
CrossPV(CrossPV(v1, v2), v3);
return v1;
}
template<IntType T>
TIntVector3<T, false>& GetPerpendicular(TIntVector3<T, false>& v1)
{
T y = v1.y;
v1.x = 0;
v1.y = v1.z;
v1.z = -y;
return v1;
}
/**
* Tests whether two vectors are perpendicular.
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @return True if perpendicular, false if not.
*/
template<IntType T>
inline bool IsPerpendicular(const TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2)
{
return (DotP(v1, v2) == 0);
}
/**
* Tests if three vectors are coplanar
*
* @param(v1) Vector one
* @param(v2) Vector two
* @param(v3) Vector three
*
* @return True if coplanar, false if not.
*/
template<IntType T>
inline bool IsCoplanar(const TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2, const TIntVector3<T, false>& v3)
{
return (ScalarTriple(v1, v2, v3) == 0);
}
// ================================================================ //
// IntVector3 static function implementation with return values //
// ================================================================ //
/**
* Gets cross product between two vectors.
*
* @param(v1) vector one
* @param(v2) vector two
*
* @return Cross product of v1 and v2
*/
template<IntType T>
TIntVector3<T, false> CrossP(const TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2)
{
return TIntVector3<T, false>((v1.y * v2.z) - (v1.z * v2.y),
(v1.z * v2.x) - (v1.x * v2.z),
(v1.x * v2.y) - (v1.y * v2.x));
}
/**
* Creates a new Vector by the componentwise max of both vectors
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @return Vector of componentwise max
*/
template<IntType T>
TIntVector3<T, false> Max(const TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2)
{
return TIntVector3<T, false>((v1.x > v2.x) ? v1.x : v2.x,
(v1.y > v2.y) ? v1.y : v2.y,
(v1.z > v2.z) ? v1.z : v2.z);
}
/**
* Creates a new Vector by the componentwise min of both vectors
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @return Vector of componentwise min
*/
template<IntType T>
TIntVector3<T, false> Min(const TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2)
{
return TIntVector3<T, false>((v1.x < v2.x) ? v1.x : v2.x,
(v1.y < v2.y) ? v1.y : v2.y,
(v1.z < v2.z) ? v1.z : v2.z);
}
/**
* Gets reversed vector.
*
* @param(v1) Vector one
*
* @note result is stored in v1.
*/
template<IntType T>
TIntVector3<T, false> Negate(const TIntVector3<T, false>& v1)
{
return TIntVector3<T, false>(-v1.x, -v1.y, -v1.z);
}
/**
* Gets vector triple product ((v1 x v2) x v3).
*
* @param(v1) Vector one
* @param(v2) Vector two
* @param(v3) Vector three
*
* @return Vector triple product
*/
template<IntType T>
TIntVector3<T, false> VectorTriple(const TIntVector3<T, false>& v1, const TIntVector3<T, false>& v2, const TIntVector3<T, false>& v3)
{
return CrossP(CrossP(v1, v2), v3);
}
template<IntType T>
TIntVector3<T, false> SignVector(const TIntVector3<T, false>& v1)
{
return TIntVector3<T, false>((v1.x >= 0) ? 1 : -1, (v1.y >= 0) ? 1 : -1, (v1.z >= 0) ? 1 : -1);
}
} // phanes::core::math::coretypes
#endif // !INTVECTOR3_H
#include "Core/public/Math/IntVector3.inl"

View File

@@ -0,0 +1,408 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/Detail/IntVector3Decl.inl"
#include "Core/public/Math/SIMD/SIMDIntrinsics.h"
#include "Core/public/Math/SIMD/PhanesSIMDTypes.h"
namespace Phanes::Core::Math
{
template<IntType T, bool S>
TIntVector3<T, S>::TIntVector3(const TIntVector3<T, S>& v)
{
Detail::construct_ivec3<T, S>::map(*this, v);
}
template<IntType T, bool S>
TIntVector3<T, S>::TIntVector3(const T _x, const T _y, const T _z)
{
Detail::construct_ivec3<T, S>::map(*this, _x, _y, _z);
}
template<IntType T, bool S>
TIntVector3<T, S>::TIntVector3(const T s)
{
Detail::construct_ivec3<T, S>::map(*this, s);
}
template<IntType T, bool S>
TIntVector3<T, S>::TIntVector3(const T* comp)
{
Detail::construct_ivec3<T, S>::map(*this, comp);
}
template<IntType T, bool S>
TIntVector3<T, S>::TIntVector3(const TIntVector2<T, S>& v1, const T s)
{
Detail::construct_ivec3<T, S>::map(*this, v1, s);
}
template<IntType T, bool S>
TIntVector3<T, S>& operator+=(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
Detail::compute_ivec3_add<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator+=(TIntVector3<T, S>& v1, T s)
{
Detail::compute_ivec3_add<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator-=(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
Detail::compute_ivec3_sub<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator-=(TIntVector3<T, S>& v1, T s)
{
Detail::compute_ivec3_sub<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator*=(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
Detail::compute_ivec3_mul<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator*=(TIntVector3<T, S>& v1, T s)
{
Detail::compute_ivec3_mul<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator/=(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
Detail::compute_ivec3_div<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator/=(TIntVector3<T, S>& v1, T s)
{
Detail::compute_ivec3_div<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator%=(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
Detail::compute_ivec3_mod<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator%=(TIntVector3<T, S>& v1, T s)
{
Detail::compute_ivec3_mod<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S> operator+(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_add<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator+(TIntVector3<T, S>& v1, T s)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_add<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator-(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_sub<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator-(TIntVector3<T, S>& v1, T s)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_sub<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator*(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_mul<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator*(TIntVector3<T, S>& v1, T s)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_mul<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator/(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_div<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator/(TIntVector3<T, S>& v1, T s)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_div<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator%(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_mod<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator%(TIntVector3<T, S>& v1, T s)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_mod<T, S>::map(r, v1, s);
return r;
}
// Bitwise operators
template<IntType T, bool S>
TIntVector3<T, S>& operator&=(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
Detail::compute_ivec3_and<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator&=(TIntVector3<T, S>& v1, T s)
{
Detail::compute_ivec3_and<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator|=(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
Detail::compute_ivec3_or<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator|=(TIntVector3<T, S>& v1, T s)
{
Detail::compute_ivec3_or<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator^=(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
Detail::compute_ivec3_xor<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator^=(TIntVector3<T, S>& v1, T s)
{
Detail::compute_ivec3_xor<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator<<=(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
Detail::compute_ivec3_left_shift<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator<<=(TIntVector3<T, S>& v1, T s)
{
Detail::compute_ivec3_left_shift<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator>>=(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
Detail::compute_ivec3_right_shift<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator>>=(TIntVector3<T, S>& v1, T s)
{
Detail::compute_ivec3_right_shift<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S> operator&(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_and<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator&(TIntVector3<T, S>& v1, T s)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_and<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator|(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_or<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator|(TIntVector3<T, S>& v1, T s)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_or<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator^(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_xor<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator^(TIntVector3<T, S>& v1, T s)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_xor<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator<<(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_left_shift<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator<<(TIntVector3<T, S>& v1, T s)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_left_shift<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator>>(TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_right_shift<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator>>(TIntVector3<T, S>& v1, T s)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_right_shift<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector3<T, S> operator~(TIntVector3<T, S>& v1)
{
TIntVector3<T, S> r;
Detail::compute_ivec3_bnot<T, S>::map(r, v1);
return r;
}
// Comparision
template<IntType T, bool S>
bool operator==(const TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
return Detail::compute_ivec3_eq<T, S>::map(v1, v2);
}
template<IntType T, bool S>
bool operator!=(const TIntVector3<T, S>& v1, const TIntVector3<T, S>& v2)
{
return Detail::compute_ivec3_ieq<T, S>::map(v1, v2);
}
// Inc- / Decrement
template<IntType T, bool S>
TIntVector3<T, S>& operator++(TIntVector3<T, S>& v1)
{
Detail::compute_ivec3_inc<T, S>::map(v1);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator--(TIntVector3<T, S>& v1)
{
Detail::compute_ivec3_inc<T, S>::map(v1);
return v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator++(TIntVector3<T, S>& v1, int)
{
return ++v1;
}
template<IntType T, bool S>
TIntVector3<T, S>& operator--(TIntVector3<T, S>& v1, int)
{
return --v1;
}
}

View File

@@ -0,0 +1,643 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathCommon.hpp"
#include "Core/public/Math/MathFwd.h"
#include "Core/public/Math/SIMD/Storage.h"
#include "Core/public/Math/IntVector2.hpp"
#ifndef P_DEBUG
#pragma warning(disable : 4244)
#endif
#ifndef INTVECTOR4_H
#define INTVECTOR4_H
namespace Phanes::Core::Math {
/**
* A 4D Vector with components x, y, z and w with integer precision.
*/
template<IntType T, bool A>
struct TIntVector4 {
public:
union
{
struct
{
/** X component of Vector
*
* @ref [FIELD]components
*
* @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.
*/
T x;
/** Y component of Vector
*
* @ref [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.
*/
T y;
/** Z component of Vector
*
* @ref [FIELD]components
*
* @note z does not hold the component, but is a reference two the second item in the components array. The varibale exists wholly for convenience.
*/
T z;
/** W component of Vector
*
* @ref [FIELD]components
*
* @note w does not hold the component, but is a reference two the second item in the components array. The varibale exists wholly for convenience.
*/
T w;
};
union
{
typename SIMD::Storage<4, T, SIMD::use_simd<T, 4, A>::value>::type comp;
typename SIMD::Storage<4, T, SIMD::use_simd<T, 4, A>::value>::type data;
};
};
public:
/**
* Default constructor without initialization
*/
TIntVector4() = default;
/// <summary>
/// Copy constructor.
/// </summary>
/// <param name="v"></param>
TIntVector4(const TIntVector4<T, A>& v);
/// <summary>
/// Construct vector from x, y, z, w components.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="z"></param>
/// <param name="w"></param>
TIntVector4(const T x, const T y, const T z, const T w);
/// <summary>
/// Broadcast s into all components.
/// </summary>
/// <param name="s"></param>
TIntVector4(T s);
/**
* Construct Vector from two component array.
*
* @param comp Array of components
*/
TIntVector4(const T *comp);
/// <summary>
/// Construct vector from two 2d vectors
/// <param>
/// x,y = v1.x, v2.y
/// </param>
/// z,w = v2.x, v2.y
/// </summary>
/// <param name="v1"></param>
/// <param name="v2"></param>
TIntVector4(const TIntVector2<T, A>& v1, const TIntVector2<T, A>& v2);
};
/**
* Addition operation on same TIntVector4<T, A> (this) by a scalar value.
*
* @param(v1) Vector to add to
* @param(s) Scalar
*/
template<IntType T, bool A>
TIntVector4<T, A>& operator+= (TIntVector4<T, A>& v1, T s);
/**
* Addition operation on same TIntVector4<T, A> (this) by a another TIntVector4<T, A>.
*
* @param(v1) Vector to add to
* @param(v2) Vector to add
*/
template<IntType T, bool A>
TIntVector4<T, A>& operator+= (TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
/**
* Substraction operation on same TIntVector4<T, A> (this) by a floating point.
*
* @param(v1) Vector to substract from
* @param(v2) Floating point to substract
*/
template<IntType T, bool A>
TIntVector4<T, A>& operator-= (TIntVector4<T, A>& v1, T s);
/**
* Substraction operation on same TIntVector4<T, A> (this) by a another TIntVector4<T, A>.
*
* @param(v1) Vector to substract from
* @param(v2) Vector to substract
*/
template<IntType T, bool A>
TIntVector4<T, A>& operator-= (TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
/**
* Multiplication of TIntVector4<T, A> (this) with a floating point.
*
* @param(v1) Vector to multiply with
* @param(s Floating point to multiply with
*/
template<IntType T, bool A>
TIntVector4<T, A>& operator*= (TIntVector4<T, A>& v1, T s);
/**
* Devision of Vector
*
* @param(v1) Vector to divide with
* @param(s) Scalar to divide with
*
* @note Result is rounded (obviously)
*/
template<IntType T, bool A>
TIntVector4<T, A>& operator/= (TIntVector4<T, A>& v1, T s);
/**
* Stores the remainder of division by a scalar.
*
* @param(v1) Vector to divide with
* @param(s) Scalar to divide with
*/
template<IntType T, bool A>
TIntVector4<T, A>& operator%= (TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
template<IntType T, bool A>
TIntVector4<T, A>& operator%= (TIntVector4<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector4<T, A>& operator&= (TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
template<IntType T, bool A>
inline TIntVector4<T, A>& operator&= (TIntVector4<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector4<T, A>& operator|= (TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
template<IntType T, bool A>
inline TIntVector4<T, A>& operator|= (TIntVector4<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector4<T, A> operator^= (TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
template<IntType T, bool A>
inline TIntVector4<T, A>& operator^= (TIntVector4<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector4<T, A>& operator<<= (TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
template<IntType T, bool A>
inline TIntVector4<T, A>& operator<<= (TIntVector4<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector4<T, A>& operator>>= (TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
template<IntType T, bool A>
inline TIntVector4<T, A>& operator>>= (TIntVector4<T, A>& v1, T s);
/**
* Scale of Vector by floating point. (> Creates a new TIntVector4<T, A>)
*
* @param(v1) Vector to multiply with
* @param(s Floating point to multiply with
*
* @return Result Vector
*/
template<IntType T, bool A>
TIntVector4<T, A> operator* (const TIntVector4<T, A>& v1, T s);
/**
* Division of Vector by floating point. (> Creates another TIntVector4<T, A>)
*
* @see [FUNC]DivideFloat
*
* @param(v1) Vector to multiply with
* @param(s Floating point to divide with
*
* @return Result Vector
* @note Deleted, because the returntype might not implicitly be obvious, when using in code or reading.
*/
template<IntType T, bool A>
TIntVector4<T, A> operator/ (const TIntVector4<T, A>& v1, T s);
/**
* Scale of Vector by floating point. (> Creates a new TIntVector4<T, A>)
*
* @param(v1) Vector to multiply with
* @param(s Floating point to multiply with
*
* @return Result Vector
*/
template<IntType T, bool A>
FORCEINLINE TIntVector4<T, A> operator* (T s, const TIntVector4<T, A>& v1) { return v1 * s; };
/**
* Division of Vector by floating point. (> For convenience not arithmethicaly correct. Works like overloaded counterpart.)
*
* @see [FUNC]DivideFloat
*
* @param(v1) Vector to multiply with
* @param(s Floating point to divide with
*
* @return Result Vector
*
* @note Deleted, because the returntype might not implicitly be obvious, when using in code or reading.
*/
template<IntType T, bool A>
FORCEINLINE TIntVector4<T, A> operator/ (T s, const TIntVector4<T, A>& v1) { return v1 / s; };
/**
* Dot product between two Vectors.
*
* @see [FUNC]DotP
*
* @param(v1) Vector one
* @param(v2) Vector two
*
* @result Dot product
*/
template<IntType T, bool A>
T operator* (const TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
/**
* Componentwise addition of Vector with floating point.
*
* @param(v1) Vector to add to
* @param(s Floating point to add
*
* @return Result Vector
*/
template<IntType T, bool A>
TIntVector4<T, A> operator+ (const TIntVector4<T, A>& v1, T s);
/**
* Componentwise addition of Vector with floating point.
*
* @param(v1) Vector to add to
* @param(s Floating point to add
*
* @return Result Vector
*/
template<IntType T, bool A>
TIntVector4<T, A> operator+ (const TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
/**
* Componentwise substraction of Vector with floating point.
*
* @param(v1) Vector to substract from
* @param(s Floating point to substract
*
* @return Result Vector
*/
template<IntType T, bool A>
TIntVector4<T, A> operator- (const TIntVector4<T, A>& v1, T s);
/**
* Componentwise substraction of Vector with Vector.
*
* @param(v1) Vector to substract from
* @param(s Floating point to substract
*
* @return Result Vector
*/
template<IntType T, bool A>
TIntVector4<T, A> operator- (const TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
/**
* Scale of Vector by floating point. (> Creates a new TIntVector4<T, A>)
*
* @param(v1) Vector to multiply with
* @param(s Floating point to multiply with
*
* @return Result Vector
*/
template<IntType T, bool A>
FORCEINLINE TIntVector4<T, A> operator% (const TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
template<IntType T, bool A>
FORCEINLINE TIntVector4<T, A> operator% (const TIntVector4<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector4<T, A> operator& (TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
template<IntType T, bool A>
inline TIntVector4<T, A> operator& (TIntVector4<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector4<T, A> operator| (TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
template<IntType T, bool A>
inline TIntVector4<T, A> operator| (TIntVector4<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector4<T, A> operator^ (TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
template<IntType T, bool A>
inline TIntVector4<T, A> operator^ (TIntVector4<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector4<T, A> operator<< (TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
template<IntType T, bool A>
inline TIntVector4<T, A> operator<< (TIntVector4<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector4<T, A> operator>> (TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
template<IntType T, bool A>
inline TIntVector4<T, A> operator>> (TIntVector4<T, A>& v1, T s);
template<IntType T, bool A>
inline TIntVector4<T, A> operator~ (TIntVector4<T, A>& v1);
/**
* Compare Vector for equality.
*
* @see [FUNC]Equals
*
* @param(v1) Vector to negate
*
* @return true if equal, false if inequal
*/
template<IntType T, bool A>
bool operator== (const TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
/**
* Compare Vector for inequality.
*
* @see [FUNC]Equals
*
* @param(v1) Vector to negate
*
* @return true if inequal, false if equal
*/
template<IntType T, bool A>
bool operator!= (const TIntVector4<T, A>& v1, const TIntVector4<T, A>& v2);
// ========================= //
// TIntVector4 functions //
// ========================= //
template<IntType T>
TIntVector4<T, false>& Set(TIntVector4<T, false>& v1, TIntVector4<T, false>& v2)
{
v1.x = v2.x;
v1.y = v2.y;
v1.z = v2.z;
v1.w = v2.w;
return v1;
}
/// <summary>
/// Calculates the dot product between two vectors.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Dot product between vectors.</returns>
template<IntType T>
T DotP(const TIntVector4<T, false>& v1, const TIntVector4<T, false>& v2)
{
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
}
/// <summary>
/// Gets componentwise max of both vectors.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam> * @note z does not hold the component, but is a reference two the second item in the components array. The varibale exists wholly for convenience.
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Vector with componentwise max of both vectors.</returns>
template<IntType T>
TIntVector4<T, false> Max(const TIntVector4<T, false>& v1, const TIntVector4<T, false>& v2)
{
return TIntVector4<T, false>(
(v1.x > v2.x) ? v1.x : v2.x,
(v1.y > v2.y) ? v1.y : v2.y,
(v1.z > v2.z) ? v1.z : v2.z,
(v1.w > v2.w) ? v1.w : v2.w
);
}
/// <summary>
/// Gets componentwise max of both vectors.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Copy of v1.</returns>
template<IntType T>
TIntVector4<T, false>& MaxV(TIntVector4<T, false>& v1, const TIntVector4<T, false>& v2)
{
v1.x = (v1.x > v2.x) ? v1.x : v2.x;
v1.y = (v1.y > v2.y) ? v1.y : v2.y;
v1.z = (v1.z > v2.z) ? v1.z : v2.z;
v1.w = (v1.w > v2.w) ? v1.w : v2.w;
return v1;
}
/// <summary>
/// Gets componentwise min of both vectors.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Vector with componentwise max of both vectors.</returns>
template<IntType T>
TIntVector4<T, false> Min(const TIntVector4<T, false>& v1, const TIntVector4<T, false>& v2)
{
return TIntVector4<T, false>(
(v1.x < v2.x) ? v1.x : v2.x,
(v1.y < v2.y) ? v1.y : v2.y,
(v1.z < v2.z) ? v1.z : v2.z,
(v1.w < v2.w) ? v1.w : v2.w
);
}
/// <summary>
/// Gets componentwise min of both vectors.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Copy of v1.</returns>
template<IntType T>
TIntVector4<T, false>& MinV(TIntVector4<T, false>& v1, const TIntVector4<T, false>& v2)
{
v1.x = (v1.x < v2.x) ? v1.x : v2.x;
v1.y = (v1.y < v2.y) ? v1.y : v2.y;
v1.z = (v1.z < v2.z) ? v1.z : v2.z;
v1.w = (v1.w < v2.w) ? v1.w : v2.w;
return v1;
}
/// <summary>
/// Inverses vector.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>Inverted vector</returns>
template<IntType T>
TIntVector4<T, false> Negate(const TIntVector4<T, false>& v1)
{
return TIntVector4<T, false>(
-v1.x,
-v1.y,
-v1.z,
-v1.w
);
}
/// <summary>
/// Inverses vector.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>Copy of v1.</returns>
template<IntType T>
TIntVector4<T, false>& NegateV(TIntVector4<T, false>& v1)
{
v1.x = -v1.x;
v1.y = -v1.y;
v1.z = -v1.z;
v1.w = -v1.w;
return v1;
}
/// <summary>
/// Get signs of components.
/// <para>
/// + -> +1
/// </para>
/// x -> -1
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <returns>Vector with signs of components.</returns>
template<IntType T>
TIntVector4<T, false> SignVector(TIntVector4<T, false>& v1)
{
return TIntVector4<T, false>(
(v1.x > 0) ? 1 : -1,
(v1.y > 0) ? 1 : -1,
(v1.z > 0) ? 1 : -1,
(v1.w > 0) ? 1 : -1
);
}
/// <summary>
/// Get signs of components.
/// <param>
/// + -> +1
/// </param>
/// x -> -1
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <returns></returns>
template<IntType T>
TIntVector4<T, false>& SignVectorV(TIntVector4<T, false>& v1)
{
v1.x = (v1.x > 0) ? 1 : -1;
v1.y = (v1.y > 0) ? 1 : -1;
v1.z = (v1.z > 0) ? 1 : -1;
v1.w = (v1.w > 0) ? 1 : -1;
return v1;
}
/// <summary>
/// Test if two vectors are perpendicular.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns>True if perpendicular.</returns>
template<IntType T>
inline bool IsPerpendicular(const TIntVector4<T, false>& v1, const TIntVector4<T, false>& v2)
{
return (abs(DotP(v1, v2)) == 0);
}
} // phanes::core::math::coretypes
#endif // !INTVECTOR3_H
#include "Core/public/Math/IntVector4.inl"

View File

@@ -0,0 +1,407 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/Detail/IntVector4Decl.inl"
#include "Core/public/Math/SIMD/SIMDIntrinsics.h"
#include "Core/public/Math/SIMD/PhanesSIMDTypes.h"
namespace Phanes::Core::Math
{
template<IntType T, bool S>
TIntVector4<T, S>::TIntVector4(const TIntVector4<T, S>& v)
{
Detail::construct_ivec4<T, S>::map(*this, v);
}
template<IntType T, bool S>
TIntVector4<T, S>::TIntVector4(const T _x, const T _y, const T _z, const T _w)
{
Detail::construct_ivec4<T, S>::map(*this, _x, _y, _z, _w);
}
template<IntType T, bool S>
TIntVector4<T, S>::TIntVector4(const T s)
{
Detail::construct_ivec4<T, S>::map(*this, s);
}
template<IntType T, bool S>
TIntVector4<T, S>::TIntVector4(const T* comp)
{
Detail::construct_ivec4<T, S>::map(*this, comp);
}
template<IntType T, bool S>
TIntVector4<T, S>::TIntVector4(const TIntVector2<T, S>& v1, const TIntVector2<T, S>& v2)
{
Detail::construct_ivec4<T, S>::map(*this, v1, v2);
}
template<IntType T, bool S>
TIntVector4<T, S>& operator+=(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
Detail::compute_ivec4_add<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator+=(TIntVector4<T, S>& v1, T s)
{
Detail::compute_ivec4_add<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator-=(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
Detail::compute_ivec4_sub<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator-=(TIntVector4<T, S>& v1, T s)
{
Detail::compute_ivec4_sub<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator*=(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
Detail::compute_ivec4_mul<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator*=(TIntVector4<T, S>& v1, T s)
{
Detail::compute_ivec4_mul<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator/=(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
Detail::compute_ivec4_div<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator/=(TIntVector4<T, S>& v1, T s)
{
Detail::compute_ivec4_div<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator%=(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
Detail::compute_ivec4_mod<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator%=(TIntVector4<T, S>& v1, T s)
{
Detail::compute_ivec4_mod<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S> operator+(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_add<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator+(TIntVector4<T, S>& v1, T s)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_add<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator-(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_sub<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator-(TIntVector4<T, S>& v1, T s)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_sub<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator*(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_mul<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator*(TIntVector4<T, S>& v1, T s)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_mul<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator/(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_div<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator/(TIntVector4<T, S>& v1, T s)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_div<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator%(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_mod<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator%(TIntVector4<T, S>& v1, T s)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_mod<T, S>::map(r, v1, s);
return r;
}
// Bitwise operators
template<IntType T, bool S>
TIntVector4<T, S>& operator&=(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
Detail::compute_ivec4_and<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator&=(TIntVector4<T, S>& v1, T s)
{
Detail::compute_ivec4_and<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator|=(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
Detail::compute_ivec4_or<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator|=(TIntVector4<T, S>& v1, T s)
{
Detail::compute_ivec4_or<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator^=(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
Detail::compute_ivec4_xor<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator^=(TIntVector4<T, S>& v1, T s)
{
Detail::compute_ivec4_xor<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator<<=(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
Detail::compute_ivec4_left_shift<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator<<=(TIntVector4<T, S>& v1, T s)
{
Detail::compute_ivec4_left_shift<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator>>=(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
Detail::compute_ivec4_right_shift<T, S>::map(v1, v1, v2);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator>>=(TIntVector4<T, S>& v1, T s)
{
Detail::compute_ivec4_right_shift<T, S>::map(v1, v1, s);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S> operator&(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_and<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator&(TIntVector4<T, S>& v1, T s)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_and<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator|(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_or<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator|(TIntVector4<T, S>& v1, T s)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_or<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator^(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_xor<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator^(TIntVector4<T, S>& v1, T s)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_xor<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator<<(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_left_shift<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator<<(TIntVector4<T, S>& v1, T s)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_left_shift<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator>>(TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_right_shift<T, S>::map(r, v1, v2);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator>>(TIntVector4<T, S>& v1, T s)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_right_shift<T, S>::map(r, v1, s);
return r;
}
template<IntType T, bool S>
TIntVector4<T, S> operator~(TIntVector4<T, S>& v1)
{
TIntVector4<T, S> r;
Detail::compute_ivec4_bnot<T, S>::map(r, v1);
return r;
}
// Comparision
template<IntType T, bool S>
bool operator==(const TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
return Detail::compute_ivec4_eq<T, S>::map(v1, v2);
}
template<IntType T, bool S>
bool operator!=(const TIntVector4<T, S>& v1, const TIntVector4<T, S>& v2)
{
return Detail::compute_ivec4_ieq<T, S>::map(v1, v2);
}
// Inc- / Decrement
template<IntType T, bool S>
TIntVector4<T, S>& operator++(TIntVector4<T, S>& v1)
{
Detail::compute_ivec4_inc<T, S>::map(v1);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator--(TIntVector4<T, S>& v1)
{
Detail::compute_ivec4_inc<T, S>::map(v1);
return v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator++(TIntVector4<T, S>& v1, int)
{
return ++v1;
}
template<IntType T, bool S>
TIntVector4<T, S>& operator--(TIntVector4<T, S>& v1, int)
{
return --v1;
}
}

View File

@@ -0,0 +1,72 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathFwd.h"
#include "Core/public/Math/Vector3.hpp"
#include <any>
namespace Phanes::Core::Math
{
// Line with direction and moment
template<RealType T>
struct TLine
{
public:
using Real = T;
/** Direction of line */
TVector3<Real, false> direction;
/** Base point of line */
TVector3<Real, false> base;
public:
/** Construct line from base and direction
*
* @param(direction) Direction of line
* @param(p) Base of line
*/
TLine(const TVector3<T, false>& direction, const TVector3<T, false>& p) : direction(direction), base(p) {};
};
/**
* Normalizes the direction of the line
*
* @param(l1) Line
*/
template<RealType T>
TLine<T>& NormalizeV(TLine<T>& l1)
{
std::any
NormalizeV(l1.direction);
return l1;
}
/**
* Normalizes the direction of the line
*
* @param(l1) Line
*
* @return Line with normalized direction.
*/
template<RealType T>
TLine<T> NormalizeV(const TLine<T>& l1)
{
return TLine<T>(Normalize(l1.direction), l1.base);
}
}

View File

@@ -0,0 +1,29 @@
#pragma once
#ifndef ABSTRACT_TYPES_H
#define ABSTRACT_TYPES_H
namespace Phanes::Core::Math::Internal {
template <typename T, unsigned int D = 3>
struct AVector {
public:
/**
* List of n components of the vector
*/
T comp[D];
};
template <typename T, unsigned int n = 3, unsigned int m = 3>
struct AMatrix {
public:
T fields[n][m];
};
}; // Phanes::Core::Math::abstract::coretypes
#endif // !ABSTRACT_TYPES_H

View File

@@ -0,0 +1,161 @@
#pragma once
#define P_FLT_INAC_LARGE 0.0001f // large float inaccuracy (1*10^-4);
#define P_FLT_INAC 0.00001f // float inaccuracy (1*10^-5);
#define P_FLT_INAC_SMALL 0.000001f // small float inaccuracy (1*10^-6);
#define P_180_PI 57.29577951308232 // (double) 180<38>/pi;
#define P_180_PI_FLT 57.29577951308232f // (float) 180<38>/pi;
#define P_PI_180 0.0174532925199432 // double pi/180<38>
#define P_PI_180_FLT 0.0174532925199432f // (float) pi/180<38>
#define P_PI 3.1415926535897932 // PI
#define P_PI_FLT 3.1415926535897932f // PI
#ifndef MATH_COMMON_H
#define MATH_COMMON_H
namespace Phanes::Core::Math {
/**
* Clamps a value between minimum and maximum
*
* @param value Value to clamp
* @param low Minimum
* @param high Maximum
*
* @return Minimum, if value is to small / Maximum, if value is to large / value, if value is in range.
*/
template<typename T>
T Clamp(T value, T low, T high)
{
if (value < low) value = low;
if (value > high) value = high;
return value;
}
/**
* Gets the larger of two values
*
* @param x
* @param y
*
* @return Larger value
*/
template<typename T>
constexpr T Max(T x, T y)
{
return (x > y) ? x : y;
}
/**
* Gets the smaller of two values
*
* @param x
* @param y
*
* @return Smaller value
*/
template<typename T>
constexpr T Min(T x, T y)
{
return (x < y) ? x : y;
}
/**
* Swaps the values of two variables
*
* @param x
* @param y
*/
template<typename T>
inline void Swap(T& x, T& y)
{
float z = x;
x = y;
y = z;
}
/**
* Test two numbers for equality
*
* @param(x)
* @param(y)
* @param(threshold) Allowed inaccuracy
*
* @return True, if equal, false if not
*/
template<typename T>
bool Equals(T x, T y, T threshold = P_FLT_INAC)
{
return (abs(x - y) < threshold);
}
/**
* Calculates the reciprocal of the square root of n using the algorithm of A Quake III
*
* @param n Number to calculate
*
* @return Inverse square root of n
*
* @note a simple 1.0f / sqrtf(x) is faster than this algorithm. Use for research purpose only.
*/
template<typename T>
float FastInvSqrt(T n)
{
int i = *(int*)&n;
float x2 = n * 0.5f;
i = 0x5f3759df - (i >> 1);
n = *(float*)&i;
n = n * (1.5f - (x2 * n * n));
return n;
}
template<typename T>
FORCEINLINE T Abs(T s)
{
return abs(s);
}
template<>
FORCEINLINE float Abs<float>(float s)
{
return (float)fabs(s);
};
template<>
FORCEINLINE long long Abs<long long>(long long s)
{
return llabs(s);
};
template<>
FORCEINLINE long Abs<long>(long s)
{
return labs(s);
};
template<>
FORCEINLINE double Abs<double>(double s)
{
return fabsl(s);
};
} // phanes
#endif // !MATH_COMMON_H

View File

@@ -0,0 +1,201 @@
#pragma once
#ifdef P_BUILD_LIB
#include "PhanesEnginePCH.h"
#else
#include <vector>
#endif
#ifndef MATH_FWD_H
#define MATH_FWD_H
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/SIMD/PhanesSIMDTypes.h"
/**
* Includes forward declarations, as well as certain useful typedefs.
*
* @ref OSAL/PlatformTypes.h
*/
namespace Phanes::Core::Math {
/**
* Template forward declarations.
*/
template<RealType T> struct TColor;
template<RealType T> struct TLinearColor;
template<RealType T> struct TLine;
template<RealType T> struct TQuaternion;
template<RealType T> struct TTransform;
template<RealType T> struct TPoint2;
template<RealType T> struct TPoint3;
template<RealType T> struct TPoint4;
template<IntType T> struct TIntPoint2;
template<IntType T> struct TIntPoint3;
template<IntType T> struct TIntPoint4;
template<RealType T> struct TMatrix2;
template<RealType T, bool S> struct TMatrix3;
template<RealType T, bool S> struct TMatrix4;
template<RealType T, bool S> struct TVector2;
template<RealType T, bool S> struct TVector3;
template<RealType T, bool S> struct TVector4;
template<IntType T, bool S> struct TIntVector2;
template<IntType T, bool S> struct TIntVector3;
template<IntType T, bool S> struct TIntVector4;
template<RealType T, bool S> struct TPlane;
template<RealType T, bool S> struct TRay;
/**
* Specific instantiation of forward declarations.
*/
// TPoint2
typedef TPoint2<float> Point2;
typedef TPoint2<float> Point2f;
typedef TPoint2<double> Point2d;
// TPoint3
typedef TPoint3<float> Point3;
typedef TPoint3<float> Point3f;
typedef TPoint3<double> Point3d;
// TPoint4
typedef TPoint4<float> Point4;
typedef TPoint4<float> Point4f;
typedef TPoint4<double> Point4d;
// TIntPoint2
typedef TIntPoint2<int> IntPoint2;
typedef TIntPoint2<int> IntPoint2i;
typedef TIntPoint2<long> IntPoint2l;
// TIntPoint3
typedef TIntPoint3<int> IntPoint3;
typedef TIntPoint3<int> IntPoint3i;
typedef TIntPoint3<long> IntPoint3l;
// TIntPoint4
typedef TIntPoint4<int> IntPoint4;
typedef TIntPoint4<int> IntPoint4i;
typedef TIntPoint4<long> IntPoint4l;
// IntVetor2
typedef TIntVector2<int, false> IntVector2;
typedef TIntVector2<int, false> Vector2i;
typedef TIntVector2<long, false> LongVector2;
typedef TIntVector2<long, false> Vector2l;
// IntVetor3
typedef TIntVector3<int, false> IntVector3;
typedef TIntVector3<int, false> Vector3i;
typedef TIntVector3<long, false> LongVector3;
typedef TIntVector3<long, false> Vector3l;
// IntVetor4
typedef TIntVector4<int, false> IntVector4;
typedef TIntVector4<int, false> Vector4i;
typedef TIntVector4<long, false> LongVector4;
typedef TIntVector4<long, false> Vector4l;
// Vector2
typedef TVector2<float, false> Vector2;
typedef TVector2<float, false> Vector2f;
typedef TVector2<double, false> Vector2d;
typedef TVector2<double, SIMD::use_simd<double, 2, true>::value> Vector2Regf64;
typedef TVector2<double, SIMD::use_simd<double, 2, true>::value> Vector2Reg;
typedef TVector2<double, SIMD::use_simd<double, 2, true>::value> Vector2Regd;
// Vector3
typedef TVector3<float, false> Vector3;
typedef TVector3<float, false> Vector3f;
typedef TVector3<double, false> Vector3d;
typedef TVector3<float, SIMD::use_simd<float, 3, true>::value> Vector3Reg;
typedef TVector3<float, SIMD::use_simd<float, 3, true>::value> Vector3Regf32;
typedef TVector3<double, SIMD::use_simd<double, 3, true>::value> Vector3Regd;
typedef TVector3<double, SIMD::use_simd<double, 3, true>::value> Vector3Regf64;
// Vector4
typedef TVector4<float, false> Vector4;
typedef TVector4<float, false> Vector4f;
typedef TVector4<double, false> Vector4d;
typedef TVector4<float, SIMD::use_simd<float, 4, true>::value> Vector4Reg;
typedef TVector4<float, SIMD::use_simd<float, 4, true>::value> Vector4Regf32;
typedef TVector4<double, SIMD::use_simd<double, 4, true>::value> Vector4Regd;
typedef TVector4<double, SIMD::use_simd<double, 4, true>::value> Vector4Regf64;
// Matrix2
typedef TMatrix2<float> Matrix2;
typedef TMatrix2<float> Matrix2f;
typedef TMatrix2<double> Matrix2d;
// Matrix3
typedef TMatrix3<float, false> Matrix3;
typedef TMatrix3<float, false> Matrix3f;
typedef TMatrix3<double, false> Matrix3d;
typedef TMatrix3<float, SIMD::use_simd<float, 3, true>::value> Matrix3Reg;
typedef TMatrix3<float, SIMD::use_simd<float, 3, true>::value> Matrix3Regf;
typedef TMatrix3<double, SIMD::use_simd<double, 3, true>::value> Matrix3Regd;
typedef TMatrix3<double, SIMD::use_simd<double, 3, true>::value> Matrix3Regf64;
// Matrix4
typedef TMatrix4<float, false> Matrix4;
typedef TMatrix4<float, false> Matrix4f;
typedef TMatrix4<double, false> Matrix4d;
typedef TMatrix3<float, SIMD::use_simd<float, 4, true>::value> Matrix4Reg;
typedef TMatrix3<float, SIMD::use_simd<float, 4, true>::value> Matrix4Regf;
typedef TMatrix3<double, SIMD::use_simd<double, 4, true>::value> Matrix4Regd;
typedef TMatrix3<double, SIMD::use_simd<double, 4, true>::value> Matrix4Regf64;
// TPlane
typedef TPlane<float, false> Plane;
typedef TPlane<float, false> Planef;
typedef TPlane<double, false> Planed;
typedef TPlane<float, SIMD::use_simd<float, 4, true>::value> PlaneReg;
typedef TPlane<float, SIMD::use_simd<double, 4, true>::value> PlaneRegd;
} // Phanes::Core::Math::coretypes
namespace Phanes::Core::Math::Internal
{
// Internal types
template <typename T, unsigned int D> struct AVector;
template <typename T, unsigned int n, unsigned int> struct AMatrix;
}
#endif // !MATH_FWD_H

View File

@@ -0,0 +1,27 @@
// Header file containing all files to be compiled to use core math.
// Should be included in PCH file of project to use.
#pragma once
#include "Core/public/Math/Point.hpp"
#include "Core/public/Math/Plane.hpp"
#include "Core/public/Math/Line.hpp"
#include "Core/public/Math/Ray.hpp"
#include "Core/public/Math/Vector2.hpp"
#include "Core/public/Math/Vector3.hpp"
#include "Core/public/Math/Vector4.hpp"
#include "Core/public/Math/IntPoint.hpp"
#include "Core/public/Math/IntVector2.hpp"
#include "Core/public/Math/IntVector3.hpp"
#include "Core/public/Math/IntVector4.hpp"
#include "Core/public/Math/Matrix2.hpp"
#include "Core/public/Math/Matrix3.hpp"
#include "Core/public/Math/Matrix4.hpp"
#include "Core/public/Math/MathCommon.hpp"
#include "Core/public/Math/MathTypeConversion.hpp"
#include "Core/public/Math/MathUnitConversion.hpp"

View File

@@ -0,0 +1,128 @@
#pragma once
// ============================================= //
// Function to convert types into each other //
// //
// @ref [FILE]MathUnitConversion //
// ============================================= //
#ifdef P_BUILD_LIB
#include "PhanesEnginePCH.h"
#else
#include <string>
#endif
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathAbstractTypes.h"
#include "Core/public/Math/Vector2.hpp"
#include "Core/public/Math/Vector3.hpp"
#include "Core/public/Math/Vector4.hpp"
#include "Core/public/Math/Matrix2.hpp"
#include "Core/public/Math/Matrix3.hpp"
#include "Core/public/Math/Matrix4.hpp"
#include "Core/public/Math/IntVector2.hpp"
#include "Core/public/Math/IntVector3.hpp"
#include "Core/public/Math/IntVector4.hpp"
#ifndef MATH_TYPE_CONVERSION_H
#define MATH_TYPE_CONVERSION_H
namespace Phanes::Core::Math {
// =================================================== //
// std::to_string wrapper //
// //
// This is, to make using ToString more general //
// and allow usage of one function instead of two, //
// for converting a mathmatical type to a string. //
// =================================================== //
FORCEINLINE std::string ToString(long long val) { return std::to_string(val); };
FORCEINLINE std::string ToString(double val) { return std::to_string(val); };
FORCEINLINE std::string ToString(float val) { return std::to_string(val); };
FORCEINLINE std::string ToString(int val) { return std::to_string(val); };
FORCEINLINE std::string ToString(long val) { return std::to_string(val); };
FORCEINLINE std::string ToString(long double val) { return std::to_string(val); };
FORCEINLINE std::string ToString(unsigned long long val) { return std::to_string(val); };
FORCEINLINE std::string ToString(unsigned int val) { return std::to_string(val); };
FORCEINLINE std::string ToString(unsigned long val) { return std::to_string(val); };
// ============ //
// ToString //
// ============ //
template<RealType T, bool S>
std::string ToString(const TVector2<T, S>& v)
{
return "(" + ToString(v.x) + ", " + ToString(v.y) + ")";
}
template<IntType T, bool S>
std::string ToString(const TIntVector2<T, S>& v)
{
return "(" + ToString(v.x) + ", " + ToString(v.y) + ")";
}
template<RealType T, bool S>
std::string ToString(const TVector3<T, S>& v)
{
return "(" + ToString(v.x) + ", " + ToString(v.y) + ", " + ToString(v.z) + ")";
}
template<IntType T, bool S>
std::string ToString(const TIntVector3<T, S>& v)
{
return "(" + ToString(v.x) + ", " + ToString(v.y) + ", " + ToString(v.z) + ")";
}
template<RealType T, bool S>
std::string ToString(const TVector4<T, S>& v)
{
return "(" + ToString(v.x) + ", " + ToString(v.y) + ", " + ToString(v.z) + ", " + ToString(v.w) + ")";
}
template<IntType T, bool S>
std::string ToString(const TIntVector4<T, S>& v)
{
return "(" + ToString(v.x) + ", " + ToString(v.y) + ", " + ToString(v.z) + ", " + ToString(v.w) + ")";
}
template<RealType T>
std::string ToString(const TMatrix2<T>& m)
{
return "([" + ToString(m(0, 0)) + ", " + ToString(m(0, 1)) + "], [" +
ToString(m(1, 0)) + ", " + ToString(m(1, 1)) + "])";
}
template<RealType T, bool S>
std::string ToString(const TMatrix3<T, S>& m)
{
return "([" + ToString(m(0, 0)) + ", " + ToString(m(0, 1)) + ", " + ToString(m(0, 2)) + "], [" +
ToString(m(1, 0)) + ", " + ToString(m(1, 1)) + ", " + ToString(m(1, 2)) + "], [" +
ToString(m(2, 0)) + ", " + ToString(m(2, 1)) + ", " + ToString(m(2, 2)) + "])";
}
template<RealType T, bool S>
std::string ToString(const TMatrix4<T, S>& m)
{
return "([" + ToString(m(0, 0)) + ", " + ToString(m(0, 1)) + ", " + ToString(m(0, 2)) + ", " + ToString(m(0, 3)) + "], [" +
ToString(m(1, 0)) + ", " + ToString(m(1, 1)) + ", " + ToString(m(1, 2)) + ", " + ToString(m(1, 3)) + "], [" +
ToString(m(2, 0)) + ", " + ToString(m(2, 1)) + ", " + ToString(m(2, 2)) + ", " + ToString(m(2, 3)) + "], [" +
ToString(m(3, 0)) + ", " + ToString(m(3, 1)) + ", " + ToString(m(3, 2)) + ", " + ToString(m(3, 3)) + "])";
}
}
#endif // !MATH_TYPE_CONVERSION_H

View File

@@ -0,0 +1,111 @@
#pragma once
#ifdef P_BUILD_LIB
# include "PhanesEnginePCH.h"
#else
# define NOMINMAX
# include <stdint.h>
#endif
// ============================================= //
// Turn os specific types into global types. //
// ============================================= //
// TODO: include int128
namespace Phanes::Core::Types
{
#ifdef P_WIN_BUILD
// MSVC specific types
typedef _FLOAT128 float128;
#endif
// Specific types size
//
// 8-Bit integer
typedef int8_t int8;
// 16-Bit integer
typedef int16_t int16;
// 32-Bit integer
typedef int32_t int32;
// 64-Bit integer
typedef int64_t int64;
// 8-Bit unsigned integer
typedef uint8_t uint8;
// 16-Bit unsigned integer
typedef uint16_t uint16;
// 32-Bit unsigned integer
typedef uint32_t uint32;
// 64-Bit unsigned integer
typedef uint64_t uint64;
// At least N bit types
//
// At least 8-Bit integer
typedef int_least8_t lint8;
// At least 16-Bit integer
typedef int_least16_t lint16;
// At least 32-Bit integer
typedef int_least32_t lint32;
// At least 64-Bit integer
typedef int_least64_t lint64;
// At least 8-Bit integer
typedef uint_least8_t ulint8;
// At least 16-Bit integer
typedef uint_least16_t ulint16;
// At least 32-Bit integer
typedef uint_least32_t ulint32;
// At least 64-Bit integer
typedef uint_least64_t ulint64;
// Fast N bit types
//
// Fast 8-bit integer
typedef int_fast8_t fint8;
// At least 16-Bit integer
typedef int_fast16_t fint16;
// At least 32-Bit integer
typedef int_fast32_t fint32;
// At least 64-Bit integer
typedef int_fast64_t fint64;
// At least 8-Bit integer
typedef uint_fast8_t ufint8;
// At least 16-Bit integer
typedef uint_fast16_t ufint16;
// At least 32-Bit integer
typedef uint_fast32_t ufint32;
// At least 64-Bit integer
typedef uint_fast64_t ufint64;
}

View File

@@ -0,0 +1,139 @@
#pragma once
// ======================================= //
// Contains functions to convert units //
// ======================================= //
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathCommon.hpp"
namespace Phanes::Core::Math::UnitConversion
{
/**
* Converts degrees to radians.
*
* @param(deg) Angle in degress (<28>)
*
* @return Angle in radians
*/
template<RealType T>
inline T DegToRad(T deg)
{
return deg * P_PI_180_FLT;
}
/**
* Converts radians to degrees.
*
* @param(rad) Angle in radians (rad)
*
* @return Angle in degrees
*/
template<RealType T>
inline T RadToDeg(T rad)
{
return rad * P_180_PI_FLT;
}
/**
* Converts degrees to gradian.
*
* @param(deg) Angle in degress (<28>)
*
* @return Angle in gradian
*/
template<RealType T>
inline T DegToGradian(T deg)
{
return deg * 1.111111f;
}
/**
* Converts gradian to degrees.
*
* @param(rad) Angle in gradians (g)
*
* @return Angle in degrees
*/
template<RealType T>
inline T GradianToDeg(T g)
{
return g * 0.9f;
}
/**
* Converts radians to gradians.
*
* @param(deg) Angle in radians (rad)
*
* @return Angle in gradians
*/
template<RealType T>
inline T RadToGradian(T rad)
{
return rad * 200 / P_PI_FLT;
}
/**
* Converts gradian to radians.
*
* @param(rad) Angle in gradians (g)
*
* @return Angle in radians
*/
template<RealType T>
inline T GradianToRad(T g)
{
return g * P_PI_FLT / 200;
}
} // phanes::core::math::typeconversion
namespace Phanes::Core::Math::UnitLiterals
{
// ============================================== //
// unit conversion with user-defined literals //
// ============================================== //
/**
* Convert deg to rad.
*
* @param(_x) Angle in degress
*/
double operator ""_deg(long double _x)
{
return _x * P_PI_180_FLT;
}
/**
* Convert rad to rad.
*
* @param(_x) Angle in degress
*/
double operator ""_rad(long double _x)
{
return _x;
}
/**
* Convert gradian to rad.
*
* @param(_x) Angle in degress
*/
double operator ""_g(long double _x)
{
return _x * P_PI_FLT / 200;
}
}

View File

@@ -0,0 +1,358 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathFwd.h"
#include "Core/public/Math/Vector2.hpp"
#ifndef MATRIX2_H
#define MATRIX2_H
namespace Phanes::Core::Math {
// 2x2 Matrix defined in column-major order.
// Accessed by M[Row][Col].
template<RealType T>
struct TMatrix2
{
public:
union
{
struct
{
/// <summary>
/// Column one.
/// </summary>
TVector2<T, false> c0;
/// <summary>
/// Column two
/// </summary>
TVector2<T, false> c1;
};
T data[2][2];
};
public:
TMatrix2() = default;
/**
* Copy constructor.
*/
TMatrix2(const TMatrix2<T>& m1)
{
this->c0 = m1.c0;
this->c1 = m1.c1;
}
/**
* Construct Matrix from 2d array.
*
* @param(fields) 2D Array with column major order.
*/
TMatrix2(T fields[2][2])
{
this->data[0][0] = fields[0][0]; this->data[1][0] = fields[1][0];
this->data[0][1] = fields[0][1]; this->data[1][1] = fields[1][1];
}
/**
* Construct Matrix from parameters.
*
* @param(n00) M[0][0]
* @param(n10) M[1][0]
* @param(n01) M[0][1]
* @param(n11) M[1][1]
*
* @note nXY = n[Row][Col]
*/
TMatrix2(T n00, T n01, T n10, T n11)
{
this->data[0][0] = n00; this->data[1][0] = n01;
this->data[0][1] = n10; this->data[1][1] = n11;
}
/**
* Construct Matrix from two 2d vector columns.
*
* @param(v1) Column zero
* @param(v2) Column one
*/
TMatrix2(const TVector2<T, false>& v1, const TVector2<T, false>& v2)
{
this->c0 = v1;
this->c1 = v2;
}
public:
T& operator() (int n, int m)
{
return this->data[m][n];
}
T operator() (int n, int m) const
{
return this->data[m][n];
}
TVector2<T, false>& operator[] (int m)
{
switch (m)
{
case 0:
return this->c0;
case 1:
return this->c1;
}
throw std::invalid_argument("m is outside valid range.");
}
TVector2<T, false> operator[] (int m) const
{
switch (m)
{
case 0:
return this->c0;
case 1:
return this->c1;
}
throw std::invalid_argument("m is outside valid range.");
}
};
// ====================== //
// TMatrix2 operator //
// ====================== //
template<RealType T>
TMatrix2<T>& operator+= (TMatrix2<T>& m1, T s)
{
m1(0, 0) += s;
m1(0, 1) += s;
m1(1, 0) += s;
m1(1, 1) += s;
return m1;
}
template<RealType T>
TMatrix2<T>& operator+= (TMatrix2<T>& m1, const TMatrix2<T>& m2)
{
m1(0, 0) += m2(0, 0);
m1(0, 1) += m2(0, 1);
m1(1, 0) += m2(1, 0);
m1(1, 1) += m2(1, 1);
return m1;
}
template<RealType T>
TMatrix2<T>& operator-= (TMatrix2<T>& m1, T s)
{
m1(0, 0) -= s;
m1(0, 1) -= s;
m1(1, 0) -= s;
m1(1, 1) -= s;
return m1;
}
template<RealType T>
TMatrix2<T>& operator-= (TMatrix2<T>& m1, const TMatrix2<T>& m2)
{
m1(0, 0) -= m2(0, 0);
m1(0, 1) -= m2(0, 1);
m1(1, 0) -= m2(1, 0);
m1(1, 1) -= m2(1, 1);
return m1;
}
template<RealType T>
TMatrix2<T>& operator*= (TMatrix2<T>& m1, T s)
{
m1.data[0][0] *= s;
m1.data[0][1] *= s;
m1.data[1][0] *= s;
m1.data[1][1] *= s;
return m1;
}
template<RealType T>
TMatrix2<T>& operator*= (TMatrix2<T>& m1, const TMatrix2<T>& m2)
{
TMatrix2<T> c = m1;
m1(0, 0) = c(0, 0) * m2(0, 0) + c(0, 1) * m2(1, 0);
m1(0, 1) = c(0, 0) * m2(0, 1) + c(0, 1) * m2(1, 1);
m1(1, 0) = c(1, 0) * m2(0, 0) + c(1, 1) * m2(1, 0);
m1(1, 1) = c(1, 0) * m2(0, 1) + c(1, 1) * m2(1, 1);
return m1;
}
template<RealType T>
TMatrix2<T>& operator/= (TMatrix2<T>& m1, T s)
{
s = (T)1.0 / s;
m1.data[0][0] *= s;
m1.data[0][1] *= s;
m1.data[1][0] *= s;
m1.data[1][1] *= s;
return m1;
}
template<RealType T>
TMatrix2<T> operator+ (const TMatrix2<T>& m1, T s)
{
return TMatrix2<T>(m1(0, 0) + s, m1(0, 1) + s,
m1(1, 0) + s, m1(1, 1) + s);
}
template<RealType T>
TMatrix2<T> operator+ (const TMatrix2<T>& m1, const TMatrix2<T>& m2)
{
return TMatrix2<T>(m1(0, 0) + m2(0, 0), m1(0, 1) + m2(0, 1),
m1(1, 0) + m2(1, 0), m1(1, 1) + m2(1, 1));
}
template<RealType T>
TMatrix2<T> operator- (const TMatrix2<T>& m1, T s)
{
return TMatrix2<T>(m1(0, 0) - s, m1(0, 1) - s,
m1(1, 0) - s, m1(1, 1) - s);
}
template<RealType T>
TMatrix2<T> operator- (const TMatrix2<T>& m1, const TMatrix2<T>& m2)
{
return TMatrix2<T>(m1(0, 0) - m2(0, 0), m1(0, 1) - m2(0, 1),
m1(1, 0) - m2(1, 0), m1(1, 1) - m2(1, 1));
}
template<RealType T>
TMatrix2<T> operator* (const TMatrix2<T>& m1, T s)
{
return TMatrix2<T>(m1(0, 0) * s, m1(0, 1) * s,
m1(1, 0) * s, m1(1, 1) * s);
}
template<RealType T>
TMatrix2<T> operator/ (const TMatrix2<T>& m1, T s)
{
s = (T)1.0 / s;
return TMatrix2<T>(m1(0, 0) * s, m1(0, 1) * s,
m1(1, 0) * s, m1(1, 1) * s);
}
template<RealType T>
TMatrix2<T> operator* (const TMatrix2<T>& m1, const TMatrix2<T>& m2)
{
return TMatrix2<T>(m1(0, 0) * m2(0, 0) + m1(0, 1) * m2(1, 0), m1(0, 0) * m2(0, 1) + m1(0, 1) * m2(1, 1),
m1(1, 0) * m2(0, 0) + m1(1, 1) * m2(1, 0), m1(1, 0) * m2(0, 1) + m1(1, 1) * m2(1, 1));
}
template<RealType T>
TVector2<T, false> operator* (const TMatrix2<T>& m1, const TVector2<T, false>& v)
{
return TVector2<T, false>(m1(0, 0) * v.x + m1(0, 1) * v.y,
m1(1, 0) * v.x + m1(1, 1) * v.y);
}
template<RealType T>
bool operator== (const TMatrix2<T>& m1, const TMatrix2<T>& m2)
{
return m1[0] == m2[0] && m1[1] == m2[1];
}
template<RealType T>
bool operator!= (const TMatrix2<T>& m1, const TMatrix2<T>& m2)
{
return m1[0] != m2[0] || m1[1] != m2[1];
}
// ============================== //
// Matrix function definition //
// ============================== //
template<RealType T>
T Determinant(const TMatrix2<T>& m1)
{
return m1(0, 0) * m1(1, 1) - m1(0, 1) * m1(1, 0);
}
template<RealType T>
TMatrix2<T>& InverseV(TMatrix2<T>& m1)
{
float _1_det = 1.0f / Determinant(m1);
float m00 = m1(0, 0);
m1(0, 0) = m1(1, 1);
m1(0, 1) = -m1(0, 1);
m1(1, 0) = -m1(1, 0);
m1(1, 1) = m00;
m1 *= _1_det;
return m1;
}
template<RealType T>
TMatrix2<T>& TransposeV(TMatrix2<T>& m1)
{
Swap(m1(0, 1), m1(1, 0));
return m1;
}
// =============== //
// WITH RETURN //
// =============== //
template<RealType T>
TMatrix2<T> Inverse(TMatrix2<T>& m1)
{
float _1_det = 1.0f / Determinant(m1);
return TMatrix2<T>( m1(1, 1) * _1_det, -m1(0, 1) * _1_det,
-m1(1, 0) * _1_det, m1(0, 0) * _1_det);
}
template<RealType T>
TMatrix2<T> Transpose(const TMatrix2<T>& m1)
{
return TMatrix2<T>(m1(0, 0), m1(1, 0),
m1(0, 1), m1(1, 1));
}
template<RealType T>
bool IsIdentityMatrix(const TMatrix2<T>& m1, T threshold = P_FLT_INAC)
{
return (abs(m1(0, 0) - (T)1.0) < P_FLT_INAC && abs(m1(0, 1)) < P_FLT_INAC &&
abs(m1(1, 0)) < P_FLT_INAC && abs(m1(1, 1) - (T)1.0) < P_FLT_INAC);
}
} // Phanes::Core::Math
#endif // !MATRIX2_H
#include "Core/public/Math/SIMD/SIMDIntrinsics.h"

View File

@@ -0,0 +1,550 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathAbstractTypes.h"
#include "Core/public/Math/MathFwd.h"
#include "Core/public/Math/Vector3.hpp"
#ifndef MATRIX3_H
#define MATRIX3_H
namespace Phanes::Core::Math {
// 3x3 Matrix defined in column-major order.
// Accessed by M[Row][Col].
template<RealType T, bool S>
struct TMatrix3
{
public:
union
{
struct
{
/// <summary>
/// Column one.
/// </summary>
TVector3<T, S> c0;
/// <summary>
/// Column two.
/// </summary>
TVector3<T, S> c1;
/// <summary>
/// Column three.
/// </summary>
TVector3<T, S> c2;
};
T data[3][4];
};
public:
TMatrix3() = default;
TMatrix3(TMatrix3<T, S>&& m)
: c0(std::move(m.c0)), c1(std::move(m.c1)), c2(std::move(m.c2))
{};
TMatrix3(const TMatrix3<T, S>& m)
: c0(m.c0), c1(m.c1), c2(m.c2)
{};
/**
* Construct Matrix from 2d array.
*
* @param(fields) 2D Array with row major order.
*/
TMatrix3(T fields[3][3])
{
this->c0 = TVector3<T, S>(fields[0][0], fields[1][0], fields[2][0]);
this->c1 = TVector3<T, S>(fields[0][1], fields[1][1], fields[2][1]);
this->c2 = TVector3<T, S>(fields[0][2], fields[1][2], fields[2][2]);
}
/**
* Construct Matrix from parameters.
*
* @param(n00) M[0][0]
* @param(n10) M[0][1]
* @param(n20) M[0][2]
* @param(n01) M[1][0]
* ...
*
* @note nXY = n[Row][Col]
*/
TMatrix3(T n00, T n01, T n02,
T n10, T n11, T n12,
T n20, T n21, T n22)
{
this->c0 = TVector3<T, S>(n00,n10,n20);
this->c1 = TVector3<T, S>(n01,n11,n21);
this->c2 = TVector3<T, S>(n02,n12,n22);
}
/**
* Construct Matrix from two 2d vector columns.
*
* @param(v1) Column zero
* @param(v2) Column one
*/
TMatrix3(const TVector3<T, S>& v1, const TVector3<T, S>& v2, const TVector3<T, S> v3)
{
this->c0 = v1;
this->c1 = v2;
this->c2 = v3;
}
TMatrix3<T, S>& operator= (TMatrix3<T, S>&& m)
{
if (this != &m)
{
this->c0 = std::move(m.c0);
this->c1 = std::move(m.c1);
this->c2 = std::move(m.c2);
}
return *this;
}
TMatrix3<T, S>& operator= (const TMatrix3<T, S>& m)
{
if (this != &m)
{
this->c0 = m.c0;
this->c1 = m.c1;
this->c2 = m.c2;
}
return *this;
}
public:
FORCEINLINE T operator() (int n, int m) const
{
return this->data[m][n];
}
FORCEINLINE T& operator() (int n, int m)
{
return this->data[m][n];
}
FORCEINLINE TVector3<T, S>& operator[] (int m)
{
return (*reinterpret_cast<TVector3<T, S>*>(this->data[m]));
}
FORCEINLINE const TVector3<T, S> operator[] (int m) const
{
return (*reinterpret_cast<TVector3<T, S>*>(this->data[m]));
}
};
// ==================== //
// Matrix3 operator //
// ==================== //
/**
* Adds scalar to matrix componentwise
*
* @param(m) Matrix
* @param(s) Scalar
*/
template<RealType T, bool S>
TMatrix3<T, S>& operator+= (TMatrix3<T, S>& m1, T s)
{
m1.c0 += s;
m1.c1 += s;
m1.c2 += s;
return m1;
}
/**
* Adds matrix to matrix componentwise
*
* @param(m1) Matrix
* @param(m2) Matrix
*/
template<RealType T, bool S>
TMatrix3<T, S>& operator+= (TMatrix3<T, S>& m1, const TMatrix3<T, S>& m2)
{
m1.c0 += m2.c0;
m1.c1 += m2.c1;
m1.c2 += m2.c2;
return m1;
}
/**
* Substract scalar from matrix componentwise
*
* @param(m) Matrix
* @param(s) Scalar
*/
template<RealType T, bool S>
TMatrix3<T, S>& operator-= (TMatrix3<T, S>& m1, T s)
{
m1.c0 -= s;
m1.c1 -= s;
m1.c2 -= s;
return m1;
}
/**
* Substract matrix from matrix componentwise
*
* @param(m1) Matrix
* @param(m2) Matrix
*/
template<RealType T, bool S>
TMatrix3<T, S>& operator-= (TMatrix3<T, S>& m1, const TMatrix3<T, S>& m2)
{
m1.c0 -= m2.c0;
m1.c1 -= m2.c1;
m1.c2 -= m2.c2;
return m1;
}
/**
* Multiply matrix with scalar
*
* @param(m1) Matrix
* @param(s) Scalar
*/
template<RealType T, bool S>
TMatrix3<T, S>& operator*= (TMatrix3<T, S>& m1, T s)
{
m1.c0 *= s;
m1.c1 *= s;
m1.c2 *= s;
return m1;
}
/**
* Matrix on matrix (componentwise)
*
* @param(m1) Matrix
* @param(m2) Matrix
*/
template<RealType T, bool S>
TMatrix3<T, S>& operator*= (TMatrix3<T, S>& m1, const TMatrix3<T, S>& m2);
/**
* Multiply matrix with scalar
*
* @param(m1) Matrix
* @param(s) Scalar
*/
template<RealType T, bool S>
TMatrix3<T, S>& operator/= (TMatrix3<T, S>& m1, T s)
{
s = (T)1.0 / s;
m1.c0 *= s;
m1.c1 *= s;
m1.c2 *= s;
return m1;
}
/**
* Matrix on matrix (componentwise)
*
* @param(m1) Matrix
* @param(m2) Matrix
*/
template<RealType T, bool S>
TMatrix3<T, S>& operator/= (TMatrix3<T, S>& m1, const TMatrix3<T, S>& m2)
{
m1.c0 /= m2.c0;
m1.c1 /= m2.c1;
m1.c2 /= m2.c2;
return m1;
}
/**
* Add scalar to matrix componentwise
*
* @param(m1) Matrix
* @param(s) Scalar
*/
template<RealType T, bool S>
TMatrix3<T, S> operator+ (const TMatrix3<T, S>& m, T s)
{
return TMatrix3<T, S>(m.c0 + s,
m.c1 + s,
m.c2 + s);
}
/**
* Add matrix to matrix componentwise
*
* @param(m1) Matrix
* @param(m2) Matrix
*/
template<RealType T, bool S>
TMatrix3<T, S> operator+ (const TMatrix3<T, S>& m1, const TMatrix3<T, S>& m2)
{
return TMatrix3<T, S>(m1.c0 + m2.c0,
m1.c1 + m2.c1,
m1.c2 + m2.c2);
}
/**
* Add scalar to matrix componentwise
*
* @param(m) Matrix
* @param(s) Scalar
*/
template<RealType T, bool S>
TMatrix3<T, S> operator- (const TMatrix3<T, S>& m, T s)
{
return TMatrix3<T, S>(m.c0 - s,
m.c1 - s,
m.c2 - s);
}
/**
* Add scalar to matrix componentwise
*
* @param(m) Matrix
* @param(s) Scalar
*/
template<RealType T, bool S>
TMatrix3<T, S> operator- (const TMatrix3<T, S>& m1, const TMatrix3<T, S>& m2)
{
return TMatrix3<T, S>(m1.c0 - m2.c0,
m1.c1 - m2.c1,
m1.c2 - m2.c2);
}
/**
* Multiply scalar with matrix
*
* @param(m) Matrix
* @param(s) Scalar
*/
template<RealType T, bool S>
TMatrix3<T, S> operator* (const TMatrix3<T, S>& m, float s)
{
return TMatrix3<T, S>(m.c0 * s,
m.c1 * s,
m.c2 * s);
}
/**
* Multiply scalar with matrix
*
* @param(m) Matrix
* @param(s) Scalar
*/
template<RealType T, bool S>
TMatrix3<T, S> operator/ (const TMatrix3<T, S>& m, float s)
{
s = (T)1.0 / s;
return TMatrix3<T, S>(m.c0 * s,
m.c1 * s,
m.c2 * s);
}
/**
* Multiplay matrix by matrix (componentwise)
*
* @param(m1) Matrix
* @param(m2) Matrix
*/
template<RealType T, bool S>
TMatrix3<T, S> operator* (const TMatrix3<T, S>& m1, const TMatrix3<T, S>& m2);
template<RealType T, bool S>
TVector3<T, S> operator* (const TMatrix3<T, S>& m1, const TVector3<T, S>& v);
/**
* Compare matrix with other matrix.
*
* @param(m1) Matrix
* @param(m2) Matrix
*/
template<RealType T, bool S>
bool operator== (const TMatrix3<T, S>& m1, const TMatrix3<T, S>& m2)
{
return (m1.c0 == m2.c0 && m1.c1 == m2.c1 && m1.c2 == m2.c2);
}
/**
* Compare matrix with other matrix.
*
* @param(m1) Matrix
* @param(m2) Matrix
*/
template<RealType T, bool S>
bool operator!= (const TMatrix3<T, S>& m1, const TMatrix3<T, S>& m2)
{
return (m1.c0 != m2.c0 || m1.c1 != m2.c1 || m1.c2 != m2.c2);
}
// =============================== //
// Matrix function definition //
// =============================== //
/**
* Calculate determinant of 3x3 Matrix
*
* @param(m1) Matrix
*/
template<RealType T, bool S>
T Determinant(const TMatrix3<T, S>& m1)
{
return m1(0, 0) * (m1(1, 1) * m1(2, 2) - m1(1, 2) * m1(2, 1))
- m1(0, 1) * (m1(1, 0) * m1(2, 2) - m1(1, 2) * m1(2, 0))
+ m1(0, 2) * (m1(1, 0) * m1(2, 1) - m1(1, 1) * m1(2, 0));
}
/**
* Calculate inverse of 3x3 Matrix
*
* @see [FUNC]Inverse
*
* @param(m1) Matrix
*
* @note Stores result in m1.
*/
template<RealType T, bool S>
bool InverseV(TMatrix3<T, S>& m1)
{
// Rows of inversed matrix
TVector3<T, S> r0 = CrossP(m1.c1, m1.c2);
TVector3<T, S> r1 = CrossP(m1.c2, m1.c0);
TVector3<T, S> r2 = CrossP(m1.c0, m1.c1);
T _1_det = (T)1.0 / Determinant(m1);
if (_1_det == (T)0.0)
{
return false;
}
// Store matrix transposed
m1 = TMatrix3<T, S>(r0.x, r0.y, r0.z,
r1.x, r1.y, r1.z,
r2.x, r2.y, r2.z);
m1 *= _1_det;
return true;
}
/**
* Get transpose of matrix.
*
* @param(m1) Matrix
*
* @note Result is stored in m1;
*/
template<RealType T, bool S>
TMatrix3<T, S>& TransposeV(TMatrix3<T, S>& m1);
// =============== //
// WITH RETURN //
// =============== //
/**
* Calculate inverse of 3x3 Matrix
*
* @param(m1) Matrix
*/
template<RealType T, bool S>
bool Inverse(const TMatrix3<T, S>& m1, Ref<TMatrix3<T, S>> r)
{
// r is a row-major matrix.
TMatrix3<T, S> row;
row[0] = CrossP(m1.c1, m1.c2);
row[1] = CrossP(m1.c2, m1.c0);
row[2] = CrossP(m1.c0, m1.c1);
T _1_det = (T)1.0 / Determinant(m1);
if (Phanes::Core::Math::Equals(_1_det, (T)0.0))
{
return false;
}
row *= _1_det;
// Store matrix transposed.
(*r).data[0][0] = row.data[0][0]; (*r).data[1][0] = row.data[0][1]; (*r).data[2][0] = row.data[0][2];
(*r).data[0][1] = row.data[1][0]; (*r).data[1][1] = row.data[1][1]; (*r).data[2][1] = row.data[1][2];
(*r).data[0][2] = row.data[2][0]; (*r).data[1][2] = row.data[2][1]; (*r).data[2][2] = row.data[2][2];
return true;
}
/**
* Get transpose of matrix.
*
* @param(m1) Matrix
*
* @note Result is stored in m1;
*/
template<RealType T, bool S>
TMatrix3<T, S> Transpose(const TMatrix3<T, S>& m1);
/**
* Checks if matrix is an identity matrix.
*/
template<RealType T, bool S>
bool IsIdentityMatrix(const TMatrix3<T, S>& m1)
{
return (abs(m1(0, 0) - (T)1.0) < P_FLT_INAC && abs(m1(0, 1)) < P_FLT_INAC && abs(m1(0, 2)) < P_FLT_INAC &&
abs(m1(1, 0)) < P_FLT_INAC && abs(m1(1, 1) - (T)1.0) < P_FLT_INAC && abs(m1(1, 2)) < P_FLT_INAC &&
abs(m1(2, 0)) < P_FLT_INAC && abs(m1(2, 1)) < P_FLT_INAC && abs(m1(2, 2) - (T)1.0) < P_FLT_INAC);
}
} // Phanes::Core::Math
#endif // !MATRIX3_H
#include "Core/public/Math/Matrix3.inl"

View File

@@ -0,0 +1,51 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/Detail/Matrix3Decl.inl"
#include "Core/public/Math/SIMD/SIMDIntrinsics.h"
#include "Core/public/Math/SIMD/PhanesSIMDTypes.h"
namespace Phanes::Core::Math
{
template<RealType T, bool S>
TMatrix3<T, S>& TransposeV(TMatrix3<T, S>& m)
{
Detail::compute_mat3_transpose<T, S>::map(m, m);
return m;
}
template<RealType T, bool S>
TMatrix3<T, S> Transpose(const TMatrix3<T, S>& m)
{
TMatrix3<T, S> r;
Detail::compute_mat3_transpose<T, S>::map(r, m);
return r;
}
template<RealType T, bool S>
TMatrix3<T, S>& operator*= (TMatrix3<T, S>& m1, const TMatrix3<T, S>& m2)
{
TMatrix3<T, S> r;
Detail::compute_mat3_mul<T, S>::map(r, m1, m2);
return (m1 = r);
}
template<RealType T, bool S>
TMatrix3<T, S> operator* (const TMatrix3<T, S>& m1, const TMatrix3<T, S>& m2)
{
TMatrix3<T, S> r;
Detail::compute_mat3_mul<T, S>::map(r, m1, m2);
return r;
}
template<RealType T, bool S>
TVector3<T, S> operator* (const TMatrix3<T, S>& m1, const TVector3<T, S>& v)
{
TVector3<T, S> r;
Detail::compute_mat3_mul<T, S>::map(r, m1, v);
return r;
}
}

View File

@@ -0,0 +1,334 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathAbstractTypes.h"
#include "Core/public/Math/MathFwd.h"
#include "Core/public/Math/Vector4.hpp"
#ifndef MATRIX4_H
#define MATRIX4_H
namespace Phanes::Core::Math {
// 4x4 Matrix defined in column-major order.
template<RealType T, bool S>
struct TMatrix4
{
public:
union
{
struct
{
TVector4<T, S> c0;
TVector4<T, S> c1;
TVector4<T, S> c2;
TVector4<T, S> c3;
};
T data[4][4];
};
public:
/// <summary>
/// Default constructor.
/// </summary>
TMatrix4() = default;
/// <summary>
/// Move constructor
/// </summary>
/// <param name="v"></param>
TMatrix4(TMatrix4<T, S>&& m)
: c0(std::move(m.c0)), c1(std::move(m.c1)), c2(std::move(m.c2)), c3(std::move(m.c3))
{};
/// <summary>
/// Copy constructor
/// </summary>
/// <param name="v"></param>
TMatrix4(const TMatrix4<T, S>& m)
: c0(m.c0), c1(m.c1), c2(m.c2), c3(m.c3)
{};
/// <summary>
/// Construct matrix with values.
/// </summary>
TMatrix4(float n00, float n01, float n02, float n03,
float n10, float n11, float n12, float n13,
float n20, float n21, float n22, float n23,
float n30, float n31, float n32, float n33)
{
this->c0 = TVector4<T, S>(n00, n10, n20, n30);
this->c1 = TVector4<T, S>(n01, n11, n21, n31);
this->c2 = TVector4<T, S>(n02, n12, n22, n32);
this->c3 = TVector4<T, S>(n03, n13, n23, n33);
}
/// <summary>
/// Construct matrix from columns.
/// </summary>
TMatrix4(const TVector4<T, S>& v0, const TVector4<T, S>& v1, const TVector4<T, S>& v2, const TVector4<T, S>& v3)
{
this->c0 = v0;
this->c1 = v1;
this->c2 = v2;
this->c3 = v3;
}
/// <summary>
/// Construct matrix from field of values.
/// </summary>
/// <param name="field"></param>
TMatrix4(T field[4][4])
{
this->c0 = TVector4(field[0]);
this->c1 = TVector4(field[1]);
this->c2 = TVector4(field[2]);
this->c3 = TVector4(field[3]);
}
TMatrix4<T, S>& operator= (TMatrix4<T, S>&& m)
{
if (this != &m)
{
this->c0 = std::move(m.c0);
this->c1 = std::move(m.c1);
this->c2 = std::move(m.c2);
this->c3 = std::move(m.c3);
}
return *this;
}
TMatrix4<T, S>& operator= (const TMatrix4<T, S>& m)
{
if (this != &m)
{
this->c0 = m.c0;
this->c1 = m.c1;
this->c2 = m.c2;
this->c3 = m.c3;
}
return *this;
}
public:
FORCEINLINE T& operator() (int n, int m)
{
return this->data[m][n];
}
FORCEINLINE TVector4<T, S>& operator[] (int m)
{
return (*reinterpret_cast<TVector4<T, S>*>(this->m[m]));
}
FORCEINLINE const T& operator() (int n, int m) const
{
return this->data[m][n];
}
FORCEINLINE const TVector4<T, S>& operator[] (int m) const
{
return (*reinterpret_cast<const TVector4<T, S>*>(this->data[m]));
}
};
// ==================== //
// Matrix4 operator //
// ==================== //
template<RealType T, bool S>
TMatrix4<T, S>& operator+= (TMatrix4<T, S>& m1, T s)
{
m1.c0 += s;
m1.c1 += s;
m1.c2 += s;
m1.c3 += s;
return m1;
}
template<RealType T, bool S>
TMatrix4<T, S>& operator+= (TMatrix4<T, S>& m1, const TMatrix4<T, S>& m2)
{
m1.c0 += m2.c0;
m1.c1 += m2.c1;
m1.c2 += m2.c2;
m1.c3 += m2.c3;
return m1;
}
template<RealType T, bool S>
TMatrix4<T, S>& operator-= (TMatrix4<T, S>& m1, T s)
{
m1.c0 -= s;
m1.c1 -= s;
m1.c2 -= s;
m1.c3 -= s;
return m1;
}
template<RealType T, bool S>
TMatrix4<T, S>& operator-= (TMatrix4<T, S>& m1, const TMatrix4<T, S>& m2)
{
m1.c0 -= m2.c0;
m1.c1 -= m2.c1;
m1.c2 -= m2.c2;
m1.c3 -= m2.c3;
return m1;
}
template<RealType T, bool S>
TMatrix4<T, S>& operator*= (TMatrix4<T, S>& m1, T s)
{
m1.c0 *= s;
m1.c1 *= s;
m1.c2 *= s;
m1.c3 *= s;
return m1;
}
// Matrix multiplication
template<RealType T, bool S>
TMatrix4<T, S>& operator*= (TMatrix4<T, S>& m1, const TMatrix4<T, S>& m2);
template<RealType T, bool S>
TMatrix4<T, S>& operator/= (TMatrix4<T, S>& m1, T s)
{
s = (T)1.0 / s;
m1.c0 *= s;
m1.c1 *= s;
m1.c2 *= s;
m1.c3 *= s;
return m1;
}
template<RealType T, bool S>
TMatrix4<T, S> operator+ (const TMatrix4<T, S>& m1, T s)
{
return TMatrix4<T, S>(m1.c0 + s,
m1.c1 + s,
m1.c2 + s,
m1.c3 + s
);
}
template<RealType T, bool S>
TMatrix4<T, S> operator+ (const TMatrix4<T, S>& m1, const TMatrix4<T, S>& m2)
{
return TMatrix4<T, S>(m1.c0 + m2.c0,
m1.c1 + m2.c1,
m1.c2 + m2.c2,
m1.c3 + m2.c3
);
}
template<RealType T, bool S>
TMatrix4<T, S> operator- (const TMatrix4<T, S>& m1, T s)
{
return TMatrix4<T, S>(m1.c0 - s,
m1.c1 - s,
m1.c2 - s,
m1.c3 - s
);
}
template<RealType T, bool S>
TMatrix4<T, S> operator- (const TMatrix4<T, S>& m1, const TMatrix4<T, S>& m2)
{
return TMatrix4<T, S>(m1.c0 - m2.c0,
m1.c1 - m2.c1,
m1.c2 - m2.c2,
m1.c3 - m2.c3
);
}
template<RealType T, bool S>
TMatrix4<T, S> operator* (const TMatrix4<T, S>& m1, T s)
{
return TMatrix4<T, S>(m1.c0 * s,
m1.c1 * s,
m1.c2 * s,
m1.c3 * s
);
}
template<RealType T, bool S>
TMatrix4<T, S> operator* (const TMatrix4<T, S>& m1, const TMatrix4<T, S>& m2);
template<RealType T, bool S>
TMatrix4<T, S> operator/ (const TMatrix4<T, S>& m1, T s)
{
s = (T)1.0 / s;
return TMatrix4<T, S>(m1.c0 * s,
m1.c1 * s,
m1.c2 * s,
m1.c3 * s
);
}
template<RealType T, bool S>
TVector4<T, S> operator* (const TMatrix4<T, S>& m1, const TVector4<T, S>& v);
template<RealType T, bool S>
bool operator== (const TMatrix4<T, S>& m1, const TMatrix4<T, S>& m2)
{
return (m1.c0 == m2.c0 && m1.c1 == m2.c1 && m1.c2 == m2.c2 && m1.c3 == m2.c3);
}
template<RealType T, bool S>
bool operator!= (const TMatrix4<T, S>& m1, const TMatrix4<T, S>& m2)
{
return (m1.c0 != m2.c0 || m1.c1 != m2.c1 || m1.c2 != m2.c2 || m1.c3 != m2.c3);
}
// ================================ //
// Matrix4 function definition //
// ================================ //
template<RealType T, bool S>
T Determinant(const TMatrix4<T, S>& m);
template<RealType T, bool S>
bool InverseV(TMatrix4<T, S>& a);
template<RealType T, bool S>
TMatrix4<T, S>& TransposeV(TMatrix4<T, S>& a);
// =============== //
// WITH RETURN //
// =============== //
template<RealType T, bool S>
bool Inverse(const TMatrix4<T, S>& m, Ref<TMatrix4<T, S>> r);
template<RealType T, bool S>
TMatrix4<T, S> Transpose(const TMatrix4<T, S>& a);
template<RealType T, bool S>
FORCEINLINE bool IsIdentityMatrix(const TMatrix4<T, S>& m1)
{
return (abs(m1(0, 0) - (T)1.0) < P_FLT_INAC && abs(m1(0, 1)) < P_FLT_INAC && abs(m1(0, 2)) < P_FLT_INAC && abs(m1(0, 3)) < P_FLT_INAC &&
abs(m1(1, 0)) < P_FLT_INAC && abs(m1(1, 1) - (T)1.0) < P_FLT_INAC && abs(m1(1, 2)) < P_FLT_INAC && abs(m1(1, 3)) < P_FLT_INAC &&
abs(m1(2, 0)) < P_FLT_INAC && abs(m1(2, 1)) < P_FLT_INAC && abs(m1(2, 2) - (T)1.0) < P_FLT_INAC && abs(m1(2, 3)) < P_FLT_INAC &&
abs(m1(3, 0)) < P_FLT_INAC && abs(m1(3, 1)) < P_FLT_INAC && abs(m1(3, 2)) < P_FLT_INAC && abs(m1(3, 3) - (T)0.0) < P_FLT_INAC);
}
} // Phanes::Core::Math
#endif // !MATRIX4_H
#include "Core/public/Math/Matrix4.inl"

View File

@@ -0,0 +1,69 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/Detail/Matrix4Decl.inl"
#include "Core/public/Math/SIMD/SIMDIntrinsics.h"
#include "Core/public/Math/SIMD/PhanesSIMDTypes.h"
namespace Phanes::Core::Math
{
template<RealType T, bool S>
T Determinant(const TMatrix4<T, S>& m)
{
return Detail::compute_mat4_det<T, S>::map(m);
}
template<RealType T, bool S>
bool InverseV(TMatrix4<T, S>& a)
{
return Detail::compute_mat4_inv<T, S>::map(a, a);
}
template<RealType T, bool S>
TMatrix4<T, S>& TransposeV(TMatrix4<T, S>& a)
{
Detail::compute_mat4_transpose<T, S>::map(a, a);
return a;
}
template<RealType T, bool S>
bool Inverse(const TMatrix4<T, S>& m, Ref<TMatrix4<T, S>> r)
{
return Detail::compute_mat4_inv<T, S>::map(*r, m);
}
template<RealType T, bool S>
TMatrix4<T, S> Transpose(TMatrix4<T, S>& a)
{
TMatrix4<T, S> r;
Detail::compute_mat4_transpose<T, S>::map(r, a);
return r;
}
template<RealType T, bool S>
TMatrix4<T, S>& operator*= (TMatrix4<T, S>& m1, const TMatrix4<T, S>& m2)
{
TMatrix4<T, S> r;
Detail::compute_mat4_mul<T, S>::map(r, m1, m2);
return (m1 = r);
}
template<RealType T, bool S>
TMatrix4<T, S> operator* (const TMatrix4<T, S>& m1, const TMatrix4<T, S>& m2)
{
TMatrix4<T, S> r;
Detail::compute_mat4_mul<T, S>::map(r, m1, m2);
return r;
}
template<RealType T, bool S>
TVector4<T, S> operator* (const TMatrix4<T, S>& m1, const TVector4<T, S>& v)
{
TVector4<T, S> r;
Detail::compute_mat4_mul<T, S>::map(r, m1, v);
return r;
}
}

View File

@@ -0,0 +1,956 @@
#pragma once
// TODO: Transform
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathFwd.h"
#include "Core/public/Math/Line.hpp"
#include "Core/public/Math/Ray.hpp"
#include "Core/public/Math/Vector3.hpp"
namespace Phanes::Core::Math {
// Plane in 3D space, defined as: P: ax + by + cz = d;
template<RealType T, bool S>
struct TPlane
{
public:
using Real = T;
union
{
struct
{
union
{
struct
{
/** X Part of the normal. */
Real x;
/** Y Part of the normal. */
Real y;
/** Z Part of the normal. */
Real z;
};
TVector3<Real, S> normal;
};
/// <summary>
/// Scalar component of plane
/// </summary>
Real d;
};
/// <summary>
/// Vector containing all components of vector (x, y, z and d).
/// </summary>
TVector4<Real, S> comp;
};
public:
/**
* Default constructor.
*/
TPlane() = default;
/**
* Construct plane from normal and d
*
* @param(normal) Normal of plane
* @param(d) Scalar component
*
* @note Normal is NOT normalized, make sure to normalize [PARAM]normal, or use [FUNC]CreateFromVector. Otherwise unexpected results may occur using the plane.
*/
TPlane(const TVector3<Real, S>& normal, Real d);
/**
* Construct plane from normal and base point.
*
* @param(normal) Normal of plane
* @param(base) Base point
*/
TPlane(const TVector3<Real, S>& normal, const TVector3<Real, S>& base);
/**
* Construct plane from coefficients. The components should be normalized.
*
* @param(x) X coefficient
* @param(y) Y coefficient
* @param(z) Z coefficient
* @param(d) D coefficient
*/
TPlane(Real x, Real y, Real z, Real d);
/**
* Construct plane from 3 points
*
* @param(p1) Point one
* @param(p2) Point two
* @param(p3) Point three
*/
TPlane(const TVector3<Real, S>& p1, const TVector3<Real, S>& p2, const TVector3<Real, S>& p3);
};
// ======================== //
// Operators for TPlane //
// ======================== //
/**
* Adds pl2 to pl1.
*
* @param(pl1) Plane to add to
* @param(pl2) Plane to add
*
* @note This leads to the plane not being normalized anymore. Use PlaneNormalizeV to normalize again.
* @see [FUNC] PlaneNormalizeV
*/
template<RealType T, bool S>
TPlane<T, S> operator+= (TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
/**
* Substracts pl2 from pl1.
*
* @param(pl1) Plane to substract from
* @param(pl2) Plane to substract
*
* @note This leads to the plane not being normalized anymore. Use PlaneNormalizeV to normalize again.
* @see [FUNC] PlaneNormalizeV
*/
template<RealType T, bool S>
TPlane<T, S> operator-= (TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
/**
* Multiplies pl1 with pl2.
*
* @param(pl1) Plane to multiply
* @param(pl2) Plane to multiply with
*
* @note This leads to the plane not being normalized anymore. Use PlaneNormalizeV to normalize again.
* @see [FUNC] PlaneNormalizeV
*/
template<RealType T, bool S>
TPlane<T, S> operator*= (TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
/// <summary>
/// Divides pl1 by pl2
/// </summary>
/// <param name="pl1"></param>
/// <param name="pl2"></param>
/// <returns></returns>
template<RealType T, bool S>
TPlane<T, S> operator/= (TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
/// <summary>
/// Add scalar to plane
/// </summary>
/// <param name="pl1"></param>
/// <param name="s"></param>
/// <returns></returns>
template<RealType T, bool S>
TPlane<T, S> operator+= (TPlane<T, S>& pl1, T s);
/// <summary>
/// Substract scalar from plane
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="S"></typeparam>
/// <param name="pl1"></param>
/// <param name="s"></param>
/// <returns></returns>
template<RealType T, bool S>
TPlane<T, S> operator-= (TPlane<T, S>& pl1, T s);
/**
* Multiplies pl1 with a scalar
*
* @param(pl1) Plane to multiply
* @param(s) Scalar to multiply with
*/
template<RealType T, bool S>
TPlane<T, S> operator*= (TPlane<T, S>& pl1, T s);
/**
* Divides pl1 with a scalar
*
* @param(pl1) Plane to divide
* @param(s) Scalar to divide with
*/
template<RealType T, bool S>
TPlane<T, S> operator/= (TPlane<T, S>& pl1, T s);
/**
* Add two planes.
*
* @param(pl1) Plane
* @param(pl2) Plane
*
* @return Sum of planes
*/
template<RealType T, bool S>
TPlane<T, S> operator+ (const TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
/**
* Substracts two planes.
*
* @param(pl1) Plane
* @param(pl2) Plane
*
* @return Difference of the planes
*/
template<RealType T, bool S>
TPlane<T, S> operator- (const TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
/**
* Multiplies two planes.
*
* @param(pl1) Plane
* @param(pl2) Plane
*
* @return Product of planes
*/
template<RealType T, bool S>
TPlane<T, S> operator* (const TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
/// <summary>
/// Divides plane by plane
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="S"></typeparam>
/// <param name="pl1"></param>
/// <param name="pl2"></param>
/// <returns></returns>
template<RealType T, bool S>
TPlane<T, S> operator/ (const TPlane<T, S>& pl1, const TPlane<T, S>& pl2);
/// <summary>
/// Add scalar to plane
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="S"></typeparam>
/// <param name="pl1"></param>
/// <param name="s"></param>
/// <returns></returns>
template<RealType T, bool S>
TPlane<T, S> operator+ (const TPlane<T, S>& pl1, T s);
/// <summary>
/// Substracts scalar from plane
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="S"></typeparam>
/// <param name="pl1"></param>
/// <param name="s"></param>
/// <returns></returns>
template<RealType T, bool S>
TPlane<T, S> operator- (const TPlane<T, S>& pl1, T s);
/**
* Multiplies pl1 with a scalar
*
* @param(pl1) Plane to multiply
* @param(s) Scalar to multiply with
*
* @return Product of plane and scalar
*/
template<RealType T, bool S>
TPlane<T, S> operator* (const TPlane<T, S>& pl1, T s);
/**
* Divides pl1 with a scalar
*
* @param(pl1) Plane to divide
* @param(s) Scalar to divide with
*
* @return Quotient of plane and scalar
*/
template<RealType T, bool S>
TPlane<T, S> operator/ (const TPlane<T, S>& pl1, T s);
/**
* Tests two planes for equality
*
* @see [FUNC] Equals
*
* @param(pl1) Plane one
* @param(pl2) Plane two
*
* @return True, if planes are equal, false, if not.
*/
template<RealType T>
FORCEINLINE bool operator== (const TPlane<T, false>& pl1, const TPlane<T, false>& pl2)
{
return pl1.comp == pl2.comp;
}
/**
* Tests two planes for inequality
*
* @see [FUNC] Equals
*
* @param(pl1) Plane one
* @param(pl2) Plane two
*
* @return True, if planes are inequal, false, if not.
*/
template<RealType T>
FORCEINLINE bool operator!= (const TPlane<T, false>& pl1, const TPlane<T, false>& pl2)
{
return pl1.comp != pl2.comp;
}
// ======================= //
// Functions of TPlane //
// ======================= //
/**
* Tests whether two planes are perpendicular.
*
* @param(pl1) Plane one
* @param(pl2) Plane two
* @param(threshold) Allowed T inaccuracy
*
* @return True if perpendicular, false if not.
*/
template<RealType T>
inline bool IsPerpendicular(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2, T threshold = P_FLT_INAC)
{
return (Abs(DotP(pl1.normal, pl2.normal)) < threshold);
}
/**
* Tests whether two planes are parallel.
*
* @param(pl1) Plane one
* @param(pl2) Plane two
* @param(threshold) Allowed T inaccuracy from one (e.g. 0.98f)
*
* @return True if parallel, false if not.
*/
template<RealType T>
inline bool IsParallel(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2, T threshold = 1.0f - P_FLT_INAC)
{
return (Abs(DotP(pl1.normal, pl2.normal)) > threshold);
}
/**
* Tests whether two planes are coincident (Parallel and point in same direction).
*
* @param(pl1) Plane one
* @param(pl2) Plane two
* @param(threshold) Allowed T inaccuracy from one (e.g. 0.98f)
*
* @return True if coincident, false if not.
*/
template<RealType T>
inline bool IsCoincident(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2, T threshold = 1.0f - P_FLT_INAC)
{
return (DotP(pl1.normal, pl2.normal) > threshold);
}
/**
* Tests whether pl1 plane is a unit vector.
*
* @param(pl1) Plane
* @param(threshold) Allowed T inaccuracy
*
* @return True if unit vector, false if not.
*/
template<RealType T>
inline bool IsNormalized(const TPlane<T, false>& pl1, T threshold = P_FLT_INAC)
{
return (SqrMagnitude(pl1.normal) < threshold);
}
/**
* Tests whether two planes are the same
*
* @see [FUNC]Equals
*
* @param(pl1) Plane one
* @param(pl2) Plane two
* @param(threshold) Allowed T inaccuracy
*
* @return True if same, false if not.
* @note Planes must be normalized.
*/
template<RealType T>
inline bool IsSame(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2, T threshold = P_FLT_INAC)
{
return DotP(pl1.normal, pl2.normal) > threshold && abs(pl1.d - pl2.d) < P_FLT_INAC;
}
/**
* Normalizes plane.
*
* @param(pl1) Plane
*/
template<RealType T>
TPlane<T, false> PlaneNormalizeV(TPlane<T, false>& pl1)
{
T normVec = SqrMagnitude(pl1);
T scale = (normVec > P_FLT_INAC) ? (T)1.0 / sqrt(normVec) : 1.0f;
pl1.normal *= scale; pl1.d *= scale;
return pl1;
}
/**
* Normalizes plane.
*
* @param(pl1) Plane
*
* @return Normalized plane
*/
template<RealType T>
TPlane<T, false> PlaneNormalize(TPlane<T, false>& pl1)
{
T normVec = SqrMagnitude(pl1);
T scale = (normVec > P_FLT_INAC) ? (T)1.0 / sqrt(normVec) : 1.0f;
return TPlane<T, false>(pl1.normal * scale, pl1.d * scale);
}
/**
* Normalizes plane.
*
* @param(pl1) Plane
*
* @note Does not check for zero vector pl1.normal.
*/
template<RealType T>
TPlane<T, false> PlaneUnsafeNormalizeV(TPlane<T, false>& pl1)
{
T scale = (T)1.0 / Magnitude(pl1);
pl1.normal *= scale; pl1.d *= scale;
return pl1;
}
/**
* Normalizes plane.
*
* @param(pl1) Plane
*
* @return Normalized plane
*
* @note Does not check for zero vector pl1.normal.
*/
template<RealType T>
TPlane<T, false> PlaneUnsafeNormalize(TPlane<T, false>& pl1)
{
T scale = (T)1.0 / Magnitude(pl1);
return TPlane<T, false>(pl1.normal * scale, pl1.d * scale);
}
/**
* Get dot product between two planes
*
* @param(pl1) Plane one
* @param(pl2) Plane two
*/
template<RealType T>
FORCEINLINE T PlaneDotP(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2)
{
return DotP(pl1.normal, pl2.normal);
}
/**
* Get angle between two planes
*
* @param(pl1) Plane one
* @param(pl2) Plane two
*/
template<RealType T>
FORCEINLINE T PlaneAngle(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2)
{
return Angle(pl1.normal, pl2.normal);
}
/**
* Get cosine of angle between two planes
*
* @param(pl1) Plane one
* @param(pl2) Plane two
*/
template<RealType T>
FORCEINLINE T PlaneCosAngle(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2)
{
return CosineAngle(pl1.normal, pl2.normal);
}
/**
* Flip plane.
*
* @param(pl1) Plane
*/
template<RealType T>
TPlane<T, false> FlipV(const TPlane<T, false>& pl1)
{
pl1.normal = -pl1.normal;
pl1.d = -pl1.d;
}
/**
* Get flipped plane.
*
* @param(pl1) Plane
*
* @return Flipped plane
*/
template<RealType T>
TPlane<T, false> Flip(const TPlane<T, false>& pl1)
{
return TPlane<T, false>(-pl1.normal, -pl1.d);
}
/**
* Transform plane with Transform
*
* @param(pl) Plane
* @param(tr) Transform
*/
template<RealType T>
FORCEINLINE TPlane<T, false> TransformV(TPlane<T, false>& pl, const TTransform<T>& tr)
{
// TODO: Do with operator*
}
/**
* Transform plane with Transform
*
* @param(pl) Plane
* @param(tr) Transform
*
* @return Transformed plane.
*/
template<RealType T>
FORCEINLINE TPlane<T, false> Transform(const TPlane<T, false>& pl, const TTransform<T>& tr)
{
// TODO: Do with operator*
}
/**
* Calculates distance bewteen point and plane.
*
* @param(pl1) Plane
* @param(p1) Point
*
* @return Distance from point to plane
* @note Distance is 0 if point is on plane, >0 if it's in front and <0 if it's on the backside.
*/
template<RealType T>
T PointDistance(const TPlane<T, false>& pl1, const TVector3<T, false>& p1)
{
return (pl1.x * p1.x + pl1.y * p1.y + pl1.z * p1.z) - pl1.d;
}
/**
* Gets the origin point (base) of the plane
*
* @param(pl1) Plane
*
* @return Base of plane
*/
template<RealType T>
TVector3<T, false> GetOrigin(const TPlane<T, false>& pl1)
{
return TVector3<T, false>(pl1.normal * pl1.d);
}
/**
* Translates plane by vector
*
* @param(pl1) Plane
* @param(v1) Vector
*/
template<RealType T>
TPlane<T, false> TranslateV(TPlane<T, false>& pl1, const TVector3<T, false>& v1)
{
pl1.d = DotP(this->normal, GetOrigin(pl1) + v1);
return pl1;
}
/**
* Translates plane by vector
*
* @param(pl1) Plane
* @param(v1) Vector
*/
template<RealType T>
TPlane<T, false> Translate(TPlane<T, false>& pl1, const TVector3<T, false>& v1)
{
return TPlane<T, false>(pl1.normal, GetOrigin(pl1) + v1);
}
/**
* Returns the side a point is on.
*
* @param(pl1) Plane
* @param(p1) Point
*
* @return True, if it's in the front and false, if it's on the back.
*/
template<RealType T>
bool GetSide(const TPlane<T, false>& pl1, const TVector3<T, false>& p1)
{
return (pl1.d <= DotP(pl1.normal, p1));
}
/**
* Projects vector onto plane
*
* @param(v1) Vector to reject
* @param(plane) Plane
*
* @note result is stored in v1.
* @note Simply rejects v1 from normal
*/
template<RealType T>
FORCEINLINE TVector3<T, false> ProjectOntoPlaneV(TVector3<T, false>& v1, const TPlane<T, false>& plane)
{
return RejectV(v1, plane.normal);
}
/**
* Projects vector onto plane
*
* @param(v1) Vector to reject
* @param(normal) Normal of the plane
*
* @note result is stored in v1.
* @note Simply rejects v1 from normal
*/
template<RealType T>
FORCEINLINE TVector3<T, false> ProjectOntoPlaneV(TVector3<T, false>& v1, const TVector3<T, false>& normal)
{
return RejectV(v1, normal);
}
/**
* Reflect from plane
*
* @param(v1) Vector to mirror
* @param(plane) Plane to mirror on
*
* @note result is stored in v1.
*/
template<RealType T>
FORCEINLINE TVector3<T, false> ReflectFromPlaneV(TVector3<T, false>& v1, const TPlane<T, false>& plane)
{
return ReflectV(v1, plane.normal);
}
/**
* Reflect from plane
*
* @param(v1) Vector to mirror
* @param(normal) Normal of plane
*
* @note result is stored in v1.
*/
template<RealType T>
FORCEINLINE TVector3<T, false> ReflectFromPlaneV(TVector3<T, false>& v1, const TVector3<T, false>& normal)
{
return ReflectV(v1, normal);
}
/**
* Reflect from plane
*
* @param(v1) Vector to mirror
* @param(plane) Plane to mirror on
*
* @return Reflected vector
*/
template<RealType T>
FORCEINLINE TVector3<T, false> ReflectFromPlane(const TVector3<T, false>& v1, const TPlane<T, false>& plane)
{
return Reflect(v1, plane.normal);
}
/**
* Reflect from plane
*
* @param(v1) Vector to mirror
* @param(plane) Normal of plane
*
* @return Reflected vector
*/
template<RealType T>
FORCEINLINE TVector3<T, false> ReflectFromPlane(const TVector3<T, false>& v1, const TVector3<T, false>& normal)
{
return Reflect(v1, normal);
}
/**
* Projects vector onto plane
*
* @see [FUNC]PointProjectOntoPlane
*
* @param(v1) Vector to reject
* @param(normal) Normal of the plane
*
* @return Projected vector
* @note Simply rejects the vector from normal
*/
template<RealType T>
FORCEINLINE TVector3<T, false> ProjectOntoPlane(const TVector3<T, false>& v1, const TVector3<T, false>& normal)
{
return Reject(v1, normal);
}
/**
* Projects vector onto plane
*
* @see [FUNC]PointProjectOntoPlane
*
* @param(v1) Vector to reject
* @param(plane) Plane
*
* @return Projected vector
* @note Simply rejects the vector from normal
*/
template<RealType T>
FORCEINLINE TVector3<T, false> ProjectOntoPlane(const TVector3<T, false>& v1, const TPlane<T, false>& plane)
{
return Reject(v1, plane.normal);
}
/**
* Tests planes for equality
*
* @param(pl1) Plane one
* @param(pl2) Plane two
* @param(threshold) Allowed inaccuracy
*
* @return True, if equal, false if not.
*/
template<RealType T>
inline bool Equals(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2, T threshold = P_FLT_INAC)
{
return Equals(pl1.normal, pl2.normal, threshold) && abs(pl1.d - pl2.d) < threshold;
}
/** Tests whether a point is on a plane
*
* @param(pl1) Plane
* @param(p1) Point
*
* @return True, if p1 on pl1, false if not.
*/
template<RealType T>
FORCEINLINE bool IsPointOnPlane(const TPlane<T, false>& pl1, const TVector3<T, false>& p1)
{
return (Equals(DotP(pl1.normal, p1), p1.d));
}
/**
* Tests whether two planes intersect. Sets line to intersection-line if true.
*
* @param(pl1) Plane one
* @param(pl2) Plane two
* @param(interLine) Line of intersection
* @param(threshold) Threshold for parallel planes.
*
* @return True, if planes intersect, false, if not.
*/
template<RealType T>
bool PlanesIntersect2(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2, Ref<TLine<T>> interLine, T threshold = P_FLT_INAC)
{
TVector3<T, false> dirLine = CrossP(pl1.normal, pl2.normal);
T det = SqrMagnitude(dirLine);
if (abs(det) > P_FLT_INAC)
{
interLine = MakeRef<TLine<T>>(dirLine, (CrossP(dirLine, pl2.normal) * pl1.d + CrossP(dirLine, pl1.normal) * pl2.d) / det);
NormalizeV(interLine);
return true;
}
return false;
}
/**
* Tests whether three planes intersect. Sets line to intersection-line if true.
*
* @param(pl1) Plane one
* @param(pl2) Plane two
* @param(pl3) Plane three
* @param(interPoint) Point of intersection
* @param(threshold) Threshold for parallel planes.
*
* @return True, if all planes intersect, false, if not.
*/
template<RealType T>
bool PlanesIntersect3(const TPlane<T, false>& pl1, const TPlane<T, false>& pl2, const TPlane<T, false>& pl3, Ref<TVector3<T, false>> interPoint, T threshold = P_FLT_INAC)
{
T det = DotP(CrossP(pl1.normal, pl2.normal), pl3.normal);
if (abs(det) > P_FLT_INAC)
{
interPoint = MakeRef<TVector3<T, false>>((CrossP(pl3.normal, pl2.normal) * pl1.d + CrossP(pl1.normal, pl3.normal) * pl2.d) / det);
return true;
}
return false;
}
/**
* Mirrors a point through plane
*
* @param(p1) Point to mirror
* @param(pl1) Plane
*
* @return Mirrored point.
*/
template<RealType T>
TVector3<T, false> PlaneMirrorPoint(const TVector3<T, false>& p1, const TPlane<T, false>& pl1)
{
return p1 - pl1.normal * ((T)2.0 * PointDistance(pl1, p1));
}
/**
* Projects point onto plane
*
* @param(p1) Point to project
* @param(pl1) Plane
*
* @return Projected point.
*/
template<RealType T>
TVector3<T, false> PointProjectOntoPlane(const TVector3<T, false>& p1, const TPlane<T, false>& pl1)
{
return p1 - PointDistance(pl1, p1) * pl1.normal;
}
/**
* Calculates the intersection point, of a line with a plane, if there is one
*
* @param(pl1) Plane
* @param(l1) Line
* @param(p1) Point
*
* @return True, if they intersect, false if not.
*/
template<RealType T>
bool LineIntersect(const TPlane<T, false>& pl1, const TLine<T>& l1, Ref<TVector3<T, false>> p1)
{
T dotProduct = DotP(l1.normal, pl1.normal);
if (abs(dotProduct) > P_FLT_INAC)
{
p1 = MakeRef<TVector3<T, false>>(l1.base - l1.normal * (DotP(l1.normal * p1.base) / dotProduct));
return true;
}
return false;
}
/**
* Calculates, the intersection point, of a plane and a ray.
*
* @param(pl1) Plane
* @param(r1) Ray
* @param(p1) Intersection point
*
* @return True, if they intersect, false if not.
*/
template<RealType T>
bool RayIntersect(const TPlane<T, false>& pl1, const TRay<T, false>& r1, Ref<TVector3<T, false>> p1)
{
T pr = DotP(pl1.normal, Normalize(r1.direction));
T parameter = DotP((GetOrigin(pl1) - r1.origin), pl1.normal) / pr;
if (p1 > P_FLT_INAC && parameter >= 0)
{
p1 = MakeRef<TVector3<T, false>>(PointAt(r1, parameter));
return true;
}
return false;
}
} // Phanes::Core::Math
// Include operator impl.
#include "Core/public/Math/Plane.inl"

View File

@@ -0,0 +1,159 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/Detail/PlaneDecl.inl"
#include "Core/public/Math/SIMD/SIMDIntrinsics.h"
#include "Core/public/Math/SIMD/PhanesSIMDTypes.h"
namespace Phanes::Core::Math
{
template<RealType T, bool S>
TPlane<T, S>::TPlane(const TVector3<T, S>& normal, Real d)
{
Detail::construct_plane<T, S>::map(*this, normal, d);
}
template<RealType T, bool S>
TPlane<T, S>::TPlane(const TVector3<T, S>& normal, const TVector3<T, S>& base)
{
Detail::construct_plane<T, S>::map(*this, normal, base);
}
template<RealType T, bool S>
TPlane<T, S>::TPlane(Real x, Real y, Real z, Real d)
{
Detail::construct_plane<T, S>::map(*this, x, y, z, d);
}
template<RealType T, bool S>
TPlane<T, S>::TPlane(const TVector3<T, S>& p1, const TVector3<T, S>& p2, const TVector3<T, S>& p3)
{
Detail::construct_plane<T, S>::map(*this, p1, p2, p3);
}
template<RealType T, bool S>
TPlane<T, S> operator+=(TPlane<T, S>& pl1, const TPlane<T, S>& pl2)
{
Detail::compute_plane_add(pl1, pl1, pl2);
return pl1;
}
template<RealType T, bool S>
TPlane<T, S> operator+=(TPlane<T, S>& pl1, T s)
{
Detail::compute_plane_add(pl1, pl1, s);
return pl1;
}
template<RealType T, bool S>
TPlane<T, S> operator+(const TPlane<T, S>& pl1, const TPlane<T, S>& pl2)
{
TPlane<T, S> r;
Detail::compute_plane_add(r, pl1, pl2);
return r;
}
template<RealType T, bool S>
TPlane<T, S> operator+(const TPlane<T, S>& pl1, T s)
{
TPlane<T, S> r;
Detail::compute_plane_add(r, pl1, s);
return r;
}
template<RealType T, bool S>
TPlane<T, S> operator-=(TPlane<T, S>& pl1, const TPlane<T, S>& pl2)
{
Detail::compute_plane_sub(pl1, pl1, pl2);
return pl1;
}
template<RealType T, bool S>
TPlane<T, S> operator-=(TPlane<T, S>& pl1, T s)
{
Detail::compute_plane_sub(pl1, pl1, s);
return pl1;
}
template<RealType T, bool S>
TPlane<T, S> operator-(const TPlane<T, S>& pl1, const TPlane<T, S>& pl2)
{
TPlane<T, S> r;
Detail::compute_plane_sub(r, pl1, pl2);
return r;
}
template<RealType T, bool S>
TPlane<T, S> operator-(const TPlane<T, S>& pl1, T s)
{
TPlane<T, S> r;
Detail::compute_plane_sub(r, pl1, s);
return r;
}
template<RealType T, bool S>
TPlane<T, S> operator*=(TPlane<T, S>& pl1, const TPlane<T, S>& pl2)
{
Detail::compute_plane_mul(pl1, pl1, pl2);
return pl1;
}
template<RealType T, bool S>
TPlane<T, S> operator*=(TPlane<T, S>& pl1, T s)
{
Detail::compute_plane_mul(pl1, pl1, s);
return pl1;
}
template<RealType T, bool S>
TPlane<T, S> operator*(const TPlane<T, S>& pl1, const TPlane<T, S>& pl2)
{
TPlane<T, S> r;
Detail::compute_plane_mul(r, pl1, pl2);
return r;
}
template<RealType T, bool S>
TPlane<T, S> operator*(const TPlane<T, S>& pl1, T s)
{
TPlane<T, S> r;
Detail::compute_plane_mul(r, pl1, s);
return r;
}
template<RealType T, bool S>
TPlane<T, S> operator/=(TPlane<T, S>& pl1, const TPlane<T, S>& pl2)
{
Detail::compute_plane_div(pl1, pl1, pl2);
return pl1;
}
template<RealType T, bool S>
TPlane<T, S> operator/=(TPlane<T, S>& pl1, T s)
{
Detail::compute_plane_div(pl1, pl1, s);
return pl1;
}
template<RealType T, bool S>
TPlane<T, S> operator/(const TPlane<T, S>& pl1, const TPlane<T, S>& pl2)
{
TPlane<T, S> r;
Detail::compute_plane_sub(r, pl1, pl2);
return r;
}
template<RealType T, bool S>
TPlane<T, S> operator/(const TPlane<T, S>& pl1, T s)
{
TPlane<T, S> r;
Detail::compute_plane_sub(r, pl1, s);
return r;
}
}

View File

@@ -0,0 +1,112 @@
#pragma once
#include "PhanesEnginePCH.h"
// ============================================= //
// Turn os specific types into global types. //
// ============================================= //
// TODO: include int128
namespace Phanes::Core::Types
{
#ifdef P_WIN_BUILD
// MSCV++ specific types
typedef FLOAT128 float128;
//#elif P_UNIX_BUILD
//
// // GCC specific types
//
// typedef __float128 float128;
#endif
// Specific types size
//
// 8-Bit integer
typedef int8_t int8;
// 16-Bit integer
typedef int16_t int16;
// 32-Bit integer
typedef int32_t int32;
// 64-Bit integer
typedef int64_t int64;
// 8-Bit unsigned integer
typedef uint8_t uint8;
// 16-Bit unsigned integer
typedef uint16_t uint16;
// 32-Bit unsigned integer
typedef uint32_t uint32;
// 64-Bit unsigned integer
typedef uint64_t uint64;
// At least N bit types
//
// At least 8-Bit integer
typedef int_least8_t lint8;
// At least 16-Bit integer
typedef int_least16_t lint16;
// At least 32-Bit integer
typedef int_least32_t lint32;
// At least 64-Bit integer
typedef int_least64_t lint64;
// At least 8-Bit integer
typedef uint_least8_t ulint8;
// At least 16-Bit integer
typedef uint_least16_t ulint16;
// At least 32-Bit integer
typedef uint_least32_t ulint32;
// At least 64-Bit integer
typedef uint_least64_t ulint64;
// Fast N bit types
//
// Fast 8-bit integer
typedef int_fast8_t fint8;
// At least 16-Bit integer
typedef int_fast16_t fint16;
// At least 32-Bit integer
typedef int_fast32_t fint32;
// At least 64-Bit integer
typedef int_fast64_t fint64;
// At least 8-Bit integer
typedef uint_fast8_t ufint8;
// At least 16-Bit integer
typedef uint_fast16_t ufint16;
// At least 32-Bit integer
typedef uint_fast32_t ufint32;
// At least 64-Bit integer
typedef uint_fast64_t ufint64;
}

View File

@@ -0,0 +1,193 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathCommon.hpp"
#include "Core/public/Math/MathAbstractTypes.h"
#include "Core/public/Math/MathFwd.h"
#include "Core/public/Math/Vector2.hpp"
#include "Core/public/Math/Vector3.hpp"
#ifndef P_DEBUG
#pragma warning(disable : 4244)
#endif
/**
* The Point is the same as a vector. The type exists, to ensure
* differentiation between the two types.
*/
#ifndef POINT_H
#define POINT_H
namespace Phanes::Core::Math {
/**
* A 2D Point with components x and y with float precision.
*/
template<RealType T>
struct TPoint2 : public TVector2<T, false> {
using TVector2<T, false>::TVector2;
using Real = T;
/**
* Creates Point2 from Point3's xy
*
* @param a Point3 one
*/
TPoint2(const TPoint3<T>& p)
{
this->x = p.x;
this->y = p.y;
}
/**
* Creates Point2 from Point4's xy
*
* @param a Point4 one
*/
TPoint2(const TPoint4<T>& p)
{
this->x = p.x;
this->y = p.y;
}
};
/**
* Calculates distance between two points.
*
* @param(p1) Point one
* @param(p2) Point two
*
* @return Distance between two points.
*/
template<RealType T>
T Distance(const TPoint2<T>& p1, const TPoint2<T>& p2)
{
return Magnitude(p2 - p1);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* A 3D Point with components x and y with float precision.
*/
template<RealType T>
struct TPoint3 : public TVector3<T, false> {
using TVector3<T, false>::TVector3;
using Real = T;
/**
* Creates Point3 from Point2's xy and zero
*
* @param a Point2 one
*/
TPoint3(const TPoint2<T>& p)
{
this->x = p.x;
this->y = p.y;
this->z = 0;
}
/**
* Creates Point3 from Point4's xyz
*
* @param a Point4 one
*/
TPoint3(const TPoint4<T>& p)
{
this->x = p.x;
this->y = p.y;
this->z = p.z;
}
};
/**
* Calculates distance between two points.
*
* @param(p1) Point one
* @param(p2) Point two
*
* @return Distance between two points.
*/
template<RealType T>
T Distance(const TPoint3<T>& p1, const TPoint3<T>& p2)
{
return Magnitude(p2 - p1);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* A 4D Point with components x and y with float precision.
*/
template<RealType T>
struct TPoint4 : public TVector4<T, false> {
using TVector4<T, false>::TVector4;
/**
* Creates Point4 from Point2's xy and the last two zero
*
* @param a Point2 one
*/
TPoint4(const TPoint2<T>& p)
{
this->x = p.x;
this->y = p.y;
this->z = 0;
this->w = 0;
}
/**
* Creates Point4 from Point3's xyz and zero
*
* @param a Point3 one
*/
TPoint4(const TPoint3<T>& p)
{
this->x = p.x;
this->y = p.y;
this->z = p.z;
this->w = 0;
}
};
/**
* Calculates distance between two points.
*
* @param(p1) Point one
* @param(p2) Point two
*
* @return Distance between two points.
*/
template<RealType T>
T Distance(const TPoint4<T>& p1, const TPoint4<T>& p2)
{
return Magnitude(p2 - p1);
}
} // phanes::core::math::coretypes
#endif // !POINT_H

View File

@@ -0,0 +1,13 @@
# PhanesCore
## Math
### Description
Math lib.
Math is designed, to be completly independent from the rest of Phanes.
### Notes
- Normals are called normals for a reason.

View File

@@ -0,0 +1,127 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathFwd.h"
#include "Core/public/Math/Vector3.hpp"
namespace Phanes::Core::Math
{
// Ray with origin and direction (L = p + t * v)
template<RealType T, bool S>
struct TRay
{
public:
using Real = T;
TVector3<Real, S> origin;
TVector3<Real, S> direction;
public:
/** Default constructor */
TRay() = default;
/** Copy constructor */
TRay(const TRay<Real, S>& r) : direction(r.direction), origin(r.origin) {};
/** Move constructor */
TRay(TRay<Real, S>&& r) : direction(std::move(r.direction)), origin(std::move(r.origin)) {};
/**
* Construct ray from origin and direction.
*
* @param(direction) Direction
* @param(origin) Origin
*/
TRay(const TVector3<Real, S>& direction, const TVector3<Real, S>& origin) : direction(direction), origin(origin) {};
};
// ================== //
// TRay operators //
// ================== //
/**
* Tests two rays for equality
*
* @param(r1) Ray one
* @param(r2) Ray two
*
* @return True, if same and false, if not.
*/
template<RealType T>
FORCEINLINE bool operator== (const TRay<T, false>& r1, const TRay<T, false>& r2)
{
return (r1.origin == r2.origin && r1.direction == r2.direction);
}
/**
* Tests two rays for inequality
*
* @param(r1) Ray one
* @param(r2) Ray two
*
* @return True, if not same and false, if same.
*/
template<RealType T>
FORCEINLINE bool operator!= (const TRay<T, false>& r1, const TRay<T, false>& r2)
{
return (r1.origin != r2.origin || r1.direction != r2.direction);
}
// ================== //
// TRay functions //
// ================== //
/**
* Gets the point of the ray at a given parameter
*
* @param(r1) Ray
* @param(t) Parameter
*
* @return Point at t
*/
template<RealType T, bool S>
TVector3<T, S> PointAt(const TRay<T, S>& r1, T t)
{
return r1.origin + r1.direction * t;
}
/**
* Gets parameter necessary to travel to query point on line.
*
* @param(r1) Ray
* @param(p1) Query point
*
* @return parameter t
*/
template<RealType T, bool S>
TVector3<T, S> GetParameter(const TRay<T, S>& r1, const TVector3<T, S>& p1)
{
return DotP((p1 - r1.origin), r1.direction);
}
/**
* Tests wether two ray point in the same direction (Not if origin).
*
* @param(r1) Ray one
* @param(r2) Ray two
*
* @return True, if both rays point in the same direction, false if not.
*/
template<RealType T, bool S>
inline bool SameDirection(const TRay<T, S>& r1, const TRay<T, S>& r2)
{
return (r1.direction == r1.direction);
}
}

View File

@@ -0,0 +1,30 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
namespace Phanes::Core::Math::SIMD
{
// Structure to conveniently align arrays.
template<typename T, size_t L>
struct alignas(sizeof(T) * 4) AlignedVec
{
public:
T data[L];
AlignedVec(const T* n_aligned_data)
{
for (size_t i = 0; i < L; ++i)
{
data[i] = n_aligned_data[i];
}
}
const T* Get()
{
return data;
}
};
}

View File

@@ -0,0 +1,228 @@
#pragma once
// This file includes the necessary header for vectorization intrinsics. If no specifics are defined SSE4.2 is used.
//
// ARM is not supported.
#include "Core/public/Math/SIMD/Platform.h"
#include "Core/public/Math/MathTypes.h"
#if P_INTRINSICS == P_INTRINSICS_AVX2
# include <immintrin.h>
#elif P_INTRINSICS == P_INTRINSICS_AVX
# include <immintrin.h>
#elif P_INTRINSICS == P_INTRINSICS_SSE
# include <nmmintrin.h>
#elif P_INTRINSICS == P_INTRINSICS_NEON
# include "neon.h" // <- Not supported
#endif
// use_simd for metaprogramming
namespace Phanes::Core::Math::SIMD
{
/// <summary>
/// This decides, whether simd operations should be used, based on the vector type, it's size, the vector alignment and whether the right extension can be loaded during compiletime.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="L">Length of vector</typeparam>
/// <typeparam name="IsAligned">Whether the vector is aligned for simd usage.</typeparam>
template<typename T, size_t L, bool IsAligned>
struct use_simd
{
static const bool value = false;
};
// SSE / NEON
template<>
struct use_simd<float, 4, true>
{
static const bool value = true && (P_SSE__ || P_NEON__);
};
template<>
struct use_simd<float, 3, true>
{
static const bool value = true && (P_SSE__ || P_NEON__);
};
template<>
struct use_simd<int, 4, true>
{
static const bool value = true && (P_SSE__ || P_NEON__);
};
template<>
struct use_simd<int, 3, true>
{
static const bool value = true && (P_SSE__ || P_NEON__);
};
template<>
struct use_simd<unsigned int, 4, true>
{
static const bool value = true && (P_SSE__ || P_NEON__);
};
template<>
struct use_simd<unsigned int, 3, true>
{
static const bool value = true && (P_SSE__ || P_NEON__);
};
// SSE
template<>
struct use_simd<double, 2, true>
{
static const bool value = true && P_SSE__;
};
template<>
struct use_simd<Phanes::Core::Types::int64, 2, true>
{
static const bool value = true && P_SSE__;
};
template<>
struct use_simd<Phanes::Core::Types::uint64, 2, true>
{
static const bool value = true && P_SSE__;
};
// AVX
template<>
struct use_simd<double, 4, true>
{
static const bool value = true && P_AVX__;
};
template<>
struct use_simd<double, 3, true>
{
static const bool value = true && P_AVX__;
};
template<>
struct use_simd<float, 8, true>
{
static const bool value = true && P_AVX__;
};
// AVX2
template<>
struct use_simd<Phanes::Core::Types::int64, 4, true>
{
static const bool value = true && P_AVX2__;
};
template<>
struct use_simd<Phanes::Core::Types::int64, 3, true>
{
static const bool value = true && P_AVX2__;
};
template<>
struct use_simd<Phanes::Core::Types::uint64, 4, true>
{
static const bool value = true && P_AVX2__;
};
template<>
struct use_simd<Phanes::Core::Types::uint64, 3, true>
{
static const bool value = true && P_AVX2__;
};
template<>
struct use_simd<int, 8, true>
{
static const bool value = true && P_AVX2__;
};
template<>
struct use_simd<unsigned int, 8, true>
{
static const bool value = true && P_AVX2__;
};
}
// Register aliases
namespace Phanes::Core::Types
{
#if P_INTRINSICS >= 1
typedef __m128 Vec4f32Reg;
typedef __m128d Vec2f64Reg;
typedef __m128i Vec4i32Reg;
typedef __m128i Vec2i64Reg;
typedef __m128i Vec4u32Reg;
typedef __m128i Vec2u64Reg;
#elif P_INTRINSICS != P_INTRINSICS_NEON
typedef struct alignas(16) Vec4f32Reg { float data[4]; } Vec4f32Reg;
typedef struct alignas(16) Vec2f64Reg { double data[2]; } Vec2f64Reg;
typedef struct alignas(16) Vec4i32Reg { int data[4]; } Vec4i32Reg;
typedef struct alignas(16) Vec2i64Reg { Phanes::Core::Types::int64 data[2]; } Vec2i64Reg;
typedef struct alignas(16) Vec4u32Reg { unsigned int data[4]; } Vec4u32Reg;
typedef struct alignas(16) Vec2u64Reg { Phanes::Core::Types::uint64 data[4]; } Vec2u64Reg;
#endif
#if P_INTRINSICS >= 2
typedef __m256 Vec4x2f32Reg;
typedef __m256 Vec8f32Reg;
typedef __m256d Vec2x2f64Reg;
typedef __m256d Vec4f64Reg;
#elif P_INTRINSICS != P_INTRINSICS_NEON
typedef struct alignas(32) Vec4x2f32Reg { float data[8]; } Vec4x2f32Reg;
typedef struct alignas(32) Vec8f32Reg { float data[8]; } Vec8f32Reg;
typedef struct alignas(32) Vec2x2f64Reg { double data[4]; } Vec2x2f64Reg;
typedef struct alignas(32) Vec4f64Reg { double data[4]; } Vec4f64Reg;
#endif
#if P_INTRINSICS == 3
typedef __m256i Vec4x2i32Reg;
typedef __m256i Vec8i32Reg;
typedef __m256i Vec2x2i64Reg;
typedef __m256i Vec4i64Reg;
typedef __m256i Vec4x2u32Reg;
typedef __m256i Vec8u32Reg;
typedef __m256i Vec2x2u64Reg;
typedef __m256i Vec4u64Reg;
#elif P_INTRINSICS != P_INTRINSICS_NEON
typedef struct alignas(32) Vec4x2i32Reg { int data[8]; } Vec4x2i32Reg;
typedef struct alignas(32) Vec8i32Reg { int data[8]; } Vec8i32Reg;
typedef struct alignas(32) Vec2x2i64Reg { Phanes::Core::Types::int64 data[4]; } Vec2x2i64Reg;
typedef struct alignas(32) Vec4i64Reg { Phanes::Core::Types::int64 data[4]; } Vec4i64Reg;
typedef struct alignas(32) Vec4x2u32Reg { unsigned int data[8]; } Vec4x2u32Reg;
typedef struct alignas(32) Vec8u32Reg { unsigned int data[8]; } Vec8u32Reg;
typedef struct alignas(32) Vec2x2u64Reg { Phanes::Core::Types::uint64 data[4]; } Vec2x2u64Reg;
typedef struct alignas(32) Vec4u64Reg { Phanes::Core::Types::uint64 data[4]; } Vec4u64Reg;
#endif
// NEON ...
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include "PhanesVectorMathSSE.hpp" // Include previous
#include <immintrin.h>

View File

@@ -0,0 +1,3 @@
#pragma once
#include "PhanesVectorMathAVX.hpp" // Include previous

View File

@@ -0,0 +1,74 @@
#pragma once
#include "Core/public/Math/SIMD/PhanesSIMDTypes.h"
#include "Core/public/Math/MathCommon.hpp"
namespace Phanes::Core::Math::SIMD
{
/// <summary>
/// Adds all scalars of the vector.
/// </summary>
/// <param name="v">Vector</param>
/// <returns>Sum stored in v[0:31].</returns>
Phanes::Core::Types::Vec4f32Reg vec4_hadd(const Phanes::Core::Types::Vec4f32Reg v)
{
Phanes::Core::Types::Vec4f32Reg r;
r.data[0] = v.data[0] + v.data[1] + v.data[2] + v.data[3];
}
/// <summary>
/// Adds all scalars of the vector.
/// </summary>
/// <param name="v">Vector</param>
/// <returns>Sum of components.</returns>
float vec4_hadd_cvtf32(const Phanes::Core::Types::Vec4f32Reg v)
{
return v.data[0] + v.data[1] + v.data[2] + v.data[3];
}
/// <summary>
/// Gets the absolute value of each scalar in the vector.
/// </summary>
/// <param name="v">Vector</param>
/// <returns>Vector with all components positive.</returns>
Phanes::Core::Types::Vec4f32Reg vec4_abs(const Phanes::Core::Types::Vec4f32Reg v)
{
Phanes::Core::Types::Vec4f32Reg r;
r.data[0] = Abs(v.data[0]);
}
/// <summary>
/// Gets the dot product of the
/// </summary>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
Phanes::Core::Types::Vec4f32Reg vec4_dot(const Phanes::Core::Types::Vec4f32Reg v1, const Phanes::Core::Types::Vec4f32Reg v2)
{
Phanes::Core::Types::Vec4f32Reg r;
r.data[0] = v1.data[0] * v1.data[0] + v1.data[1] * v2.data[1] + v1.data[2] * v2.data[2] + v1.data[3] * v2.data[3];
return r;
}
/// <summary>
/// Gets the dot product of the
/// </summary>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
float vec4_dot_cvtf32(const Phanes::Core::Types::Vec4f32Reg v1, const Phanes::Core::Types::Vec4f32Reg v2)
{
return v1.data[0] * v1.data[0] + v1.data[1] * v2.data[1] + v1.data[2] * v2.data[2] + v1.data[3] * v2.data[3];
}
Phanes::Core::Types::Vec2f64Reg vec2_eq(const Phanes::Core::Types::Vec2f64Reg v1, const Phanes::Core::Types::Vec2f64Reg v2)
{
Phanes::Core::Types::Vec4f64Reg r;
r.data[0] = (Phanes::Core::Math::Abs(v1.data[0] - v2.data[0]) < P_FLT_INAC) ? 0xFFFFFFFF : 0;
r.data[1] = (Phanes::Core::Math::Abs(v1.data[1] - v2.data[1]) < P_FLT_INAC) ? 0xFFFFFFFF : 0;
}
}

View File

@@ -0,0 +1,2 @@
#pragma once
#error ARM architecture is not yet supported by PhanesEngine.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,330 @@
// Platform / Compiler detection.
#pragma once
// Architecture MACRO
// Implicitly asumes x86 architecture
#ifndef P_ARM_ARCH
# define P_x86_ARCH
#else
# ifdef P_x86_ARCH
# undef P_x86_ARCH
# endif
# error ARM architecture not supported.
#endif
// Set platform MACRO depending on defined build
#define P_PLATFORM_WIN 0
#define P_PLATFORM_LIN 1
#define P_PLATFORM_MAC 2
// #define P_PLATFORM_FBSD 3 -> Is planed for eventual PS5 support
// User defines build platform
#ifdef P_WIN_BUILD
# define P_PLATFORM P_PLATFORM_WIN
#elif P_LINUX_BUILD
# define P_PLATFORM P_PLATFORM_LIN
# error Linux / Unix system is not yet supported.
#elif P_MAC_BUILD
# define P_PLATFORM P_PLATFORM_MAC
# error Mac target system is not yet supported.
#elif P_PS5_BUILD || P_FBSD_BUILD
# define P_PLATFORM P_PLATFORM_FBSD
# error FreeBSD is not yet supported.
#else
# error Your target system is either not supported, or you have yet to define it.
#endif
// Set compiler depending on defined compiler
// Compiler macro definition
// ID's defined like [0-9][0-x]
// First bracket defines compiler, second defines the version of the compiler.
// Visual C++
#define P_COMPILER_VC22 001
#define P_COMPILER_VC19 002
#define P_COMPILER_VC17 003
#define P_COMPILER_VC15 004
#define P_COMPILER_VC13 005
#define P_COMPILER_VC12 006
#define P_COMPILER_VC10 007
#define P_COMPILER_VC08 008
#define P_COMPILER_VC05 009
#define P_COMPILER_VC03 010
#define P_COMPILER_VC02 011
#define P_COMPILER_VCSP 012
// Clang
#define P_COMPILER_CLANG34 101
#define P_COMPILER_CLANG35 102
#define P_COMPILER_CLANG36 103
#define P_COMPILER_CLANG37 104
#define P_COMPILER_CLANG38 105
#define P_COMPILER_CLANG39 106
#define P_COMPILER_CLANG4 107
#define P_COMPILER_CLANG5 108
#define P_COMPILER_CLANG6 109
#define P_COMPILER_CLANG7 110
#define P_COMPILER_CLANG8 111
#define P_COMPILER_CLANG9 112
#define P_COMPILER_CLANG10 113
#define P_COMPILER_CLANG11 114
#define P_COMPILER_CLANG12 115
#define P_COMPILER_CLANG13 116
#define P_COMPILER_CLANG14 117
#define P_COMPILER_CLANG15 118
#define P_COMPILER_CLANG16 119
#define P_COMPILER_CLANG17 120
#define P_COMPILER_CLANG18 121
#define P_COMPILER_CLANG19 122
// G++
#define P_COMPILER_GCC46 201
#define P_COMPILER_GCC47 202
#define P_COMPILER_GCC48 203
#define P_COMPILER_GCC49 204
#define P_COMPILER_GCC5 205
#define P_COMPILER_GCC6 206
#define P_COMPILER_GCC61 207
#define P_COMPILER_GCC7 208
#define P_COMPILER_GCC8 209
#define P_COMPILER_GCC9 210
#define P_COMPILER_GCC10 211
#define P_COMPILER_GCC11 212
#define P_COMPILER_GCC12 213
#define P_COMPILER_GCC13 214
#define P_COMPILER_GCC14 215
// Intel C++
#define P_COMPILER_INTEL14 301
#define P_COMPILER_INTEL15 302
#define P_COMPILER_INTEL16 303
#define P_COMPILER_INTEL17 304
#define P_COMPILER_INTEL18 305
#define P_COMPILER_INTEL19 306
#define P_COMPILER_INTEL21 307
// Visual studio
#ifdef _MSC_VER
# if _MSC_VER >= 1930
# define P_COMPILER P_COMPILER_VC22
# elif _MSC_VER >= 1920
# define P_COMPILER P_COMPILER_VC19
# elif _MSC_VER >= 1910
# define P_COMPILER P_COMPILER_VC17
# elif _MSC_VER >= 1900
# define P_COMPILER P_COMPILER_VC15
# elif _MSC_VER >= 1800
# define P_COMPILER P_COMPILER_VC13
# elif _MSC_VER >= 1700
# define P_COMPILER P_COMPILER_VC12
# elif _MSC_VER >= 1600
# define P_COMPILER P_COMPILER_VC10
# elif _MSC_VER >= 1500
# define P_COMPILER P_COMPILER_VC08
# elif _MSC_VER >= 1400
# define P_COMPILER P_COMPILER_VC05
# elif _MSC_VER >= 1310
# define P_COMPILER P_COMPILER_VC03
# elif _MSC_VER >= 1300
# define P_COMPILER P_COMPILER_VC02
# elif _MSC_VER >= 1200
# define P_COMPILER P_COMPILER_VCSP
# endif
// Clang
#elif (defined(__clang__))
# error PhanesEngine only supports MSVC -> Visual Studio
# if defined(__apple_build_version__)
#
# if (__clang_major__ < 6)
# error "GLM requires Clang 3.4 / Apple Clang 6.0 or higher"
# elif __clang_major__ == 6 && __clang_minor__ == 0
# define P_COMPILER P_COMPILER_CLANG35
# elif __clang_major__ == 6 && __clang_minor__ >= 1
# define P_COMPILER P_COMPILER_CLANG36
# elif __clang_major__ >= 7
# define P_COMPILER P_COMPILER_CLANG37
# endif
# else
# if ((__clang_major__ == 3) && (__clang_minor__ < 4)) || (__clang_major__ < 3)
# error "GLM requires Clang 3.4 or higher"
# elif __clang_major__ == 3 && __clang_minor__ == 4
# define P_COMPILER P_COMPILER_CLANG34
# elif __clang_major__ == 3 && __clang_minor__ == 5
# define P_COMPILER P_COMPILER_CLANG35
# elif __clang_major__ == 3 && __clang_minor__ == 6
# define P_COMPILER P_COMPILER_CLANG36
# elif __clang_major__ == 3 && __clang_minor__ == 7
# define P_COMPILER P_COMPILER_CLANG37
# elif __clang_major__ == 3 && __clang_minor__ == 8
# define P_COMPILER P_COMPILER_CLANG38
# elif __clang_major__ == 3 && __clang_minor__ >= 9
# define P_COMPILER P_COMPILER_CLANG39
# elif __clang_major__ == 4 && __clang_minor__ == 0
# define P_COMPILER P_COMPILER_CLANG4
# elif __clang_major__ == 5
# define P_COMPILER P_COMPILER_CLANG5
# elif __clang_major__ == 6
# define P_COMPILER P_COMPILER_CLANG6
# elif __clang_major__ == 7
# define P_COMPILER P_COMPILER_CLANG7
# elif __clang_major__ == 8
# define P_COMPILER P_COMPILER_CLANG8
# elif __clang_major__ == 9
# define P_COMPILER P_COMPILER_CLANG9
# elif __clang_major__ == 10
# define P_COMPILER P_COMPILER_CLANG10
# elif __clang_major__ == 11
# define P_COMPILER P_COMPILER_CLANG11
# elif __clang_major__ == 12
# define P_COMPILER P_COMPILER_CLANG12
# elif __clang_major__ == 13
# define P_COMPILER P_COMPILER_CLANG13
# elif __clang_major__ == 14
# define P_COMPILER P_COMPILER_CLANG14
# elif __clang_major__ == 15
# define P_COMPILER P_COMPILER_CLANG15
# elif __clang_major__ == 16
# define P_COMPILER P_COMPILER_CLANG16
# elif __clang_major__ == 17
# define P_COMPILER P_COMPILER_CLANG17
# elif __clang_major__ == 18
# define P_COMPILER P_COMPILER_CLANG18
# elif __clang_major__ >= 19
# define P_COMPILER P_COMPILER_CLANG19
# endif
# endif
// G++
#elif defined(__GNUC__) || defined(__MINGW32__)
# error PhanesEngine only supports MSVC -> Visual Studio
# if __GNUC__ >= 14
# define P_COMPILER P_COMPILER_GCC14
# elif __GNUC__ >= 13
# define P_COMPILER P_COMPILER_GCC13
# elif __GNUC__ >= 12
# define P_COMPILER P_COMPILER_GCC12
# elif __GNUC__ >= 11
# define P_COMPILER P_COMPILER_GCC11
# elif __GNUC__ >= 10
# define P_COMPILER P_COMPILER_GCC10
# elif __GNUC__ >= 9
# define P_COMPILER P_COMPILER_GCC9
# elif __GNUC__ >= 8
# define P_COMPILER P_COMPILER_GCC8
# elif __GNUC__ >= 7
# define P_COMPILER P_COMPILER_GCC7
# elif __GNUC__ >= 6
# define P_COMPILER P_COMPILER_GCC6
# elif __GNUC__ >= 5
# define P_COMPILER P_COMPILER_GCC5
# elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9
# define P_COMPILER P_COMPILER_GCC49
# elif __GNUC__ == 4 && __GNUC_MINOR__ >= 8
# define P_COMPILER P_COMPILER_GCC48
# elif __GNUC__ == 4 && __GNUC_MINOR__ >= 7
# define P_COMPILER P_COMPILER_GCC47
# elif __GNUC__ == 4 && __GNUC_MINOR__ >= 6
# define P_COMPILER P_COMPILER_GCC46
# elif ((__GNUC__ == 4) && (__GNUC_MINOR__ < 6)) || (__GNUC__ < 4)
# error PhanesEngine does not support your compiler.
# endif
#elif defined(__CUDACC__)
# error CUDA C++ is not supported by PhanesEngine
#endif
// Vector instruction sets
// Define also supported instruction sets for Visual Studio, as it only defines the latest (e.g. only __AVX__ not __SSE4__ ...).
#ifdef P_FORCE_INTRINSICS
# undef __AVX2__
# undef __AVX__
# undef __SSE__
# ifndef P_INTRINSICS
# error P_INTRINSICS must be defined by the user, when P_FORCE_INTRINSICS is used.
# endif
#elif !defined(P_FORCE_FPU)
# ifdef __AVX2__
# define P_AVX2__ 1
# elif defined(__AVX__)
# define P_AVX__ 1
# elif defined(__SSE__)
# define P_SSE__ 1
# endif
#endif // !P_FORCE_INTRINSICS
#ifdef P_AVX2__
# define P_AVX__ 1
#endif
#ifdef P_AVX__
# define P_SSE__ 1
#endif
// Deactivate unset SIMD
#ifndef P_AVX2__
# define P_AVX2__ 0
#endif
// Deactivate unset SIMD
#ifndef P_AVX__
# define P_AVX__ 0
#endif
#ifndef P_SSE__
# define P_SSE__ 0
#endif
#ifndef P_NEON__
# define P_NEON__ 0
#endif
#define P_INTRINSICS_FPU 0
#define P_INTRINSICS_SSE 1
#define P_INTRINSICS_AVX 2
#define P_INTRINSICS_AVX2 3
#define P_INTRINSICS_NEON 4
#if defined(P_FORCE_FPU) // Force, that no intrinsics may be used.
# define P_INTRINSICS P_INTRINSICS_FPU
# define P_AVX2__ 0
# define P_AVX__ 0
# define P_SSE__ 0
# define P_SSE__ 0
#else
# if (P_AVX__ == 1) && (P_AVX2__ == 0)
# define P_INTRINSICS P_INTRINSICS_AVX
# elif P_AVX2__ == 1
# define P_INTRINSICS P_INTRINSICS_AVX2
# elif P_SSE__ == 1
# define P_INTRINSICS P_INTRINSICS_SSE
# elif defined(P_ARM_ARCH)
# define P_INTRINSICS P_INTRINSICS_NEON
# define P_NEON__ 1
# elif !defined(P_FORCE_INTRINSICS)
# error No SIMD instruction set detected. Use P_FORCE_FPU to disable SIMD extensions.
# endif
#endif

View File

@@ -0,0 +1,15 @@
#pragma once
#include "Core/public/Math/SIMD/Platform.h"
#if P_INTRINSICS == P_INTRINSICS_AVX2
# include "PhanesVectorMathAVX2.hpp"
#elif P_INTRINSICS == P_INTRINSICS_AVX
# include "PhanesVectorMathAVX.hpp"
#elif P_INTRINSICS == P_INTRINSICS_SSE
# include "PhanesVectorMathSSE.hpp"
#elif P_INTRINSICS == P_INTRINSICS_NEON
# include "PhanesVectorMathNeon.hpp"
#endif

View File

@@ -0,0 +1,140 @@
// Defines on compile time, whether a xmm register or an array should be used.
#pragma once
#include "Core/public/Math/SIMD/PhanesSIMDTypes.h"
#include "Core/public/Math/MathTypes.h"
namespace Phanes::Core::Math::SIMD
{
template<size_t L, typename T, bool UseSimd>
struct Storage;
// General unaligned memory storage
template<size_t L, typename T>
struct Storage<L, T, false>
{
typedef T type[4];
};
template<typename T>
struct Storage<3, T, false>
{
typedef T type[4];
};
// SSE4.2
template<>
struct Storage<4, float, true>
{
typedef Phanes::Core::Types::Vec4f32Reg type;
};
template<>
struct Storage<3, float, true>
{
typedef Phanes::Core::Types::Vec4f32Reg type;
};
template<>
struct Storage<4, int, true>
{
typedef Phanes::Core::Types::Vec4i32Reg type;
};
template<>
struct Storage<3, int, true>
{
typedef Phanes::Core::Types::Vec4i32Reg type;
};
template<>
struct Storage<4, unsigned int, true>
{
typedef Phanes::Core::Types::Vec4u32Reg type;
};
template<>
struct Storage<3, unsigned int, true>
{
typedef Phanes::Core::Types::Vec4u32Reg type;
};
template<>
struct Storage<2, double, true>
{
typedef Phanes::Core::Types::Vec2f64Reg type;
};
template<>
struct Storage<2, Phanes::Core::Types::int64, true>
{
typedef Phanes::Core::Types::Vec2i64Reg type;
};
template<>
struct Storage<2, Phanes::Core::Types::uint64, true>
{
typedef Phanes::Core::Types::Vec2u64Reg type;
};
// AVX
template<>
struct Storage<4, double, true>
{
typedef Phanes::Core::Types::Vec4f64Reg type;
};
template<>
struct Storage<3, double, true>
{
typedef Phanes::Core::Types::Vec4f64Reg type;
};
template<>
struct Storage<8, float, true>
{
typedef Phanes::Core::Types::Vec4x2f32Reg type;
};
// AVX2
template<>
struct Storage<4, Phanes::Core::Types::int64, true>
{
typedef Phanes::Core::Types::Vec4i64Reg type;
};
template<>
struct Storage<3, Phanes::Core::Types::int64, true>
{
typedef Phanes::Core::Types::Vec4i64Reg type;
};
template<>
struct Storage<4, Phanes::Core::Types::uint64, true>
{
typedef Phanes::Core::Types::Vec4u64Reg type;
};
template<>
struct Storage<3, Phanes::Core::Types::uint64, true>
{
typedef Phanes::Core::Types::Vec4u64Reg type;
};
template<>
struct Storage<8, int, true>
{
typedef Phanes::Core::Types::Vec4x2i32Reg type;
};
template<>
struct Storage<8, unsigned int, true>
{
typedef Phanes::Core::Types::Vec4x2u32Reg type;
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,281 @@
/**
* Contains functions, that have separate simd equivalents.
*/
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/Detail/Vector2Decl.inl"
#include "Core/public/Math/SIMD/SIMDIntrinsics.h"
#include "Core/public/Math/SIMD/PhanesSIMDTypes.h"
namespace Phanes::Core::Math
{
template<RealType T, bool S>
TVector2<T, S>::TVector2(const TVector2<Real, S>& v)
{
Detail::construct_vec2<T, S>::map(*this, v);
}
template<RealType T, bool S>
TVector2<T, S>::TVector2(Real _x, Real _y)
{
Detail::construct_vec2<T, S>::map(*this, _x, _y);
}
template<RealType T, bool S>
TVector2<T, S>::TVector2(Real s)
{
Detail::construct_vec2<T, S>::map(*this, s);
}
template<RealType T, bool S>
TVector2<T, S>::TVector2(const Real* comp)
{
Detail::construct_vec2<T, S>::map(*this, comp);
}
template<RealType T, bool S>
TVector2<T, S>& operator+=(TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
Detail::compute_vec2_add<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector2<T, S>& operator+=(TVector2<T, S>& v1, T s)
{
Detail::compute_vec2_add<T, S>::map(v1, v1, s);
return v1;
}
template<RealType T, bool S>
TVector2<T, S>& operator-=(TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
Detail::compute_vec2_sub<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector2<T, S>& operator-=(TVector2<T, S>& v1, T s)
{
Detail::compute_vec2_sub<T, S>::map(v1, v1, s);
return v1;
}
template<RealType T, bool S>
TVector2<T, S>& operator*=(TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
Detail::compute_vec2_mul<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector2<T, S>& operator*=(TVector2<T, S>& v1, T s)
{
Detail::compute_vec2_mul<T, S>::map(v1, v1, s);
return v1;
}
template<RealType T, bool S>
TVector2<T, S>& operator/=(TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
Detail::compute_vec2_div<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector2<T, S>& operator/=(TVector2<T, S>& v1, T s)
{
Detail::compute_vec2_div<T, S>::map(v1, v1, s);
return v1;
}
template<RealType T, bool S>
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);
return r;
}
template<RealType T, bool 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);
return r;
}
template<RealType T, bool S>
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);
return r;
}
template<RealType T, bool 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);
return r;
}
template<RealType T, bool S>
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);
return r;
}
template<RealType T, bool 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);
return r;
}
template<RealType T, bool S>
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);
return r;
}
template<RealType T, bool 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);
return r;
}
template<RealType T, bool S>
TVector2<T, S> operator/(T s, const TVector2<T, S>& v1)
{
TVector2<T, S> r;
Detail::compute_vec2_div<T, S>::map(r, s, v1);
return r;
}
template<RealType T, bool S>
TVector2<T, S> operator-(T s, const TVector2<T, S>& v1)
{
TVector2<T, S> r;
Detail::compute_vec2_sub<T, S>::map(r, s, v1);
return r;
}
// Comparision
template<RealType T, bool S>
bool operator==(const TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
return Detail::compute_vec2_eq<T, S>::map(v1, v2);
}
template<RealType T, bool S>
bool operator!=(const TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
return Detail::compute_vec2_ieq<T, S>::map(v1, v2);
}
// Inc- / Decrement
template<RealType T, bool S>
TVector2<T, S>& operator++(TVector2<T, S>& v1)
{
Detail::compute_vec2_inc<T, S>::map(v1);
return v1;
}
template<RealType T, bool S>
TVector2<T, S>& operator--(TVector2<T, S>& v1)
{
Detail::compute_vec2_inc<T, S>::map(v1);
return v1;
}
template<RealType T, bool S>
TVector2<T, S>& operator++(TVector2<T, S>& v1, int)
{
return ++v1;
}
template<RealType T, bool S>
TVector2<T, S>& operator--(TVector2<T, S>& v1, int)
{
return --v1;
}
template<RealType T, bool S>
T Magnitude(const TVector2<T, S>& v1)
{
return Detail::compute_vec2_mag<T, S>::map(v1);
}
template<RealType T, bool S>
T SqrMagnitude(const TVector2<T, S>& v1)
{
return Detail::compute_vec2_dotp<T, S>::map(v1, v1);
}
template<RealType T, bool S>
inline T DotP(const TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
return Detail::compute_vec2_dotp<T, S>::map(v1, v2);
}
template<RealType T, bool S>
TVector2<T, S>& MaxV(TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
Detail::compute_vec2_max<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector2<T, S> Max(const TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
TVector2<T, S> r;
Detail::compute_vec2_max<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector2<T, S>& MinV(TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
Detail::compute_vec2_min<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector2<T, S> Min(const TVector2<T, S>& v1, const TVector2<T, S>& v2)
{
TVector2<T, S> r;
Detail::compute_vec2_min<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector2<T, S>& Set(TVector2<T, S>& v1, T x, T y)
{
Detail::compute_vec2_set<T, S>::map(v1, x, y);
return v1;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,308 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/Detail/Vector3Decl.inl"
#include "Core/public/Math/SIMD/SIMDIntrinsics.h"
#include "Core/public/Math/SIMD/PhanesSIMDTypes.h"
namespace Phanes::Core::Math
{
template<RealType T, bool S>
TVector3<T, S>::TVector3(Real _x, Real _y, Real _z)
{
Detail::construct_vec3<T, S>::map(*this, _x, _y, _z);
}
template<RealType T, bool S>
TVector3<T, S>::TVector3(Real s)
{
Detail::construct_vec3<T, S>::map(*this, s);
}
template<RealType T, bool S>
TVector3<T, S>::TVector3(const TVector2<Real, S>& v1, Real s)
{
Detail::construct_vec3<T, S>::map(*this, v1, s);
}
template<RealType T, bool S>
TVector3<T, S>::TVector3(const Real* comp)
{
static_assert(sizeof(comp) >= sizeof(T) * 3, "Size of comp has to be of at least three (3) components.");
Detail::construct_vec3<T, S>::map(*this, comp);
}
template<RealType T, bool S>
TVector3<T, S>& operator+=(TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
Detail::compute_vec3_add<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector3<T, S>& operator+=(TVector3<T, S>& v1, T s)
{
Detail::compute_vec3_add<T, S>::map(v1, v1, s);
return v1;
}
template<RealType T, bool S>
TVector3<T, S>& operator-=(TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
Detail::compute_vec3_sub<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector3<T, S>& operator-=(TVector3<T, S>& v1, T s)
{
Detail::compute_vec3_sub<T, S>::map(v1, v1, s);
return v1;
}
template<RealType T, bool S>
TVector3<T, S>& operator*=(TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
Detail::compute_vec3_mul<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector3<T, S>& operator*=(TVector3<T, S>& v1, T s)
{
Detail::compute_vec3_mul<T, S>::map(v1, v1, s);
return v1;
}
template<RealType T, bool S>
TVector3<T, S>& operator/=(TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
Detail::compute_vec3_div<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector3<T, S>& operator/=(TVector3<T, S>& v1, T s)
{
Detail::compute_vec3_div<T, S>::map(v1, v1, s);
return v1;
}
template<RealType T, bool S>
TVector3<T, S> operator+(const TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
TVector3<T, S> r;
Detail::compute_vec3_add<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector3<T, S> operator+(const TVector3<T, S>& v1, T s)
{
TVector3<T, S> r;
Detail::compute_vec3_add<T, S>::map(r, v1, s);
return r;
}
template<RealType T, bool S>
TVector3<T, S> operator-(const TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
TVector3<T, S> r;
Detail::compute_vec3_sub<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector3<T, S> operator-(const TVector3<T, S>& v1, T s)
{
TVector3<T, S> r;
Detail::compute_vec3_sub<T, S>::map(r, v1, s);
return r;
}
template<RealType T, bool S>
TVector3<T, S> operator-(T s, const TVector3<T, S>& v1)
{
TVector3<T, S> r;
Detail::compute_vec3_sub<T, S>::map(r, s, v1);
return r;
}
template<RealType T, bool S>
TVector3<T, S> operator*(const TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
TVector3<T, S> r;
Detail::compute_vec3_mul<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector3<T, S> operator*(const TVector3<T, S>& v1, T s)
{
TVector3<T, S> r;
Detail::compute_vec3_mul<T, S>::map(r, v1, s);
return r;
}
template<RealType T, bool S>
TVector3<T, S> operator/(const TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
TVector3<T, S> r;
Detail::compute_vec3_div<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector3<T, S> operator/(const TVector3<T, S>& v1, T s)
{
TVector3<T, S> r;
Detail::compute_vec3_div<T, S>::map(r, v1, s);
return r;
}
template<RealType T, bool S>
TVector3<T, S> operator/(T s, const TVector3<T, S>& v1)
{
TVector3<T, S> r;
Detail::compute_vec3_div<T, S>::map(r, s, v1);
return r;
}
// Comparision
template<RealType T, bool S>
bool operator==(const TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
return Detail::compute_vec3_eq<T, S>::map(v1, v2);
}
template<RealType T, bool S>
bool operator!=(const TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
return Detail::compute_vec3_ieq<T, S>::map(v1, v2);
}
// Inc- / Decrement
template<RealType T, bool S>
TVector3<T, S>& operator++(TVector3<T, S>& v1)
{
Detail::compute_vec3_inc<T, S>::map(v1);
return v1;
}
template<RealType T, bool S>
TVector3<T, S>& operator--(TVector3<T, S>& v1)
{
Detail::compute_vec3_inc<T, S>::map(v1);
return v1;
}
template<RealType T, bool S>
TVector3<T, S>& operator++(TVector3<T, S>& v1, int)
{
return ++v1;
}
template<RealType T, bool S>
TVector3<T, S>& operator--(TVector3<T, S>& v1, int)
{
return --v1;
}
// Other
template<RealType T, bool S>
TVector3<T, S> CrossP(const TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
TVector3<T, S> r;
Detail::compute_vec3_cross_p<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector3<T, S>& CrossPV(TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
Detail::compute_vec3_cross_p<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
inline T Magnitude(const TVector3<T, S>& v1)
{
return Detail::compute_vec3_mag<T, S>::map(v1);
}
template<RealType T, bool S>
inline T SqrMagnitude(const TVector3<T, S>& v1)
{
return Detail::compute_vec3_dotp<T, S>::map(v1, v1);
}
template<RealType T, bool S>
inline T DotP(const TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
return Detail::compute_vec3_dotp<T, S>::map(v1, v2);
}
template<RealType T, bool S>
TVector3<T, S>& MaxV(TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
Detail::compute_vec3_max<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector3<T, S> Max(TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
TVector3<T, S> r;
Detail::compute_vec3_max<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector3<T, S>& MinV(TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
Detail::compute_vec3_min<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector3<T, S> Min(TVector3<T, S>& v1, const TVector3<T, S>& v2)
{
TVector3<T, S> r;
Detail::compute_vec3_min<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector3<T, S>& Set(TVector3<T, S>& v1, T x, T y, T z)
{
Detail::compute_vec3_set<T, S>::map(v1, x, y, z);
}
template<RealType T, bool S>
TVector3<T, S>& ClampToCubeV(TVector3<T, S> v1, T cubeRadius)
{
Detail::compute_vec3_clamp<T, S>::map(v1, v1, cubeRadius);
return v1;
}
template<RealType T, bool S>
TVector3<T, S> ClampToCube(const TVector3<T, S>& v1, T cubeRadius)
{
TVector3<T, S> r;
Detail::compute_vec3_clamp<T, S>::map(r, v1, cubeRadius);
return r;
}
}

View File

@@ -0,0 +1,867 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/MathCommon.hpp"
#include "Core/public/Math/SIMD/Storage.h"
#include "Core/public/Math/MathFwd.h"
#include "Core/public/Math/Vector2.hpp"
#include "Core/public/Math/Vector3.hpp"
#define PZeroVector4(type, aligned) Phanes::Core::Math::TVector4<##type, ##aligned>(0,0,0,0)
namespace Phanes::Core::Math
{
/// 4D Vector defined with x, y, z, w.
/// Alignment allows for possible simd optimization.
template<RealType T, bool S = false>
struct TVector4
{
public:
using Real = T;
union
{
struct {
/// <summary>
/// X component of vector
/// </summary>
Real x;
/// <summary>
/// X component of vector
/// </summary>
Real y;
/// <summary>
/// Z component of vector
/// </summary>
Real z;
/// <summary>
/// W component of vector
/// </summary>
Real w;
};
/// <summary>
/// Wraps components in one array / xmm register.
/// </summary>
union
{
typename SIMD::Storage<4, Real, SIMD::use_simd<T, 4, S>::value>::type comp;
typename SIMD::Storage<4, Real, SIMD::use_simd<T, 4, S>::value>::type data;
};
};
public:
/// Default constructor
TVector4() = default;
/// <summary>
/// Construct vector from one scalar.
/// <para>x,y,z,w = s</para>
/// </summary>
/// <param name="s">Scalar</param>
TVector4(Real s);
/// <summary>
/// Construct vector from x, y, z, w components.
/// </summary>
/// <param name="_x">X component</param>
/// <param name="_y">Y component</param>
/// <param name="_z">Z component</param>
/// <param name="_w">W component</param>
TVector4(Real _x, Real _y, Real _z, Real _w);
/// <summary>
/// Construct vector from two 2d vectors like:
/// <para>x, y = v1.x, v1.y</para>
/// z, w = v2.x, v2.y
/// </summary>
/// <param name="v1">TVector2 one</param>
/// <param name="v2">TVector2 two</param>
TVector4(const TVector2<Real, S>& v1, const TVector2<Real, S>& v2);
/// <summary>
/// Construct vector from 3d vector (x,y,z) and w
/// </summary>
/// <param name="v1">TVector3</param>
/// <param name="w">W</param>
TVector4(const TVector3<Real, S>& v1, Real w);
/// <summary>
/// Construct vector from array of components
/// </summary>
/// <param name="comp">Array of at least 4 components</param>
TVector4(const Real* comp);
};
// ===================== //
// Vector4 operators //
// ===================== //
// Unary arithmetic operators
/// <summary>
/// Vector addition.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& operator+= (TVector4<T, S>& v1, const TVector4<T, S>& v2);
/// <summary>
/// Vector - scalar addition.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <param name="s">Scalar</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& operator+= (TVector4<T, S>& v1, T s);
/// <summary>
/// Vector substraction.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& operator-= (TVector4<T, S>& v1, const TVector4<T, S>& v2);
/// <summary>
/// Vector - scalar substraction.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <param name="s">Scalar</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& operator-= (TVector4<T, S>& v1, T s);
/// <summary>
/// Vector - scalar multiplication.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <param name="s">Scalar</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& operator*= (TVector4<T, S>& v1, T s);
/// <summary>
/// Scale vector by another vector componentwise.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& operator*= (TVector4<T, S>& v1, const TVector4<T, S>& v2);
/// <summary>
/// Vector - scalar division.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <param name="s">Scalar</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& operator/= (TVector4<T, S>& v1, T s);
/// <summary>
/// Coponentwise vector division.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& operator/= (TVector4<T, S>& v1, const TVector4<T, S>& v2);
// Unary arithmetic operators
/// <summary>
/// Vector addition.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Computed vector.</returns>
template<RealType T, bool S>
TVector4<T, S> operator+ (const TVector4<T, S>& v1, const TVector4<T, S>& v2);
/// <summary>
/// Vector - scalar addition.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <param name="s">Scalar</param>
/// <returns>Computed vector.</returns>
template<RealType T, bool S>
TVector4<T, S> operator+ (const TVector4<T, S>& v1, T s);
/// <summary>
/// Vector substraction.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Computed vector.</returns>
template<RealType T, bool S>
TVector4<T, S> operator- (const TVector4<T, S>& v1, const TVector4<T, S>& v2);
/// <summary>
/// Vector - scalar substraction.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <param name="s">Scalar</param>
/// <returns>Computed vector.</returns>
template<RealType T, bool S>
TVector4<T, S> operator- (const TVector4<T, S>& v1, T s);
template<RealType T, bool S>
TVector4<T, S> operator- (T s, const TVector4<T, S>& v1);
/// <summary>
/// Vector - scalar multiplication.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <param name="s">Scalar</param>
/// <returns>Computed vector.</returns>
template<RealType T, bool S>
TVector4<T, S> operator* (const TVector4<T, S>& v1, T s);
template<RealType T, bool S>
FORCEINLINE TVector4<T, S> operator* (T s, const TVector4<T, S>& v1) { return v1 * s; };
/// <summary>
/// Scale vector by another vector componentwise.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Computed vector.</returns>
template<RealType T, bool S>
TVector4<T, S> operator* (const TVector4<T, S>& v1, const TVector4<T, S>& v2);
/// <summary>
/// Vector - scalar division.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <param name="s">Scalar</param>
/// <returns>Computed vector.</returns>
template<RealType T, bool S>
TVector4<T, S> operator/ (const TVector4<T, S>& v1, T s);
template<RealType T, bool S>
FORCEINLINE TVector4<T, S> operator/ (T s, const TVector4<T, S>& v1);
/// <summary>
/// Componentwise vector division.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Computed vector.</returns>
template<RealType T, bool S>
TVector4<T, S> operator/ (const TVector4<T, S>& v1, const TVector4<T, S>& v2);
// Comparison operators
/// <summary>
/// Test to vectors for equality.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns><code>True</code>, if equal and <code>false</code> if not.</returns>
template<RealType T, bool S>
bool operator==(const TVector4<T, S>& v1, const TVector4<T, S>& v2);
/// <summary>
/// Test to vectors for inequality.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns><code>True</code>, if inequal and <code>false</code> if equal.</returns>
template<RealType T, bool S>
bool operator!=(const TVector4<T, S>& v1, const TVector4<T, S>& v2);
// Unaray increment operators
/// <summary>
/// Increment vector by one
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& operator++(TVector4<T, S>& v1);
/// <summary>
/// Decrement vector by one
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>v1</returns>
template<RealType T, bool S>
TVector4<T, S>& operator--(TVector4<T, S>& v1);
/// <summary>
/// Increment vector by one
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>v1</returns>
template<RealType T, bool S>
TVector4<T, S> operator++(TVector4<T, S>& v1, int);
/// <summary>
/// Decrement vector by one
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S> operator--(TVector4<T, S>& v1, int);
// ====================== //
// TVector4 functions //
// ====================== //
template<RealType T, bool S>
TVector4<T, S>& Set(TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
v1 = v2;
return v1;
}
/// <summary>
/// Set vector to values.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <param name="x">X Component</param>
/// <param name="y">Y Component</param>
/// <param name="z">Z Component</param>
/// <param name="w">W Component</param>
/// <returns></returns>
template<RealType T, bool S>
TVector4<T, S>& Set(TVector4<T, S>& v1, T x, T y, T z, T w);
/// <summary>
/// Get magnitude of vector.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v">Vector</param>
/// <returns>Magnitude of vector.</returns>
template<RealType T, bool S>
T Magnitude(const TVector4<T, S>& v);
/// <summary>
/// Get square of magnitude of vector.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v">Vector</param>
/// <returns>Square of magnitude of vector.</returns>
template<RealType T, bool S>
T SqrMagnitude(const TVector4<T, S>& v);
/// <summary>
/// Get magnitude of vector.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v">Vector</param>
/// <returns>Magnitude of vector.</returns>
template<RealType T, bool S>
constexpr T Length(const TVector4<T, S>& v) { return Magnitude(v); }
/// <summary>
/// Get square of magnitude of vector.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v">Vector</param>
/// <returns>Square of magnitude of vector.</returns>
template<RealType T, bool S>
constexpr T SqrLength(const TVector4<T, S>& v) { return SqrMagnitude(v); }
/// <summary>
/// Angle between two vectors.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns></returns>
template<RealType T, bool S>
T Angle(const TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
return acos(DotP(v1, v2) / (Magnitude(v1) * Magnitude(v2)));
}
/// <summary>
/// Cosine of angle between two vectors.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns></returns>
template<RealType T, bool S>
T CosineAngle(const TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
return DotP(v1, v2) / (Magnitude(v1) * Magnitude(v2));
}
/// <summary>
/// Normalizes a vector.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>Normalized vector</returns>
template<RealType T, bool S>
TVector4<T, S> Normalize(const TVector4<T, S>& v1)
{
T vecNorm = Magnitude(v1);
vecNorm = (vecNorm < P_FLT_INAC) ? (T)1.0 : vecNorm;
return (v1 / vecNorm);
}
/// <summary>
/// Normalizes a vector.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& NormalizeV(TVector4<T, S>& v1)
{
T vecNorm = Magnitude(v1);
vecNorm = (vecNorm < P_FLT_INAC) ? (T)1.0 : vecNorm;
v1 /= vecNorm;
return v1;
}
/// <summary>
/// Normalizes a vector.
/// </summary>
/// <remarks>Doesn't check for zero vector.</remarks>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>Normalized vector</returns>
template<RealType T, bool S>
TVector4<T, S> UnsafeNormalize(const TVector4<T, S>& v1)
{
return v1 / Magnitude(v1);
}
/// <summary>
/// Normalizes a vector.
/// </summary>
/// <remarks>Doesn't check for zero vector.</remarks>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& UnsafeNormalizeV(TVector4<T, S>& v1)
{
v1 /= Magnitude(v1);
return v1;
}
/// <summary>
/// Calculates the dot product between two vectors.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Dot product between vectors.</returns>
template<RealType T, bool S>
T DotP(const TVector4<T, S>& v1, const TVector4<T, S>& v2);
/// <summary>
/// Gets componentwise max of both vectors.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Vector with componentwise max of both vectors.</returns>
template<RealType T, bool S>
TVector4<T, S> Max(const TVector4<T, S>& v1, const TVector4<T, S>& v2);
/// <summary>
/// Gets componentwise max of both vectors.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& MaxV(TVector4<T, S>& v1, const TVector4<T, S>& v2);
/// <summary>
/// Gets componentwise min of both vectors.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Vector with componentwise max of both vectors.</returns>
template<RealType T, bool S>
TVector4<T, S> Min(const TVector4<T, S>& v1, const TVector4<T, S>& v2);
/// <summary>
/// Gets componentwise min of both vectors.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector one</param>
/// <param name="v2">Vector two</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& MinV(TVector4<T, S>& v1, const TVector4<T, S>& v2);
/// <summary>
/// Inverses vector.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>Inverted vector</returns>
template<RealType T, bool S>
TVector4<T, S> Negate(const TVector4<T, S>& v1)
{
return (T)0.0 - v1;
}
/// <summary>
/// Inverses vector.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& NegateV(TVector4<T, S>& v1)
{
return (v1 = (T)0.0 - v1);
}
/// <summary>
/// Inverses the components of vector.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>Vector with reciprocal of components.</returns>
template<RealType T, bool S>
TVector4<T, S> CompInverse(const TVector4<T, S>& v1)
{
return (T)1.0 / v1;
}
/// <summary>
/// Inverses the components of vector.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& CompInverseV(TVector4<T, S>& v1)
{
return (v1 = (T)1.0 / v1);
}
/// <summary>
/// Clamp the vectors length to a magnitude.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1"></param>
/// <param name="s"></param>
/// <returns>Vector with magnitude clamped to s.</returns>
template<RealType T, bool S>
TVector4<T, S> ClampToMagnitude(const TVector4<T, S>& v1, T min, T max)
{
T magnitude = Magnitude(v1);
TVector4<T, S> unitVec;
unitVec = (magnitude > P_FLT_INAC) ? v1 / magnitude : PZeroVector4(T, false);
magnitude = Clamp(magnitude, min, max);
return unitVec * magnitude;
}
/// <summary>
/// Clamp the vectors length to a magnitude.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <param name="s">Magnitude</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& ClampToMagnitudeV(TVector4<T, S>& v1, T min, T max)
{
T magnitude = Magnitude(v1);
v1 = (magnitude > P_FLT_INAC) ? v1 / magnitude : PZeroVector4(T, false);
v1 *= Clamp(magnitude, min, max);
return v1;
}
/// <summary>
/// Scale vector to a magnitude
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <param name="s">Magnitude</param>
/// <returns>Vector with scaled magnitude.</returns>
template<RealType T, bool S>
TVector4<T, S> ScaleToMagnitude(const TVector4<T, S>& v1, T s)
{
return Normalize(v1) * s;
}
/// <summary>
/// Scale vector to a magnitude
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <param name="s">Magnitude</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& ScaleToMagnitudeV(TVector4<T, S>& v1, T s)
{
NormalizeV(v1);
v1 *= s;
return v1;
}
/// <summary>
/// Reflect vector on plane.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <param name="normal">Planes normal</param>
/// <returns>Reflected vector</returns>
template<RealType T, bool S>
TVector4<T, S> Reflect(const TVector4<T, S>& v1, const TVector4<T, S> normal)
{
return ((T)2.0 * DotP(v1, normal) * normal) - v1;
}
/// <summary>
/// Reflect vector on plane.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <param name="normal">Planes normal</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& ReflectV(TVector4<T, S>& v1, const TVector4<T, S> normal)
{
v1 = ((T)2.0 * DotP(v1, normal) * normal) - v1;
return v1;
}
/// <summary>
/// Project vector v1 onto v2.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector to project</param>
/// <param name="v2">Vector to project on</param>
/// <returns>Projected vector.</returns>
template<RealType T, bool S>
TVector4<T, S> Project(const TVector4<T, S>& v1, const TVector4<T, S> v2)
{
return (DotP(v1, v2) / DotP(v2, v2)) * v2;
}
/// <summary>
/// Project vector v1 onto v2.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector to project</param>
/// <param name="v2">Vector to project on</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& ProjectV(TVector4<T, S>& v1, const TVector4<T, S> v2)
{
v1 = (DotP(v1, v2) / DotP(v2, v2)) * v2;
return v1;
}
/// <summary>
/// Reject vector v1 from v2.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector to reject</param>
/// <param name="v2">Vector to reject from</param>
/// <returns>Rejected vector.</returns>
template<RealType T, bool S>
TVector4<T, S> Reject(const TVector4<T, S>& v1, const TVector4<T, S> v2)
{
return v1 - (DotP(v1, v2) / DotP(v2, v2)) * v2;
}
/// <summary>
/// Reject vector v1 from v2.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector to reject</param>
/// <param name="v2">Vector to reject from</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& RejectV(TVector4<T, S>& v1, const TVector4<T, S> v2)
{
v1 = v1 - (DotP(v1, v2) / DotP(v2, v2)) * v2;
return v1;
}
/// <summary>
/// Perspective divide vector.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>Perspective divided vector.</returns>
template<RealType T, bool S>
TVector4<T, S> PerspectiveDivide(const TVector4<T, S>& v1);
/// <summary>
/// Perspective divide vector.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <typeparam name="A">Vector is aligned?</typeparam>
/// <param name="v1">Vector</param>
/// <returns>Copy of v1.</returns>
template<RealType T, bool S>
TVector4<T, S>& PerspectiveDivideV(TVector4<T, S>& v1);
/// <summary>
/// Tests if vector is normalized.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <param name="v1">Vector</param>
/// <param name="threshold">Threshold to vector magnitude of 1.0</param>
/// <returns>True if vector is normalized, false if not.</returns>
template<RealType T, bool S>
FORCEINLINE bool IsNormalized(const TVector4<T, S>& v1, T threshold = P_FLT_INAC)
{
return (SqrMagnitude(v1) - (T)1.0) < threshold;
}
/// <summary>
/// Tests if vectors are parallel.
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <param name="v1">Vector</param>
/// <param name="v2">Vector</param>
/// <param name="threshold">Allowed T inaccuracy from one (e.g. 0.98f)</param>
/// <returns>True if parallel, false if not.</returns>
template<RealType T, bool S>
FORCEINLINE bool IsParallel(const TVector4<T, S>& v1, const TVector4<T, S>& v2, T threshold = 1.0f - P_FLT_INAC)
{
return (abs(DotP(v1, v2)) > threshold);
}
/// <summary>
/// Tests whether two vectors are coincident (Parallel and point in same direction).
/// </summary>
/// <typeparam name="T">Type of vector</typeparam>
/// <param name="v1">Vector</param>
/// <param name="v2">Vector</param>
/// <param name="threshold">Allowed T inaccuracy from one (e.g. 0.98f)</param>
/// <returns>True if coincident, false if not.</returns>
template<RealType T, bool S>
FORCEINLINE bool IsCoincident(const TVector4<T, S>& v1, const TVector4<T, S>& v2, T threshold = 1.0f - P_FLT_INAC)
{
return (DotP(v1, v2) > threshold);
}
}
#include "Core/public/Math/Vector4.inl"

View File

@@ -0,0 +1,294 @@
#pragma once
#include "Core/public/Math/Boilerplate.h"
#include "Core/public/Math/Detail/Vector4Decl.inl"
#include "Core/public/Math/SIMD/SIMDIntrinsics.h"
#include "Core/public/Math/SIMD/PhanesSIMDTypes.h"
namespace Phanes::Core::Math
{
template<RealType T, bool S>
TVector4<T, S>::TVector4(Real _x, Real _y, Real _z, Real _w)
{
Detail::construct_vec4<T, S>::map(*this, _x, _y, _z, _w);
}
template<RealType T, bool S>
Phanes::Core::Math::TVector4<T, S>::TVector4(Real s)
{
Detail::construct_vec4<T, S>::map(*this, s);
}
template<RealType T, bool S>
Phanes::Core::Math::TVector4<T, S>::TVector4(const TVector2<Real, S>& v1, const TVector2<Real, S>& v2)
{
Detail::construct_vec4<T, S>::map(*this, v1, v2);
}
template<RealType T, bool S>
Phanes::Core::Math::TVector4<T, S>::TVector4(const Real* comp)
{
static_assert(sizeof(comp) >= sizeof(T) * 4, "Size of comp has to be of at least four (4) components.");
Detail::construct_vec4<T, S>::map(*this, comp);
}
template<RealType T, bool S>
Phanes::Core::Math::TVector4<T, S>::TVector4(const TVector3<T, S>& v, T w)
{
Detail::construct_vec4<T, S>::map(*this, v, w);
}
template<RealType T, bool S>
TVector4<T, S>& operator+=(TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
Detail::compute_vec4_add<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector4<T, S>& operator+=(TVector4<T, S>& v1, T s)
{
Detail::compute_vec4_add<T, S>::map(v1, v1, s);
return v1;
}
template<RealType T, bool S>
TVector4<T, S>& operator-=(TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
Detail::compute_vec4_sub<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector4<T, S>& operator-=(TVector4<T, S>& v1, T s)
{
Detail::compute_vec4_sub<T, S>::map(v1, v1, s);
return v1;
}
template<RealType T, bool S>
TVector4<T, S>& operator*=(TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
Detail::compute_vec4_mul<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector4<T, S>& operator*=(TVector4<T, S>& v1, T s)
{
Detail::compute_vec4_mul<T, S>::map(v1, v1, s);
return v1;
}
template<RealType T, bool S>
TVector4<T, S>& operator/=(TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
Detail::compute_vec4_div<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector4<T, S>& operator/=(TVector4<T, S>& v1, T s)
{
Detail::compute_vec4_div<T, S>::map(v1, v1, s);
return v1;
}
template<RealType T, bool S>
TVector4<T, S> operator+(const TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
TVector4<T, S> r;
Detail::compute_vec4_add<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector4<T, S> operator+(const TVector4<T, S>& v1, T s)
{
TVector4<T, S> r;
Detail::compute_vec4_add<T, S>::map(r, v1, s);
return r;
}
template<RealType T, bool S>
TVector4<T, S> operator-(const TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
TVector4<T, S> r;
Detail::compute_vec4_sub<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector4<T, S> operator-(const TVector4<T, S>& v1, T s)
{
TVector4<T, S> r;
Detail::compute_vec4_sub<T, S>::map(r, v1, s);
return r;
}
template<RealType T, bool S>
TVector4<T, S> operator-(T s, const TVector4<T, S>& v1)
{
TVector4<T, S> r;
Detail::compute_vec4_sub<T, S>::map(r, s, v1);
return r;
}
template<RealType T, bool S>
TVector4<T, S> operator*(const TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
TVector4<T, S> r;
Detail::compute_vec4_mul<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector4<T, S> operator*(const TVector4<T, S>& v1, T s)
{
TVector4<T, S> r;
Detail::compute_vec4_mul<T, S>::map(r, v1, s);
return r;
}
template<RealType T, bool S>
TVector4<T, S> operator/(const TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
TVector4<T, S> r;
Detail::compute_vec4_div<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector4<T, S> operator/(const TVector4<T, S>& v1, T s)
{
TVector4<T, S> r;
Detail::compute_vec4_div<T, S>::map(r, v1, s);
return r;
}
template<RealType T, bool S>
TVector4<T, S> operator/(T s, const TVector4<T, S>& v1)
{
TVector4<T, S> r;
Detail::compute_vec4_div<T, S>::map(r, s, v1);
return r;
}
// Comparision
template<RealType T, bool S>
bool operator==(const TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
return Detail::compute_vec4_eq<T, S>::map(v1, v2);
}
template<RealType T, bool S>
bool operator!=(const TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
return Detail::compute_vec4_ieq<T, S>::map(v1, v2);
}
// Inc- / Decrement
template<RealType T, bool S>
TVector4<T, S>& operator++(TVector4<T, S>& v1)
{
Detail::compute_vec4_inc<T, S>::map(v1);
return v1;
}
template<RealType T, bool S>
TVector4<T, S>& operator--(TVector4<T, S>& v1)
{
Detail::compute_vec4_dec<T, S>::map(v1);
return v1;
}
template<RealType T, bool S>
TVector4<T, S>& operator++(TVector4<T, S>& v1, int)
{
return ++v1;
}
template<RealType T, bool S>
TVector4<T, S>& operator--(TVector4<T, S>& v1, int)
{
return --v1;
}
template<RealType T, bool S>
T DotP(const TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
return Detail::compute_vec4_dotp<T, S> ::map(v1, v2);
}
template<RealType T, bool S>
TVector4<T, S>& Set(TVector4<T, S>& v1, T x, T y, T z, T w)
{
Detail::compute_vec4_set<T, S>::map(v1, x, y, z, w);
}
template<RealType T, bool S>
T Magnitude(const TVector4<T, S>& v)
{
return Detail::compute_vec4_mag<T, S>::map(v);
}
template<RealType T, bool S>
T SqrMagnitude(const TVector4<T, S>& v)
{
return Detail::compute_vec4_dotp<T, S>::map(v, v);
}
template<RealType T, bool S>
TVector4<T, S> Max(const TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
TVector4<T, S> r;
Detail::compute_vec4_max<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector4<T, S>& MaxV(TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
Detail::compute_vec4_max<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector4<T, S> Min(const TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
TVector4<T, S> r;
Detail::compute_vec4_min<T, S>::map(r, v1, v2);
return r;
}
template<RealType T, bool S>
TVector4<T, S>& MinV(TVector4<T, S>& v1, const TVector4<T, S>& v2)
{
Detail::compute_vec4_min<T, S>::map(v1, v1, v2);
return v1;
}
template<RealType T, bool S>
TVector4<T, S> PerspectiveDivide(const TVector4<T, S>& v1)
{
TVector4<T, S> r;
Detail::compute_vec4_pdiv<T, S>::map(r, v1);
return r;
}
template<RealType T, bool S>
TVector4<T, S>& PerspectiveDivideV(TVector4<T, S>& v1)
{
Detail::compute_vec4_pdiv<T, S>::map(v1, v1);
return v1;
}
}