Initial commit

This commit is contained in:
github-classroom[bot]
2025-05-08 08:33:11 +00:00
committed by GitHub
commit 294e9ab735
188 changed files with 65381 additions and 0 deletions

110
inc/EliteMath/EMat22.h Normal file
View File

@@ -0,0 +1,110 @@
/*=============================================================================*/
// Copyright 2021-2022 Elite Engine
// Authors: Matthieu Delaere
/*=============================================================================*/
// EMat22.h: Row Major Matrix 2x2 struct
// | x1 , y1 |
// | x2 , y2 |
// Info: Row Major Matrix for cache coherency, even though this is a small piece of data,
// it is a good practice.
/*=============================================================================*/
#ifndef ELITE_MATH_MATRIX22
#define ELITE_MATH_MATRIX22
namespace Elite {
#define IdentityMat22 Mat22();
//Matrix 2x2
struct Mat22
{
//=== Datamembers ===
Vector2 r[2] = { {1.f,0.f},{0.f, 1.f} };
//=== Constructors ===
Mat22() {};
Mat22(float x1, float y1, float x2, float y2)
{ r[0] = Vector2(x1, y1); r[1] = Vector2(x2, y2); };
Mat22(const Vector2& r1, const Vector2& r2)
{ r[0] = r1; r[1] = r2; };
//=== Matrix Conversions Functions ===
#ifdef USE_BOX2D
//From row-major to column-major
Mat22& operator=(const b2Mat22& m)
{
r[0][0] = m.ex.x; r[0][1] = m.ex.y;
r[1][0] = m.ey.x; r[1][1] = m.ey.y;
return *this;
}
operator b2Mat22() const
{
return b2Mat22(r[0][0], r[1][0], r[0][1], r[1][1]);
}
#endif
//=== Arithmetic Operators ===
inline auto operator+(const Mat22& m) const
{ return Mat22(r[0] + m.r[0], r[1] + m.r[1]); }
inline auto operator-(const Mat22& m) const
{ return Mat22(r[0] - m.r[0], r[1] - m.r[1]); }
inline auto operator*(float scale) const
{ return Mat22(r[0] * scale, r[1] * scale); }
inline auto operator*(const Mat22& m) const
{
//The rows of the first matrix are multiplied by the columns of the second one
Mat22 res = {};
for(auto row = 0; row < 2; ++row)
{
for(auto col = 0; col < 2; ++col)
{
res.r[row][col] = r[row][0] * m.r[0][col] +
r[row][1] * m.r[1][col];
}
}
return res;
}
inline auto operator*(const Vector2& v) const
{
//Same principle as mat22 * mat22, but with a "column" Vector2...
return Vector2(
r[0][0] * v.x + r[0][1] * v.y,
r[1][0] * v.x + r[1][1] * v.y);
}
//=== Compound Assignment Operators ===
inline auto& operator+=(const Mat22& m)
{ r[0] += m.r[0]; r[1] += m.r[1]; return *this; }
inline auto& operator-=(const Mat22& m)
{ r[0] -= m.r[0]; r[1] -= m.r[1]; return *this; }
inline auto& operator*=(float scale)
{ r[0] *= scale; r[1] *= scale; return *this; }
inline auto& operator*=(const Mat22& m)
{ auto result = *this * m; return *this = result; }
//=== Internal Vector Functions ===
void SetIdentity()
{ r[0] = Vector2( 1.f, 0.f); r[1] = Vector2(0.f, 1.f); }
auto Determinant() const //Formula: x1*y2 - y1*x2
{ return r[0][0] * r[1][1] - r[0][1] * r[1][0]; }
auto Inverse() const
{
auto det = Determinant();
if (AreEqual(det, 0.f)) //We cannot get inverse because determinant is zero, return identity matrix instead
return IdentityMat22;
det = 1.f / det;
auto m00 = det * r[1][1], m01 = det * (-r[0][1]);
auto m10 = det * (-r[1][0]), m11 = det * r[0][0];
return Mat22(m00, m01, m10, m11);
}
};
//=== Global Matrix Functions ===
inline auto GetDeterminant(const Mat22& m)
{ return m.Determinant(); }
inline auto GetInverse(const Mat22& m)
{ return m.Inverse(); }
}
#endif

21
inc/EliteMath/EMath.h Normal file
View File

@@ -0,0 +1,21 @@
/*=============================================================================*/
// Copyright 2021-2022 Elite Engine
// Authors: Matthieu Delaere
/*=============================================================================*/
// EMath.h: General Math header that includes all math types and utilities
/*=============================================================================*/
#ifndef ELITE_MATH
#define ELITE_MATH
/* --- STANDARD --- */
#include <math.h>
/* --- UTILITIES --- */
#include "EMathUtilities.h"
/* --- TYPES --- */
#include "EVector2.h"
#include "EVector3.h"
#include "EMat22.h"
#include "FMatrix.h"
/* --- TYPE DEFINES --- */
#endif

View File

@@ -0,0 +1,133 @@
/*=============================================================================*/
// Copyright 2021-2022 Elite Engine
// Authors: Matthieu Delaere, Thomas Goussaert
/*=============================================================================*/
// EMathUtilities.h: Utility class containing a bunch of commonely used functionality (not custom-type specific)
/*=============================================================================*/
#ifndef ELITE_MATH_UTILITIES
#define ELITE_MATH_UTILITIES
//Standard C++ includes
#include <cstdlib>
#include <cfloat>
#include <type_traits>
namespace Elite {
/* --- CONSTANTS --- */
#define E_PI 3.14159265358979323846
#define E_PI_2 1.57079632679489661923
#define E_PI_4 0.785398163397448309616
/* --- FUNCTIONS --- */
/*! Comparing two values (preferably float or doubles) and see if they are equal. You can change the precision (by default: epsilon)*/
template<typename T, typename = std::enable_if<std::is_pod<T>::value>>
constexpr bool AreEqual(T a, T b, float precision = FLT_EPSILON)
{
if (abs(a - b) > precision)
return false;
return true;
}
/*! An accurate inverse square root*/
inline float InvSqrt(float f) //sqrtf not defined as constexpr
{
return 1.0f / sqrtf(f);
}
/*! An fast inverse square root, not fully accurate. Implementation based on Quake III Arena*/
/*! Reference: https://betterexplained.com/articles/understanding-quakes-fast-inverse-square-root/ */
inline float InvSqrtFst(float f)
{
const float xHalf = 0.5f * f;
int i = *reinterpret_cast<int*>(&f);
i = 0x5f3759df - (i >> 1);
f = *reinterpret_cast<float*>(&i);
f = f*(1.5f - xHalf*f*f);
return f;
}
/*! Function to square a number */
template<typename T, typename = std::enable_if<std::is_pod<T>::value>>
constexpr auto Square(T v)
{
return v*v;
}
/*! Function to convert degrees to radians */
constexpr float ToRadians(const float angle)
{
return angle * (static_cast<float>(E_PI) / 180.f);
}
/*! Function to convert radians to degrees */
constexpr float ToDegrees(const float angle)
{
return angle * (180.f / static_cast<float>(E_PI));
}
/*! Clamped angle between -pi, pi (in radians) */
inline float ClampedAngle(const float radians)
{
float a = fmodf(radians + b2_pi, 2 * b2_pi);
a = a >= 0 ? (a - b2_pi) : (a + b2_pi);
return a;
}
/*! Template function to clamp between a minimum and a maximum value -> in STD since c++17 */
template<typename T>
constexpr T Clamp(const T a, T min, T max)
{
if (a < min)
return min;
if (a > max)
return max;
return a;
}
/*! Template function to clamp between a minimum and a maximum value*/
template<typename T>
constexpr T ClampRef(T& a, T min, T max)
{
if (a < min)
a = min;
if (a > max)
a = max;
return a;
}
/*! Random Integer */
inline int randomInt(int max = 1)
{ return rand() % max; }
/*! Random Float */
inline float randomFloat(float max = 1.f)
{ return max * (float(rand()) / RAND_MAX); }
/*! Random Float */
inline float randomFloat(float min, float max)
{
auto range = max - min;
return (range * (float(rand()) / RAND_MAX)) + min;
}
/*! Random Binomial Float */
inline float randomBinomial(float max = 1.f)
{ return randomFloat(max) - randomFloat(max); }
/*! Linear Interpolation */
/*inline float Lerp(float v0, float v1, float t)
{ return (1 - t) * v0 + t * v1; }*/
template<typename T>
inline T Lerp(T v0, T v1, float t)
{ return (1 - t) * v0 + t * v1; }
/*! Smooth Step */
inline float smoothStep(float edge0, float edge1, float x)
{
// Scale, bias and saturate x to 0..1 range
x = Clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
// Evaluate polynomial
return x * x * (3 - 2 * x);
}
/*! Sign Function*/
template <typename T> int sign(T val)
{ return (T(0) < val) - (val < T(0)); }
}
#endif

View File

@@ -0,0 +1,158 @@
#include "stdafx.h"
#include <cmath>
#include <string>
#include <iostream>
#include "EMatrix2x3.h"
Matrix2x3::Matrix2x3(Elite::Vector2 dirX, Elite::Vector2 dirY, Elite::Vector2 orig)
: dirX{ dirX }, dirY{ dirY }, orig{ orig }
{}
Matrix2x3::Matrix2x3(float e1X, float e1Y, float e2X, float e2Y, float oX, float oY)
: Matrix2x3{ Elite::Vector2{e1X, e1Y}, Elite::Vector2{e2X, e2Y}, Elite::Vector2{oX, oY} }
{}
Elite::Vector2 Matrix2x3::Transform(const Elite::Vector2& vector) const
{
return Elite::Vector2{ vector.x * dirX + vector.y * dirY } + orig;
}
float Matrix2x3::Determinant() const
{
return dirX.x * dirY.y - dirX.y * dirY.x;
}
Matrix2x3 Matrix2x3::Inverse() const
{
//Calculate Determinant
float det = Determinant();
//1)calculate matrix of minors
//2)Use the alternating law of signs to produce the matrix of cofactors
//3)Transpose
//4)the inverse matrix is 1/Determinant * the resulting matrix
return Matrix2x3{
Elite::Vector2(+dirY.y, -dirX.y) / det,
Elite::Vector2(-dirY.x, +dirX.x) / det,
Elite::Vector2(dirY.x * orig.y - dirY.y * orig.x, -(dirX.x * orig.y - dirX.y * orig.x)) / det
};
}
bool Matrix2x3::Equals(const Matrix2x3& other, float epsilon ) const
{
return (dirX == other.dirX) &&
(dirY == other.dirY) &&
(orig == other.orig);
}
std::string Matrix2x3::ToString() const
{
return std::string( "Matrix2x3( x( ") +
std::to_string(dirX.x) + ", " + std::to_string( dirX.y )
+ " ), y( " + std::to_string( dirY.x ) + ", " + std::to_string( dirY.y )
+ " ), orig( " + std::to_string( orig.x ) + ", " + std::to_string( orig.y ) + " ) )";
}
void Matrix2x3::SetAsIdentity()
{
dirX = Elite::Vector2{1, 0};
dirY = Elite::Vector2{0, 1};
orig = Elite::Vector2{0, 0};
}
void Matrix2x3::SetAsRotate(float degrees)
{
float radians = degrees * 3.1415926535f / 180;
dirX = Elite::Vector2{ cos( radians ), sin( radians ) };
dirY = Elite::Vector2{ -sin( radians ), cos( radians ) };
orig = Elite::Vector2{ 0, 0 };
}
void Matrix2x3::SetAsTranslate(float tx, float ty)
{
dirX = Elite::Vector2{ 1, 0 };
dirY = Elite::Vector2{ 0, 1 };
orig = Elite::Vector2{ tx, ty };
}
void Matrix2x3::SetAsTranslate(Elite::Vector2 pt)
{
dirX = Elite::Vector2{ 1, 0 };
dirY = Elite::Vector2{ 0, 1 };
orig = Elite::Vector2{ pt.x, pt.y };
}
void Matrix2x3::SetAsScale(float scaleX, float scaleY)
{
dirX = Elite::Vector2{ scaleX, 0 };
dirY = Elite::Vector2{ 0, scaleY };
orig = Elite::Vector2{ 0, 0 };
}
void Matrix2x3::SetAsScale(float scale)
{
SetAsScale(scale, scale);
}
Matrix2x3 Matrix2x3::CreateRotationMatrix(float degrees)
{
float radians = degrees * 3.1415926535f / 180;
return Matrix2x3( Elite::Vector2{ cos( radians ), sin( radians ) }, Elite::Vector2{ -sin(radians), cos( radians ) }, Elite::Vector2{} );
}
Matrix2x3 Matrix2x3::CreateIdentityMatrix()
{
return Matrix2x3( Elite::Vector2{ 1, 0 }, Elite::Vector2{ 0, 1 }, Elite::Vector2{} );
}
Matrix2x3 Matrix2x3::CreateScalingMatrix(float scale)
{
return CreateScalingMatrix(scale, scale);
}
Matrix2x3 Matrix2x3::CreateScalingMatrix(Elite::Vector2 scaleVector)
{
return CreateScalingMatrix(scaleVector.x, scaleVector.y);
}
Matrix2x3 Matrix2x3::CreateScalingMatrix(float scaleX, float scaleY)
{
return Matrix2x3( Elite::Vector2{ scaleX, 0 }, Elite::Vector2{ 0, scaleY }, Elite::Vector2{} );
}
Matrix2x3 Matrix2x3::CreateTranslationMatrix(Elite::Vector2 origin)
{
return Matrix2x3( Elite::Vector2{ 1, 0 }, Elite::Vector2{ 0, 1 }, origin );
}
Matrix2x3 Matrix2x3::CreateTranslationMatrix(float tx, float ty)
{
return CreateTranslationMatrix( Elite::Vector2{ tx, ty } );
}
// Operator overloading functionality
bool operator==(const Matrix2x3& lhs, const Matrix2x3& rhs)
{
return lhs.Equals(rhs);
}
bool operator!=(const Matrix2x3& lhs, const Matrix2x3& rhs)
{
return !(lhs == rhs);
}
Matrix2x3 operator*(const Matrix2x3& lhs, const Matrix2x3& rhs)
{
return Matrix2x3{
Elite::Vector2{ rhs.dirX.x * lhs.dirX.x + rhs.dirX.y * lhs.dirY.x, rhs.dirX.x * lhs.dirX.y + rhs.dirX.y * lhs.dirY.y },
Elite::Vector2{ rhs.dirY.x * lhs.dirX.x + rhs.dirY.y * lhs.dirY.x, rhs.dirY.x * lhs.dirX.y + rhs.dirY.y * lhs.dirY.y },
Elite::Vector2{ rhs.orig.x * lhs.dirX.x + rhs.orig.y * lhs.dirY.x + lhs.orig.x, rhs.orig.x * lhs.dirX.y + rhs.orig.y * lhs.dirY.y + lhs.orig.y }
};
}
std::ostream& operator<<(std::ostream& os, const Matrix2x3& matrix )
{
os << matrix.ToString( );
return os;
}

View File

@@ -0,0 +1,93 @@
#pragma once
#include <vector>
struct Matrix2x3
{
// -------------------------
// Constructors
// -------------------------
// Default constructor results in a unity matrix
explicit Matrix2x3( Elite::Vector2 dirX = Elite::Vector2{ 1, 0 }, Elite::Vector2 dirY = Elite::Vector2{ 0, 1 }, Elite::Vector2 origTrans = Elite::Vector2{ 0, 0 } );
// Constructor, using floats, all required
explicit Matrix2x3( float e1X, float e1Y, float e2X, float e2Y, float oX, float oY );
// -------------------------
// General Methods
// -------------------------
// Elite::Vector2 vTransformed = mat.Transform(v);
Elite::Vector2 Transform( const Elite::Vector2& v ) const;
// Calculate the determinant
float Determinant( ) const;
// Calculate the inverse matrix
Matrix2x3 Inverse( ) const;
// Are two matrices equal within a threshold?
// mat1.Equals(mat2)
bool Equals( const Matrix2x3& other, float epsilon = 0.001f ) const;
// Creates a string containing a text representation of the values of the matrix
std::string ToString( ) const;
// Converts this matrix into a Identity matrix
void SetAsIdentity( );
// Converts this matrix into a Rotate matrix
void SetAsRotate( float degrees );
// Converts this matrix into a Translation matrix
void SetAsTranslate( float tx, float ty );
// Converts this matrix into a Translation matrix
void SetAsTranslate( Elite::Vector2 pt );
// Converts this matrix into a Scale matrix
void SetAsScale( float sx, float sy );
// Converts this matrix into a Scale matrix
void SetAsScale( float s );
// -------------------------------------------
// Static Matrix2x3 object creation methods
// -------------------------------------------
// Instantiate a rotation matrix:
// Matrix matRot = Matrix::Rotation(45.0f);
static Matrix2x3 CreateRotationMatrix( float degrees );
// Instantiate an identity matrix:
// Matrix2x3 matId = Matrix2x3::Identity();
static Matrix2x3 CreateIdentityMatrix( );
// Instantiate a scale matrix:
// Matrix matScale = Matrix::Scaling(2.0f);
static Matrix2x3 CreateScalingMatrix( float scale );
// Instantiate a scale matrix:
// Matrix matScale = Matrix::Scaling(2.0f,-3.0f);
static Matrix2x3 CreateScalingMatrix( float scaleX, float scaleY );
// Instantiate a scale matrix:
// Matrix matScale = Matrix::Scaling( Elite::Vector2(2.0f,-3.0f) );
static Matrix2x3 CreateScalingMatrix( Elite::Vector2 scaleVector );
// Instantiate a translation matrix:
// Matrix matTrans = Matrix::Translation( Elite::Vector2(2.0f,3.0f) );
static Matrix2x3 CreateTranslationMatrix( Elite::Vector2 origin );
// Instantiate a translation matrix:
// Matrix matTrans = Matrix::Translation(2.0f, 3.0f);
static Matrix2x3 CreateTranslationMatrix( float tx, float ty );
// -------------------------
// Datamembers
// -------------------------
Elite::Vector2 dirX; // The first matrix vector (the "x-axis"), 1st column
Elite::Vector2 dirY; // The second matrix vector (the "y-axis"), second column
Elite::Vector2 orig; // The origin of the coordinate matrix (the "translation"), third column
};
// -------------------------
// Operators
// -------------------------
// Are two matrices exactly equal?
// mat1 == mat2
bool operator==( const Matrix2x3& lhs, const Matrix2x3& rhs );
// Are two matrices exactly unequal?
// mat1 != mat2
bool operator!=( const Matrix2x3& lhs, const Matrix2x3& rhs );
// Multiply matrices
// Matrix2x3 matProduct {mat1 * mat2};
Matrix2x3 operator*( const Matrix2x3& lhs, const Matrix2x3& rhs );
// Send matrix to output stream
// std::cout << mat;
std::ostream& operator<<( std::ostream& os, const Matrix2x3& matrix );

237
inc/EliteMath/EVector2.h Normal file
View File

@@ -0,0 +1,237 @@
/*=============================================================================*/
// Copyright 2021-2022 Elite Engine
// Authors: Matthieu Delaere
/*=============================================================================*/
// EVector2.h: Vector2D struct
/*=============================================================================*/
#ifndef ELITE_MATH_VECTOR2
#define ELITE_MATH_VECTOR2
namespace Elite
{
#define ZeroVector2 Vector2()
#define UnitVector2 Vector2(1.f,1.f)
//Vector 2D
struct Vector2
{
//=== Datamembers ===
float x = 0.0f;
float y = 0.0f;
//=== Constructors ===
Vector2() = default;
Vector2(float _x, float _y) :x(_x), y(_y) {};
//=== Vector Conversions Functions ===
#ifdef USE_BOX2D
explicit Vector2(const b2Vec2& v) : x(v.x), y(v.y) {};
Vector2& operator=(const b2Vec2& v) { x = v.x; y = v.y; return *this; }
operator b2Vec2() const
{return {x, y};};
#endif
//=== Arithmetic Operators ===
inline auto operator-(const Vector2& v) const
{ return Vector2(x - v.x, y - v.y); }
inline auto operator-() const
{ return Vector2(-x, -y); }
inline auto operator*(float scale) const
{ return Vector2(x * scale, y * scale); }
inline auto operator/(float scale) const
{
const auto revScale = 1.0f / scale;
return Vector2(x * revScale, y * revScale);
}
//=== Compound Assignment Operators === //auto& for type deduction
inline auto& operator+=(const Vector2& v)
{ x += v.x; y += v.y; return *this; }
inline auto& operator-=(const Vector2& v)
{ x -= v.x; y -= v.y; return *this; }
inline auto& operator*=(float scale)
{ x *= scale; y *= scale; return *this; }
inline auto& operator/=(float scale)
{
const auto revScale = 1.0f / scale;
x *= revScale; y *= revScale; return *this;
}
//=== Relational Operators ===
inline auto operator==(const Vector2& v) const /*Check if both components are equal*/
{ return AreEqual(x, v.x) && AreEqual(y, v.y); }
inline auto operator!=(const Vector2& v) const /*Check if one or both components are NOT equal*/
{ return !(*this == v); }
//=== Member Access Operators ===
inline float operator[](unsigned int i) const
{
return ((i == 0) ? x : y);
//if (i >= 0 && i < 2)
// return ((i == 0) ? x : y);
//throw; /*TODO : specify error thrown;*/
}
inline float& operator[](unsigned int i)
{
return ((i == 0) ? x : y);
//if (i >= 0 && i < 2)
// return ((i == 0) ? x : y);
//throw; /*TODO : specify error thrown;*/
}
//=== Internal Vector Functions ===
inline auto Dot(const Vector2& v) const
{ return x * v.x + y * v.y; }
inline auto Cross(const Vector2& v) const
{ return x * v.y - y * v.x; }
inline auto GetAbs() const
{ return Vector2(abs(x), abs(y)); }
inline auto MagnitudeSquared() const
{ return x*x + y*y; }
inline auto Magnitude() const
{ return sqrtf(MagnitudeSquared()); }
inline float Normalize()
{
auto m = Magnitude();
if (AreEqual(m, 0.f))
{
*this = ZeroVector2;
return 0.f;
}
auto invM = 1.f / m;
x *= invM;
y *= invM;
return m;
}
inline Vector2 GetNormalized() const /*! Returns a normalized copy of this vector. This vector does not change.*/
{
auto v = Vector2(*this);
v.Normalize();
return v;
}
inline auto DistanceSquared(const Vector2& v) const
{ return Square(v.x - x) + Square(v.y - y); }
inline auto Distance(const Vector2& v) const
{ return sqrtf(DistanceSquared(v)); }
inline auto Clamp(float max)
{
auto scale = max / Magnitude();
scale = scale < 1.f ? scale : 1.f;
return *this * scale;
}
};
//=== Global Vector Operators ===
#pragma region GlobalVectorOperators
inline auto operator+(const Vector2& v, const Vector2& v2)
{ return Vector2(v.x + v2.x, v.y + v2.y); }
inline auto operator* (float s, const Vector2& v)
{ return Vector2(s * v.x, s * v.y); }
inline auto operator*(const Vector2& a, const Vector2& b)
{ return Vector2(a.x*b.x, a.y*b.y); }
inline auto operator/ (float s, const Vector2& v)
{
const auto revScale = 1.0f / s;
return Vector2(revScale * v.x, revScale * v.y);
}
inline std::ostream& operator<<(std::ostream& os, const Vector2& rhs)
{
os << "(" << rhs.x << ", " << rhs.y << " )";
return os;
}
#pragma endregion //GlobalVectorOperators
//=== Global Vector Functions ===
#pragma region GlobalVectorFunctions
inline auto Dot(const Vector2& v1, const Vector2& v2)
{ return v1.Dot(v2); }
inline auto Cross(const Vector2& v1, const Vector2& v2)
{ return v1.Cross(v2); }
inline auto GetAbs(const Vector2& v)
{ return v.GetAbs(); }
inline void Abs(Vector2& v) /*! Make absolute Vector2 of this Vector2 */
{ v = v.GetAbs(); }
inline void Normalize(Vector2& v)
{ v.Normalize(); }
inline auto GetNormalized(const Vector2& v)
{ return v.GetNormalized(); }
inline auto DistanceSquared(const Vector2& v1, const Vector2& v2)
{ return v1.DistanceSquared(v2); }
inline auto Distance(const Vector2& v1, const Vector2& v2)
{ return v1.Distance(v2); }
inline auto Clamp(const Vector2& v, float max)
{
auto scale = max / v.Magnitude();
scale = scale < 1.f ? scale : 1.f;
return v * scale;
}
#pragma endregion //GlobalVectorFunctions
#pragma region ExtraFunctions
/*! Random Vector2 */
inline Vector2 randomVector2(float max = 1.f)
{
return{ randomBinomial(max),randomBinomial(max) };
}
inline Vector2 randomVector2(float min, float max)
{
return{ randomFloat(min, max),randomFloat(min, max) };
}
/* Get orientation from an a velocity vector
-- [Deprecated] -- Use VectorToAngle instead*/
[[deprecated("Use VectorToOrientation instead")]]
inline float GetOrientationFromVelocity(const Elite::Vector2& velocity)
{
if (velocity.Magnitude() == 0)
return 0.f;
return atan2f(velocity.x, -velocity.y);
}
/* Creates a normalized vector from an angle in radians. */
inline Vector2 OrientationToVector(float orientation)
{
return Vector2(cos(orientation), sin(orientation));
}
/*Calculates the orientation angle from a vector*/
inline float VectorToOrientation(const Vector2& vector)
{
return atan2f(vector.y, vector.x);
}
/*! Get Angle Between 2 vectors*/
inline float AngleBetween(const Elite::Vector2& v1, const Elite::Vector2& v2) {
float x = v1.Dot(v2);
float y = v1.Cross(v2);
return atan2(y, x);
}
#pragma endregion //ExtraFunctions
}
#endif

170
inc/EliteMath/EVector3.h Normal file
View File

@@ -0,0 +1,170 @@
/*=============================================================================*/
// Copyright 2021-2022 Elite Engine
// Authors: Matthieu Delaere
/*=============================================================================*/
// EVector2.h: Vector3D struct
/*=============================================================================*/
#ifndef ELITE_MATH_VECTOR3
#define ELITE_MATH_VECTOR3
namespace Elite {
#define ZeroVector3 Vector3()
#define UnitVector3 Vector3(1.f,1.f,1.f)
//Vector 3D
struct Vector3
{
//=== Datamembers ===
float x = 0.0f;
float y = 0.0f;
float z = 0.0f;
//=== Constructors ===
Vector3(){};
Vector3(float _x, float _y, float _z):x(_x), y(_y), z(_z) {};
explicit Vector3(const Vector2 v, float _z = 0.f):x(v.x), y(v.y), z(_z) {};
//Vector3(const Vector3& other); //Copy Constructor
//Vector3& operator=(const Vector3& other); //Copy Assignment Operator
//=== Vector Conversions Functions ===
#ifdef USE_BOX2D
explicit Vector3(const b2Vec3& v) : x(v.x), y(v.y), z(v.z) {};
Vector3& operator=(const b2Vec3& v) { x = v.x; y = v.y; z = v.z; return *this; }
explicit operator b2Vec3() const
{ return b2Vec3(x, y, z); };
#endif
//=== Arithmetic Operators ===
inline auto operator+(const Vector3& v) const
{ return Vector3(x + v.x, y + v.y, z + v.z); }
inline auto operator-(const Vector3& v) const
{ return Vector3(x - v.x, y - v.y, z - v.z); }
inline auto operator*(float scale) const
{ return Vector3(x * scale, y * scale, z * scale); }
inline auto operator/(float scale) const
{
const auto revScale = 1.0f / scale;
return Vector3(x * revScale, y * revScale, z * revScale);
}
//=== Compound Assignment Operators === //auto& for type deduction
inline auto& operator+=(const Vector3& v)
{ x += v.x; y += v.y; z += v.z; return *this; }
inline auto& operator-=(const Vector3& v)
{ x -= v.x; y -= v.y; z -= v.z; return *this; }
inline auto& operator*=(float scale)
{ x *= scale; y *= scale; z *= scale; return *this; }
inline auto& operator/=(float scale)
{
const auto revScale = 1.0f / scale;
x *= revScale; y *= revScale; z *= revScale; return *this;
}
//=== Relational Operators ===
inline auto operator==(const Vector3& v) const /*Check if both components are equal*/
{ return AreEqual(x, v.x) && AreEqual(y, v.y) && AreEqual(z, v.z); }
inline auto operator!=(const Vector3& v) const /*Check if one or both components are NOT equal*/
{ return !(*this == v); }
//=== Member Access Operators ===
inline float operator[](unsigned int i) const
{ return ((i == 0) ? x : y); }
inline float& operator[](unsigned int i)
{ return ((i == 0) ? x : y); }
//=== Internal Vector Functions ===
inline auto Dot(const Vector3& v) const
{ return x * v.x + y * v.y + z * v.z; }
inline auto Cross(const Vector3& v) const
{
return Vector3(
y * v.z - z * v.y,
z * v.x - x * v.z,
x * v.y - y * v.x);
}
inline auto GetAbs() const
{ return Vector3(abs(x), abs(y), abs(z)); }
inline auto SqrtMagnitude() const
{ return x*x + y*y + z*z; }
inline auto Magnitude() const
{ return sqrtf(SqrtMagnitude()); }
inline void Normalize()
{
auto m = Magnitude();
if (AreEqual(m, 0.f))
{
*this = ZeroVector3;
return;
}
auto invM = 1.f / m;
x *= invM;
y *= invM;
z *= invM;
}
inline Vector3 GetNormalized() const /*! Returns a normalized copy of this vector. This vector does not change.*/
{
auto v = Vector3(*this);
v.Normalize();
return v;
}
inline auto DistanceSquared(const Vector3& v) const
{ return Square(v.x - x) + Square(v.y - y) + Square(v.z - z); }
inline auto Distance(const Vector3& v) const
{ return sqrtf(DistanceSquared(v)); }
inline auto Project(const Vector3& v) const
{ return v * ((*this).Dot(v) / v.Dot(v)); }
inline auto Reject(const Vector3& v) const
{ return *this - (*this).Project(v);}
};
//=== Global Vector Operators ===
#pragma region GlobalVectorOperators
inline auto operator * (float s, const Vector3& v)
{ return Vector3(s * v.x, s * v.y, s * v.z); }
#pragma endregion //GlobalVectorOperators
//=== Global Vector Functions ===
#pragma region GlobalVectorFunctions
inline auto Dot(const Vector3& v1, const Vector3& v2)
{ return v1.Dot(v2); }
inline auto Cross(const Vector3& v1, const Vector3& v2)
{ return v1.Cross(v2); }
inline auto GetAbs(const Vector3& v)
{ return v.GetAbs(); }
inline void Abs(Vector3& v) /*! Make absolute Vector3 of this Vector3 */
{ v = v.GetAbs(); }
inline void Normalize(Vector3& v)
{ v.Normalize(); }
inline auto GetNormalized(Vector3& v)
{ return v.GetNormalized(); }
inline auto DistanceSquared(const Vector3& v1, const Vector3& v2)
{ return v1.DistanceSquared(v2); }
inline auto Distance(const Vector3& v1, const Vector3& v2)
{ return v1.Distance(v2); }
inline auto Project(const Vector3& v1, const Vector3& v2)
{ return v1.Project(v2); }
inline auto Reject(const Vector3& v1, const Vector3& v2)
{ return v1.Reject(v2); }
#pragma endregion //GlobalVectorFunctions
}
#endif

267
inc/EliteMath/FMatrix.h Normal file
View File

@@ -0,0 +1,267 @@
/*=============================================================================*/
// Copyright 2021-2022 Elite Engine
// Authors: Koen Samyn
/*=============================================================================*/
// FMatrix.cpp: FMatrix class
/*=============================================================================*/
#ifndef ELITE_MATH_FMATRIX
#define ELITE_MATH_FMATRIX
#include <random>
namespace Elite
{
class FMatrix
{
public:
FMatrix(): m_Data(nullptr), m_Rows(0), m_Columns(0), m_Size(0) {}
FMatrix(int rows, int columns):
m_Rows(rows),
m_Columns(columns),
m_Data(new float[rows * columns]),
m_Size(rows * columns)
{}
virtual ~FMatrix()
{
delete[] m_Data;
m_Data = nullptr;
}
void Resize(int nrOfRows, int nrOfColumns)
{
m_Rows = nrOfRows;
m_Columns = nrOfColumns;
m_Size = m_Rows * m_Columns;
delete[] m_Data; //ATTENTION: DELETES OLD DATA IN MATRIX
m_Data = new float[m_Size];
}
void Set(int row, int column, float value)
{
int index = RcToIndex(row, column);
if (index > -1 && index < m_Size)
{
m_Data[index] = value;
}
else
{
printf("Wrong index! [%d, %d]\n", row, column);
}
}
void SetAll(float value)
{
for (int i = 0; i < m_Size; ++i)
{
m_Data[i] = value;
}
}
void SetRowAll(int row, float value)
{
for (int c = 0; c < m_Columns; ++c)
{
Set(row, c, value);
}
}
void Randomize(float min, float max)
{
for (int i = 0; i < m_Size; ++i)
{
float r = min + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (max - min)));
m_Data[i] = r;
}
}
void Add(int row, int column, float toAdd)
{
int index = RcToIndex(row, column);
if (index > -1 && index < m_Size) {
m_Data[index] += toAdd;
}
else {
printf("Wrong index! [%d, %d]\n", row, column);
}
}
void Add(const FMatrix& other)
{
int maxRows = min(GetNrOfRows(), other.GetNrOfRows());
int maxColumns = min(GetNrOfColumns(), other.GetNrOfColumns());
for (int c_row = 0; c_row < maxRows; ++c_row) {
for (int c_column = 0; c_column < maxColumns; ++c_column) {
float oVal = other.Get(c_row, c_column);
float thisVal = Get(c_row, c_column);
Set(c_row, c_column, thisVal + oVal);
}
}
}
float Get(int row, int column) const
{
int index = RcToIndex(row, column);
if (index > -1 && index < m_Size) {
return m_Data[index];
}
else {
return -1;
}
}
int GetNrOfRows() const
{
return m_Rows;
}
int GetNrOfColumns() const
{
return m_Columns;
}
void MatrixMultiply(const FMatrix& op2, FMatrix& result)
{
int maxRows = min(GetNrOfRows(), result.GetNrOfRows());
int maxColumns = min(op2.GetNrOfColumns(), result.GetNrOfColumns());
for (int c_row = 0; c_row < maxRows; ++c_row)
{
for (int c_column = 0; c_column < maxColumns; ++c_column)
{
float sum = 0;
for (int index = 0; index < GetNrOfColumns(); ++index)
{
sum += Get(c_row, index) * op2.Get(index, c_column);
}
result.Set(c_row, c_column, sum);
}
}
}
void ScalarMultiply(float scalar)
{
for (int i = 0; i < m_Size; ++i)
{
m_Data[i] *= scalar;
}
}
void Copy(const FMatrix& other)
{
int maxRows = min(GetNrOfRows(), other.GetNrOfRows());
int maxColumns = min(GetNrOfColumns(), other.GetNrOfColumns());
for (int c_row = 0; c_row < maxRows; ++c_row) {
for (int c_column = 0; c_column < maxColumns; ++c_column) {
float oVal = other.Get(c_row, c_column);
Set(c_row, c_column, oVal);
}
}
}
void Subtract(const FMatrix& other)
{
int maxRows = min(GetNrOfRows(), other.GetNrOfRows());
int maxColumns = min(GetNrOfColumns(), other.GetNrOfColumns());
for (int c_row = 0; c_row < maxRows; ++c_row)
{
for (int c_column = 0; c_column < maxColumns; ++c_column)
{
float oVal = other.Get(c_row, c_column);
float thisVal = Get(c_row, c_column);
Set(c_row, c_column, thisVal - oVal);
}
}
}
void Sigmoid()
{
for (int i = 0; i < m_Size; ++i)
{
float val = m_Data[i];
m_Data[i] = 1 / (1 + exp(-val));
}
}
float Sum() const
{
float sum = 0;
for (int i = 0; i < m_Size; ++i)
{
sum += m_Data[i];
}
return sum;
}
float Dot(const FMatrix& op2) const
{
int mR = min(GetNrOfRows(), op2.GetNrOfRows());
int mC = min(GetNrOfColumns(), op2.GetNrOfColumns());
float dot = 0;
for (int c_row = 0; c_row < mR; ++c_row) {
for (int c_column = 0; c_column < mC; ++c_column) {
float v1 = Get(c_row, c_column);
float v2 = Get(c_row, c_column);
dot += v1 * v2;
}
}
return dot;
}
float Max() const
{
float max = -FLT_MAX;
for (int c_row = 0; c_row < m_Rows; ++c_row) {
for (int c_column = 0; c_column < m_Columns; ++c_column) {
float value = Get(c_row, c_column);
if (value > max) {
max = value;
}
}
}
return max;
}
float Max(int r, int c) const
{
float max = -FLT_MAX;
for (int c_row = 0; c_row < m_Rows; ++c_row) {
for (int c_column = 0; c_column < m_Columns; ++c_column) {
float value = Get(c_row, c_column);
if (value > max) {
max = value;
r = c_row;
c = c_column;
}
}
}
return max;
}
float MaxOfRow(int r) const
{
float max = -FLT_MAX;
for (int c_column = 0; c_column < m_Columns; ++c_column) {
float value = Get(r, c_column);
if (value > max) {
max = value;
}
}
return max;
}
void Print() const
{
for (int c_row = 0; c_row < m_Rows; ++c_row) {
for (int c_column = 0; c_column < m_Columns; ++c_column) {
float value = Get(c_row, c_column);
printf("%.3f\t", value);
}
printf("\n");
}
}
private:
float* m_Data;
int m_Rows, m_Columns;
int m_Size;
int RcToIndex(int r, int c) const
{
return c * m_Rows + r;
}
};
}
#endif