Adding code

This commit is contained in:
2023-12-26 13:24:13 -06:00
parent d456d05c3d
commit d9bd070fd1
40 changed files with 1610 additions and 1656 deletions

View File

@@ -9,6 +9,8 @@ if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
message(FATAL_ERROR "In-source builds are not allowed")
endif()
set(CMAKE_CXX_STANDARD 20)
#set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if (WIN32)
@@ -19,7 +21,10 @@ endif(WIN32)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# Enable Package Managers
#include(cmake/CPM.cmake)
include(cmake/CPM.cmake)
#include(cmake/gtest.cmake)
include(CTest)
file(GLOB_RECURSE J3ML_HEADERS "include/J3ML/*.h" "include/J3ML/*.hpp")
file(GLOB_RECURSE J3ML_SRC "src/J3ML/*.c" "src/J3ML/*.cpp")
@@ -28,3 +33,12 @@ include_directories("include")
add_library(J3ML SHARED ${J3ML_SRC})
set_target_properties(J3ML PROPERTIES LINKER_LANGUAGE CXX)
install(TARGETS ${PROJECT_NAME} DESTINATION lib/${PROJECT_NAME})
install(FILES ${J3ML_HEADERS} DESTINATION include/${PROJECT_NAME})
add_subdirectory(tests)
add_executable(MathDemo main.cpp)
target_link_libraries(MathDemo ${PROJECT_NAME})

24
cmake/CPM.cmake Normal file
View File

@@ -0,0 +1,24 @@
# SPDX-License-Identifier: MIT
#
# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors
set(CPM_DOWNLOAD_VERSION 0.38.7)
set(CPM_HASH_SUM "83e5eb71b2bbb8b1f2ad38f1950287a057624e385c238f6087f94cdfc44af9c5")
if(CPM_SOURCE_CACHE)
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
elseif(DEFINED ENV{CPM_SOURCE_CACHE})
set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
else()
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
endif()
# Expand relative path. This is important if the provided path contains a tilde (~)
get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE)
file(DOWNLOAD
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM}
)
include(${CPM_DOWNLOAD_LOCATION})

68
cmake/gtest.cmake Normal file
View File

@@ -0,0 +1,68 @@
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
#-----------------------------------------------------------------------
# CPM configuration
#-----------------------------------------------------------------------
set(CPM_MODULE_NAME google_test)
set(CPM_LIB_TARGET_NAME ${CPM_MODULE_NAME})
if ((DEFINED CPM_DIR) AND (DEFINED CPM_UNIQUE_ID) AND (DEFINED CPM_TARGET_NAME))
set(CPM_LIB_TARGET_NAME ${CPM_TARGET_NAME})
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CPM_DIR})
include(CPM)
else()
set(CPM_DIR "${CMAKE_CURRENT_BINARY_DIR}/cpm-packages" CACHE TYPE STRING)
find_package(Git)
if(NOT GIT_FOUND)
message(FATAL_ERROR "CPM requires Git.")
endif()
if (NOT EXISTS ${CPM_DIR}/CPM.cmake)
execute_process(
COMMAND "${GIT_EXECUTABLE}" clone https://github.com/iauns/cpm ${CPM_DIR}
RESULT_VARIABLE error_code
OUTPUT_VARIABLE head_sha)
if(error_code)
message(FATAL_ERROR "CPM failed to get the hash for HEAD")
endif()
endif()
include(${CPM_DIR}/CPM.cmake)
endif()
# All externals *must* define this.
CPM_ForceOnlyOneModuleVersion()
CPM_InitModule(${CPM_MODULE_NAME})
#------------------------------------------------------------------------------
# Google Test
#------------------------------------------------------------------------------
# Google test as an external project is a bad idea! You really should add it
# as a subdirectory so that it can capture your compiler flags
set(GOOGLE_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdParty/gtest)
CPM_EnsureRepoIsCurrent(
TARGET_DIR ${GOOGLE_TEST_DIR}
SVN_REPOSITORY "http://googletest.googlecode.com/svn/trunk"
SVN_REVISION "664"
USE_CACHING TRUE
)
# Compiler flags for MSVC 2010
if (MSVC_VERSION EQUAL 1600)
add_definitions(-DGTEST_USE_OWN_TR1_TUPLE=0)
CPM_ExportAdditionalDefinition("-DGTEST_USE_OWN_TR1_TUPLE=0")
endif()
# Compiler flags for MSVC 2012
if(MSVC_VERSION EQUAL 1700)
add_definitions(-D_VARIADIC_MAX=10)
endif()
# For All versions of gtest, we force shared CRT.
set(gtest_force_shared_crt ON)
set(gtest_force_shared_crt ON)
# Add gtest now that we have the appropriate flags set.
add_subdirectory(${GOOGLE_TEST_DIR})
CPM_ExportAdditionalIncludeDir("${GOOGLE_TEST_DIR}/include")
CPM_ExportAdditionalLibraryTarget("gtest")

View File

@@ -1,8 +0,0 @@
//
// Created by josh on 12/25/2023.
//
#ifndef J3ML_AXISANGLE_H
#define J3ML_AXISANGLE_H
#endif //J3ML_AXISANGLE_H

View File

@@ -1,8 +0,0 @@
//
// Created by josh on 12/25/2023.
//
#ifndef J3ML_EULERANGLE_H
#define J3ML_EULERANGLE_H
#endif //J3ML_EULERANGLE_H

66
include/J3ML/Geometry.h Normal file
View File

@@ -0,0 +1,66 @@
#include <J3ML/LinearAlgebra/Vector3.h>
#pragma once
namespace Geometry {
using Point2D = LinearAlgebra::Vector2;
class LineSegment2D
{
Point2D A;
Point2D B;
};
class Rectangle; //AABB2D;
class OBB2D;
class Line2D;
class Ray2D;
class Triangle2D;
class Polygon2D;
struct IntersectionResult2D {
};
bool Intersects2D(LineSegment2D seg, Rectangle rect);
IntersectionResult2D GetIntersection2D(LineSegment2D seg, Rectangle rect);
using Point3D = LinearAlgebra::Vector3;
// A 3D axis-aligned bounding box
// This data structure can be used to represent coarse bounds of objects, in situations where detailed triangle-level
// computations can be avoided. In physics systems, bounding boxes are used as an efficient early-out test for geometry
// intersection queries.
// the 'Axis-aligned' part in the name means that the local axes of this bounding box are restricted to align with the
// axes of the world space coordinate system. This makes computation involving AABB's very fast, since AABB's cannot
// be arbitrarily oriented in the space with respect to each other.
// If you need to represent a box in 3D space with arbitrary orientation, see the class OBB. */
class AABB;
class Capsule;
class Line;
class LineSegment
{
Point3D A;
Point3D B;
};
class Ray
{
Point3D Origin;
Point3D Direction;
};
class OBB;
class Frustum;
class Plane;
class Polygon;
class Polyhedron;
class QuadTree;
class OctTree;
class Sphere;
class Triangle;
class TriangleMesh;
}

View File

@@ -5,11 +5,35 @@
#include <algorithm>
#include <functional>
// TODO: Make GLM redundant, and remove it thereafter.
#include <glm/glm.hpp>
#include <glm/ext/scalar_constants.hpp>
// TODO: SIMD operations for fast math (parallelization!!)
namespace Math
{
const float Pi = M_PI;
inline float Radians(float degrees) { return degrees * (Pi/180.f); }
inline float Degrees(float radians) { return radians * (180.f/Pi); }
struct NumberRange
{
float LowerBound;
float UpperBound;
};
float NormalizeToRange(float input, float fromLower, float fromUpper, float toLower, float toUpper);
float NormalizeToRange(float input, const NumberRange& from, const NumberRange& to)
{
}
// auto rotation_normalized = NormalizeToRange(inp, {0, 360}, {-1, 1});
inline float Lerp(float a, float b, float t);
}
// Dawsh Linear Algebra Library - Everything you need for 3D math
namespace LinearAlgebra {
class Vector2; // A type representing a position in a 2-dimensional coordinate space.
@@ -25,7 +49,9 @@ namespace LinearAlgebra {
class Transform2D;
class Transform3D;
class Quaternion;
inline float lerp(float a, float b, float t);
using Position = Vector3;
}
// TODO: Enforce Style Consistency (Function Names use MicroSoft Case)
@@ -48,607 +74,9 @@ namespace LinearAlgebra {
namespace LinearAlgebra
{
class Vector2 {
public:
Vector2();
// Constructs a new Vector2 with the value (X, Y)
Vector2(float X, float Y);
Vector2(const Vector2& rhs); // Copy Constructor
Vector2(Vector2&&) = default; // Move Constructor
float GetX() const { return x; }
float GetY() const { return y; }
#if MUTABLE
void SetX(float newX) { x = newX;}
void SetY(float newY) { y = newY; }
#endif
static const Vector2 Zero;
static const Vector2 Up;
static const Vector2 Left;
static const Vector2 Down;
static const Vector2 Right;
float operator[](std::size_t index);
bool IsWithinMarginOfError(const Vector2& rhs, float margin=0.001f) const;
bool operator == (const Vector2& rhs) const;
bool operator != (const Vector2& rhs) const;
Vector2 Min(const Vector2& min) const;
static Vector2 Min(const Vector2& value, const Vector2& minimum) { return value.Min(minimum); }
Vector2 Max(const Vector2& max) const;
static Vector2 Max(const Vector2& value, const Vector2& maximum) { return value.Max(maximum);}
Vector2 Clamp(const Vector2& min, const Vector2& max) const;
static Vector2 Clamp(const Vector2& min, const Vector2& middle, const Vector2& max);
// Returns the magnitude between the two vectors.
float Distance(const Vector2& to) const;
static float Distance(const Vector2& from, const Vector2& to);
float Length() const;
static float Length(const Vector2& of) { return of.Length(); }
float LengthSquared() const;
static float LengthSquared(const Vector2& of) { return of.LengthSquared(); }
// Returns the length of the vector, which is sqrt(x^2 + y^2)
float Magnitude() const;
static float Magnitude(const Vector2& of) { return of.Magnitude();}
// Returns a float value equal to the magnitudes of the two vectors multiplied together and then multiplied by the cosine of the angle between them.
// For normalized vectors, dot returns 1 if they point in exactly the same direction,
// -1 if they point in completely opposite directions, and 0 if the vectors are perpendicular.
float Dot(const Vector2& rhs) const;
static float Dot(const Vector2& lhs, const Vector2& rhs) { return lhs.Dot(rhs); }
// Projects one vector onto another and returns the result. (IDK)
Vector2 Project(const Vector2& rhs) const;
// @see Project
static Vector2 Project(const Vector2& lhs, const Vector2& rhs) { return lhs.Project(rhs); }
// Returns a copy of this vector, resized to have a magnitude of 1, while preserving "direction"
Vector2 Normalize() const;
static Vector2 Normalize(const Vector2& of) { return of.Normalize(); }
// Linearly interpolates between two points.
// Interpolates between the points and b by the interpolant t.
// The parameter is (TODO: SHOULD BE!) clamped to the range[0, 1].
// This is most commonly used to find a point some fraction of the wy along a line between two endpoints (eg. to move an object gradually between those points).
Vector2 Lerp(const Vector2& rhs, float alpha) const;
// @see Lerp
static Vector2 Lerp(const Vector2& lhs, const Vector2& rhs, float alpha) { return lhs.Lerp(rhs, alpha); }
float AngleBetween(const Vector2& rhs) const;
static float AngleBetween(const Vector2& lhs, const Vector2& rhs);
// Adds two vectors.
Vector2 operator +(const Vector2& rhs) const;
Vector2 Add(const Vector2& rhs) const;
static Vector2 Add(const Vector2& lhs, const Vector2& rhs);
// Subtracts two vectors.
Vector2 operator -(const Vector2& rhs) const;
Vector2 Sub(const Vector2& rhs) const;
static Vector2 Sub(const Vector2& lhs, const Vector2& rhs);
// Multiplies this vector by a scalar value.
Vector2 operator *(float rhs) const;
Vector2 Mul(float scalar) const;
static Vector2 Mul(const Vector2& lhs, float rhs);
// Divides this vector by a scalar.
Vector2 operator /(float rhs) const;
Vector2 Div(float scalar) const;
static Vector2 Div(const Vector2& lhs, float rhs);
// Unary operator +
Vector2 operator +() const; // TODO: Implement
Vector2 operator -() const;
// Assigns a vector to another
Vector2& operator=(const Vector2&v);
Vector2& operator+=(const Vector2& rhs); // Adds a vector to this vector, in-place.
Vector2& operator-=(const Vector2& rhs); // Subtracts a vector from this vector, in-place
Vector2& operator*=(float scalar);
Vector2& operator/=(float scalar);
public:
#if MUTABLE
float x = 0;
float y = 0;
#else
const float x = 0;
const float y = 0;
#endif
};
class Vector3 {
public:
Vector3();
Vector3(float X, float Y, float Z);
Vector3(const Vector3& rhs);
Vector3(Vector3&&) = default;
Vector3& operator=(const Vector3& rhs);
float getX() const;
float getY() const;
float getZ() const;
#if MUTABLE
void setX(float newX);
void setY(float newY);
void setZ(float newZ);
#endif
static const Vector3 Zero;
static const Vector3 Up;
static const Vector3 Down;
static const Vector3 Left;
static const Vector3 Right;
static const Vector3 Forward;
static const Vector3 Backward;
float operator[](std::size_t index) const;
bool IsWithinMarginOfError(const Vector3& rhs, float margin=0.001f) const;
bool IsNormalized(float epsilonSq = 1e-5f) const;
bool IsZero(float epsilonSq = 1e-6f) const;
bool IsFinite() const;
bool IsPerpendicular(const Vector2& other, float epsilonSq=1e-5f) const;
bool operator == (const Vector3& rhs) const;
bool operator != (const Vector3& rhs) const;
Vector3 Min(const Vector3& min) const;
static Vector3 Min(const Vector3& lhs, const Vector3& rhs);
Vector3 Max(const Vector3& max) const;
static Vector3 Max(const Vector3& lhs, const Vector3& rhs);
Vector3 Clamp(const Vector3& min, const Vector3& max) const;
static Vector3 Clamp(const Vector3& min, const Vector3& input, const Vector3& max);
float Distance(const Vector3& to) const;
static float Distance(const Vector3& from, const Vector3& to);
float Length() const;
static float Length(const Vector3& of);
float LengthSquared() const;
static float LengthSquared(const Vector3& of);
// Returns the length of the vector, which is sqrt(x^2 + y^2 + z^2)
float Magnitude() const;
static float Magnitude(const Vector3& of);
// Returns a float value equal to the magnitudes of the two vectors multiplied together and then multiplied by the cosine of the angle between them.
// For normalized vectors, dot returns 1 if they point in exactly the same direction,
// -1 if they point in completely opposite directions, and 0 if the vectors are perpendicular.
float Dot(const Vector3& rhs) const;
static float Dot(const Vector3& lhs, const Vector3& rhs);
Vector3 Project(const Vector3& rhs) const;
static Vector3 Project(const Vector3& lhs, const Vector3& rhs);
// The cross product of two vectors results in a third vector which is perpendicular to the two input vectors.
// The result's magnitude is equal to the magnitudes of the two inputs multiplied together and then multiplied by the sine of the angle between the inputs.
Vector3 Cross(const Vector3& rhs) const;
static Vector3 Cross(const Vector3& lhs, const Vector3& rhs);
// Returns a copy of this vector, resized to have a magnitude of 1, while preserving "direction"
Vector3 Normalize() const;
static Vector3 Normalize(const Vector3& targ);
// Linearly interpolates between two points.
// Interpolates between the points and b by the interpolant t.
// The parameter is (TODO: SHOULD BE!) clamped to the range[0, 1].
// This is most commonly used to find a point some fraction of the wy along a line between two endpoints (eg. to move an object gradually between those points).
Vector3 Lerp(const Vector3& goal, float alpha) const;
Vector3 operator+(const Vector3& rhs) const;
Vector3 operator-(const Vector3& rhs) const;
Vector3 operator*(float rhs) const;
Vector3 operator/(float rhs) const;
Vector3 operator+() const; // TODO: Implement
Vector3 operator-() const;
public:
#if MUTABLE
float x = 0;
float y = 0;
float z = 0;
#else
const float x = 0;
const float y = 0;
const float z = 0;
#endif
};
class Vector4 {
public:
Vector4();
Vector4(const Vector3& xyz, float w = 0);
Vector4(float X, float Y, float Z, float W);
Vector4(const Vector4& copy) = default;
Vector4(Vector4&& move) = default;
float getX() const;
float getY() const;
float getZ() const;
float getW() const;
#if MUTABLE
void setX(float newX);
void setY(float newY);
void setZ(float newZ);
void setW(float newW);
#endif
float operator[](int index) const;
bool IsWithinMarginOfError(const Vector4& rhs, float margin=0.0001f) const;
bool operator==(const Vector4& rhs) const;
bool operator!=(const Vector4& rhs) const;
Vector4 min(const Vector4& min) const;
Vector4 max(const Vector4& max) const;
Vector4 clamp(const Vector4& min, const Vector4& max) const;
float distance(const Vector4& to) const;
float length() const;
float lengthSquared() const;
float magnitude() const;
float dot(const Vector4& rhs) const;
Vector4 project(const Vector4& rhs) const;
// While it is feasable to compute a cross-product in four dimensions
// the cross product only has the orthogonality property in 3 and 7 dimensions
// You should consider instead looking at Gram-Schmidt Orthogonalization
// to find orthonormal vectors.
Vector4 cross(const Vector4& rhs) const;
Vector4 normalize() const;
Vector4 lerp(const Vector4& goal, float alpha) const;
Vector4 operator+(const Vector4& rhs) const;
Vector4 operator-(const Vector4& rhs) const;
Vector4 operator*(float rhs) const;
Vector4 operator/(float rhs) const;
Vector4 operator+() const;
Vector4 operator-() const;
public:
#if MUTABLE
float x = 0;
float y = 0;
float z = 0;
float w = 0;
#else
const float x = 0;
const float y = 0;
const float z = 0;
const float w = 0;
#endif
};
// Essential Reading:
// http://www.essentialmath.com/GDC2012/GDC2012_JMV_Rotations.pdf
class EulerAngle {
public:
EulerAngle();
EulerAngle(float pitch, float yaw, float roll);
EulerAngle(const Vector3& vec) : pitch(vec.x), yaw(vec.y), roll(vec.z) {}
static EulerAngle FromRadians(float radians);
static EulerAngle FromDegrees(float degrees);
/// TODO: Implement separate upper and lower bounds
/// Preserves internal value of euler angles, normalizes and clamps the output.
/// This does not solve gimbal lock!!!
float GetPitch(float pitch_limit) const;
float GetYaw(float yaw_limit) const;
float GetRoll(float roll_limit) const;
bool operator==(const EulerAngle& a) const;
void clamp();
// TODO: Euler Angles do not represent a vector, length doesn't apply, nor is this information meaningful for this data type.
// If you need a meaningful representation of length in 3d space, use a vector!!
[[nodiscard]] float length() const {
return 0;
}
// TODO: Implement
Vector3 unitVector() const;
EulerAngle movementAngle() const;
public:
float pitch;
float yaw;
float roll;
};
/// Transitional datatype, not useful for internal representation of rotation
/// But has uses for conversion and manipulation.
class AxisAngle {
Vector3 axis;
float angle;
};
using Position = Vector3;
/// The CFrame is fundamentally 4 vectors (position, forward, right, up vector)
class CoordinateFrame
{
Vector3 getPosition();
Vector3 getLookVector();
Vector3 getRightVector();
Vector3 getUpVector();
AxisAngle GetAxisAngle();
EulerAngle GetEulerAngleXYZ();
EulerAngle GetWorldAngleYZX();
};
class Matrix2x2 {
public:
static const Matrix2x2 Zero;
static const Matrix2x2 Identity;
static const Matrix2x2 NaN;
Vector2 GetRow() const;
Vector2 GetColumn() const;
protected:
float elems[2][2];
};
/// A 3-by-3 matrix for linear transformations of 3D geometry.
/* This can represent any kind of linear transformations of 3D geometry, which include
* rotation, scale, shear, mirroring, and orthographic projection.
* A 3x3 matrix cannot represent translation, which requires a 3x4, or perspective projection (4x4).
* The elements of this matrix are
* m_00, m_01, m_02
* m_10, m_11, m_12
* m_20, m_21, m_22
*
* The element m_yx is the value on the row y and column x.
* You can access m_yx using the double-bracket notation m[y][x], or using the member function At.
*
* @note The member functions in this class use the convention that transforms are applied to
* vectors in the form M * v. This means that "Matrix3x3 M, M1, M2; M = M1 * M2;" gives a transformation M
* that applies M2 first, followed by M1 second
*/
class Matrix3x3 {
public:
enum { Rows = 3 };
enum { Cols = 3 };
static const Matrix3x3 Zero;
static const Matrix3x3 Identity;
static const Matrix3x3 NaN;
Matrix3x3();
Matrix3x3(float fillValue);
Matrix3x3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22);
Matrix3x3(const Vector3& r1, const Vector3& r2, const Vector3& r3);
explicit Matrix3x3(const Quaternion& orientation);
static Matrix3x3 RotateX(float radians);
static Matrix3x3 RotateY(float radians);
static Matrix3x3 RotateZ(float radians);
Vector3 GetRow(int index) const;
Vector3 GetColumn(int index) const;
float At(int x, int y) const;
/// Creates a new M3x3 that rotates about the given axis by the given angle
static Matrix3x3 RotateAxisAngle(const Vector3& rhs);
static Matrix3x3 RotateFromTo(const Vector3& source, const Vector3& direction);
static Matrix3x3 LookAt(const Vector3& forward, const Vector3& target, const Vector3& localUp, const Vector3& worldUp);
static Matrix3x3 FromQuat(const Quaternion& orientation);
Quaternion ToQuat() const;
/// Creates a new Matrix3x3 as a combination of rotation and scale.
// This function creates a new matrix M in the form M = R * S
// where R is a rotation matrix and S is a scale matrix.
// Transforming a vector v using this matrix computes the vector
// v' == M * v == R*S*v == (R * (S * v)) which means the scale operation
// is applied to the vector first, followed by rotation, and finally translation
static Matrix3x3 FromRS(const Quaternion& rotate, const Matrix3x3& scale);
static Matrix3x3 FromRS(const Matrix3x3 &rotate, const Matrix3x3& scale);
/// Creates a new transformation matrix that scales by the given factors.
// This matrix scales with respect to origin.
static Matrix3x3 Scale(float sx, float sy, float sz);
static Matrix3x3 Scale(const Matrix3x3& scale);
/// Returns the main diagonal.
Vector3 Diagonal() const;
/// Returns the local +X/+Y/+Z axis in world space.
/// This is the same as transforming the vector{1,0,0} by this matrix.
Vector3 WorldX() const;
/// Returns the local +Y axis in world space.
/// This is the same as transforming the vector{0,1,0} by this matrix.
Vector3 WorldY() const;
/// Returns the local +Z axis in world space.
/// This is the same as transforming the vector{0,0,1} by this matrix.
Vector3 WorldZ() const;
/// Computes the determinant of this matrix.
// If the determinant is nonzero, this matrix is invertible.
// If the determinant is negative, this matrix performs reflection about some axis.
// From http://msdn.microsoft.com/en-us/library/bb204853(VS.85).aspx :
// "If the determinant is positive, the basis is said to be "positively" oriented (or right-handed).
// If the determinant is negative, the basis is said to be "negatively" oriented (or left-handed)."
// @note This function computes 9 LOADs, 9 MULs and 5 ADDs. */
float Determinant() const;
// Returns an inverted copy of this matrix. This
Matrix3x3 Inverse() const;
// Returns a transposed copy of this matrix.
Matrix3x3 Transpose() const;
// Transforms the given vectors by this matrix M, i.e. returns M * (x,y,z)
Vector2 Transform(const Vector2& vector) const;
Vector3 Transform(const Vector3& rhs) const;
Vector2 Transform(float x, float y) const;
Vector3 Transform(float x, float y, float z) const;
Vector3 operator[] (float index) const;
Vector3 operator * (const Vector3& rhs) const;
Matrix3x3 operator * (const Matrix3x3& rhs) const;
protected:
float elems[3][3];
};
/// A 4-by-4 matrix for affine transformations and perspective projections of 3D geometry.
/* This matrix can represent the most generic form of transformations for 3D objects,
* including perspective projections, which a 4-by-3 cannot store,
* and translations, which a 3-by-3 cannot represent.
* The elements of this matrix are
* m_00, m_01, m_02, m_03
* m_10, m_11, m_12, m_13
* m_20, m_21, m_22, m_23,
* m_30, m_31, m_32, m_33
*
* The element m_yx is the value on the row y and column x.
* You can access m_yx using the double-bracket notation m[y][x]
*/
class Matrix4x4 {
public:
static const Matrix4x4 Zero;
static const Matrix4x4 Identity;
Vector3 GetTranslationComponent() const;
Matrix3x3 GetRotationComponent() const;
Vector4 GetRow() const;
Vector4 GetColumn() const;
protected:
float elems[4][4];
};
class Transform2D {
protected:
Matrix3x3 transformation;
public:
Transform2D Translate(const Vector2& offset) const;
Transform2D Translate(float x, float y) const;
Transform2D Scale(float scale); // Perform Uniform Scale
Transform2D Scale(float x, float y); // Perform Nonunform Scale
Transform2D Scale(const Vector2& scales); // Perform Nonuniform Scale
Transform2D Rotate();
};
class Transform3D {
protected:
Matrix4x4 transformation;
public:
Transform3D Scale();
Transform3D Translate();
Transform3D Rotate();
};
struct Movement {
EulerAngle angle;
Position position;
};
class Quaternion : public Vector4
{
public:
Quaternion() {}
Quaternion(const Quaternion& rhs) = default;
explicit Quaternion(Matrix3x3& rotationMtrx) {}
explicit Quaternion(Matrix4x4& rotationMtrx) {}
// @note The input data is not normalized after construction, this has to be done manually.
Quaternion(float x, float y, float z, float w);
// Constructs this quaternion by specifying a rotation axis and the amount of rotation to be performed about that axis
// @param rotationAxis The normalized rotation axis to rotate about. If using Vector4 version of the constructor, the w component of this vector must be 0.
Quaternion(const Vector3& rotationAxis, float rotationAngleBetween) { SetFromAxisAngle(rotationAxis, rotationAngleBetween); }
Quaternion(const Vector4& rotationAxis, float rotationAngleBetween) { SetFromAxisAngle(rotationAxis, rotationAngleBetween); }
//void Inverse();
Quaternion Inverse() const;
//void Normalize();
Quaternion Normalize() const;
Vector3 GetWorldX() const { return Transform(1.f, 0.f, 0.f); }
Vector3 GetWorldY() const { return Transform(0.f, 1.f, 0.f); }
Vector3 GetWorldZ() const { return Transform(0.f, 0.f, 1.f); }
Matrix3x3 ToMatrix3x3() const;
Vector3 Transform(const Vector3& vec) const
{
Matrix3x3 mat = this->ToMatrix3x3();
return mat * vec;
}
Vector3 Transform(float X, float Y, float Z) const
{
return Transform(Vector3{X, Y, Z});
}
// Note: We only transform the x,y,z components of 4D vectors, w is left untouched
Vector4 Transform(const Vector4& vec) const
{
return Vector4(Transform(vec.x, vec.y, vec.z), vec.w);
}
Vector4 Transform(float X, float Y, float Z, float W) const
{
return Transform(Vector4(X, Y, Z, W));
}
Quaternion GetInverse() const;
Quaternion Lerp(const Quaternion& b, float t) const
{
float angle = this->dot(b);
if (angle >= 0.f) // Make sure we rotate the shorter arc
return (*this * (1.f - t) + b * t).Normalize();
else
return (*this * (t - 1.f) + b * t).Normalize();
}
Quaternion Slerp(const Quaternion& target) const;
void SetFromAxisAngle(const Vector3& axis, float angle)
{
float sinz, cosz;
}
void SetFromAxisAngle(const Vector4& axis, float angle)
{
}
static Quaternion LookAt(const Vector3& position, const Vector3& direction, const Vector3& axisUp);
// Multiplies two quaternions together.
// The product q1 * q2 returns a quaternion that concatenates the two orientation rotations.
// The rotation q2 is applied first before q1.
Quaternion operator * (const Quaternion& rhs) const;
Quaternion operator * (float scalar) const
{
return Quaternion(x * scalar, y * scalar, z * scalar, w * scalar);
}
// Transforms the given vector by this Quaternion.
Vector3 operator * (const Vector3& rhs) const;
Vector4 operator * (const Vector4& rhs) const;
// Divides a quaternion by another. Divison "a / b" results in a quaternion that rotates the orientation b to coincide with orientation of
Quaternion operator / (const Quaternion& rhs) const;
Quaternion operator +(const Quaternion& rhs) const;
Quaternion operator +() const { return *this; }
Quaternion operator -() const;
};
inline namespace VectorMath {
inline float distance(Position sP, Position eP) {
return sqrt(pow(eP.x - sP.x, 2) + pow(eP.y - sP.y, 2) + pow(eP.z - sP.z, 2));
}
//Basically an aimbot.
inline Vector3 calcAngle(Position sP, Position eP) {
const auto pi = glm::pi<float>();
//returned.x = -(asinf((eP.y - sP.y) / distance(sP, eP)) * 180.0f / M_PI);
//returned.y = (atan2f(eP.x - sP.x,eP.z - sP.z) / M_PI * 180.0f);
return {static_cast<float>((-(asinf((eP.y - sP.y) / distance(sP, eP)) * 180.0f / pi ))),static_cast<float>((atan2f(eP.x - sP.x,eP.z - sP.z) / pi * 180.0f)),0};
}
}
}

View File

@@ -0,0 +1,13 @@
#pragma once
namespace LinearAlgebra
{
/// Transitional datatype, not useful for internal representation of rotation
/// But has uses for conversion and manipulation.
class AxisAngle {
Vector3 Axis;
float Angle;
};
}

View File

@@ -0,0 +1,18 @@
#pragma once
namespace LinearAlgebra
{
/// The CFrame is fundamentally 4 vectors (position, forward, right, up vector)
class CoordinateFrame
{
Vector3 getPosition();
Vector3 getLookVector();
Vector3 getRightVector();
Vector3 getUpVector();
AxisAngle GetAxisAngle();
EulerAngle GetEulerAngleXYZ();
EulerAngle GetWorldAngleYZX();
};
}

View File

@@ -0,0 +1,41 @@
#pragma once
#include <J3ML/LinearAlgebra/Vector3.h>
namespace LinearAlgebra {
// Essential Reading:
// http://www.essentialmath.com/GDC2012/GDC2012_JMV_Rotations.pdf
class EulerAngle {
public:
EulerAngle();
EulerAngle(float pitch, float yaw, float roll);
EulerAngle(const Vector3& vec) : pitch(vec.x), yaw(vec.y), roll(vec.z) {}
static EulerAngle FromRadians(float radians);
static EulerAngle FromDegrees(float degrees);
/// TODO: Implement separate upper and lower bounds
/// Preserves internal value of euler angles, normalizes and clamps the output.
/// This does not solve gimbal lock!!!
float GetPitch(float pitch_limit) const;
float GetYaw(float yaw_limit) const;
float GetRoll(float roll_limit) const;
bool operator==(const EulerAngle& a) const;
void clamp();
// TODO: Euler Angles do not represent a vector, length doesn't apply, nor is this information meaningful for this data type.
// If you need a meaningful representation of length in 3d space, use a vector!!
[[nodiscard]] float length() const {
return 0;
}
// TODO: Implement
Vector3 unitVector() const;
EulerAngle movementAngle() const;
public:
float pitch;
float yaw;
float roll;
};
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include <J3ML/LinearAlgebra/Vector2.h>
namespace LinearAlgebra {
class Matrix2x2 {
public:
static const Matrix2x2 Zero;
static const Matrix2x2 Identity;
static const Matrix2x2 NaN;
Vector2 GetRow() const;
Vector2 GetColumn() const;
protected:
float elems[2][2];
};
}

View File

@@ -0,0 +1,114 @@
#pragma once
#include <J3ML/LinearAlgebra/Vector3.h>
namespace LinearAlgebra {
/// A 3-by-3 matrix for linear transformations of 3D geometry.
/* This can represent any kind of linear transformations of 3D geometry, which include
* rotation, scale, shear, mirroring, and orthographic projection.
* A 3x3 matrix cannot represent translation, which requires a 3x4, or perspective projection (4x4).
* The elements of this matrix are
* m_00, m_01, m_02
* m_10, m_11, m_12
* m_20, m_21, m_22
*
* The element m_yx is the value on the row y and column x.
* You can access m_yx using the double-bracket notation m[y][x], or using the member function At.
*
* @note The member functions in this class use the convention that transforms are applied to
* vectors in the form M * v. This means that "Matrix3x3 M, M1, M2; M = M1 * M2;" gives a transformation M
* that applies M2 first, followed by M1 second
*/
class Matrix3x3 {
public:
enum { Rows = 3 };
enum { Cols = 3 };
static const Matrix3x3 Zero;
static const Matrix3x3 Identity;
static const Matrix3x3 NaN;
Matrix3x3() {}
Matrix3x3(float val);
Matrix3x3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22);
Matrix3x3(const Vector3& r1, const Vector3& r2, const Vector3& r3);
explicit Matrix3x3(const Quaternion& orientation);
static Matrix3x3 RotateX(float radians);
static Matrix3x3 RotateY(float radians);
static Matrix3x3 RotateZ(float radians);
Vector3 GetRow(int index) const;
Vector3 GetColumn(int index) const;
float At(int x, int y) const;
/// Creates a new M3x3 that rotates about the given axis by the given angle
static Matrix3x3 RotateAxisAngle(const Vector3& rhs);
static Matrix3x3 RotateFromTo(const Vector3& source, const Vector3& direction);
static Matrix3x3 LookAt(const Vector3& forward, const Vector3& target, const Vector3& localUp, const Vector3& worldUp);
static Matrix3x3 FromQuat(const Quaternion& orientation);
Quaternion ToQuat() const;
/// Creates a new Matrix3x3 as a combination of rotation and scale.
// This function creates a new matrix M in the form M = R * S
// where R is a rotation matrix and S is a scale matrix.
// Transforming a vector v using this matrix computes the vector
// v' == M * v == R*S*v == (R * (S * v)) which means the scale operation
// is applied to the vector first, followed by rotation, and finally translation
static Matrix3x3 FromRS(const Quaternion& rotate, const Matrix3x3& scale);
static Matrix3x3 FromRS(const Matrix3x3 &rotate, const Matrix3x3& scale);
/// Creates a new transformation matrix that scales by the given factors.
// This matrix scales with respect to origin.
static Matrix3x3 Scale(float sx, float sy, float sz);
static Matrix3x3 Scale(const Matrix3x3& scale);
/// Returns the main diagonal.
Vector3 Diagonal() const;
/// Returns the local +X/+Y/+Z axis in world space.
/// This is the same as transforming the vector{1,0,0} by this matrix.
Vector3 WorldX() const;
/// Returns the local +Y axis in world space.
/// This is the same as transforming the vector{0,1,0} by this matrix.
Vector3 WorldY() const;
/// Returns the local +Z axis in world space.
/// This is the same as transforming the vector{0,0,1} by this matrix.
Vector3 WorldZ() const;
/// Computes the determinant of this matrix.
// If the determinant is nonzero, this matrix is invertible.
// If the determinant is negative, this matrix performs reflection about some axis.
// From http://msdn.microsoft.com/en-us/library/bb204853(VS.85).aspx :
// "If the determinant is positive, the basis is said to be "positively" oriented (or right-handed).
// If the determinant is negative, the basis is said to be "negatively" oriented (or left-handed)."
// @note This function computes 9 LOADs, 9 MULs and 5 ADDs. */
float Determinant() const;
// Returns an inverted copy of this matrix. This
Matrix3x3 Inverse() const;
// Returns a transposed copy of this matrix.
Matrix3x3 Transpose() const;
// Transforms the given vectors by this matrix M, i.e. returns M * (x,y,z)
Vector2 Transform(const Vector2& vector) const;
Vector3 Transform(const Vector3& rhs) const;
Vector2 Transform(float x, float y) const;
Vector3 Transform(float x, float y, float z) const;
Vector3 operator[] (float index) const;
Vector3 operator * (const Vector3& rhs) const;
Matrix3x3 operator * (const Matrix3x3& rhs) const;
protected:
float elems[3][3];
};
}

View File

@@ -0,0 +1,31 @@
#pragma once
namespace LinearAlgebra {
/// A 4-by-4 matrix for affine transformations and perspective projections of 3D geometry.
/* This matrix can represent the most generic form of transformations for 3D objects,
* including perspective projections, which a 4-by-3 cannot store,
* and translations, which a 3-by-3 cannot represent.
* The elements of this matrix are
* m_00, m_01, m_02, m_03
* m_10, m_11, m_12, m_13
* m_20, m_21, m_22, m_23,
* m_30, m_31, m_32, m_33
*
* The element m_yx is the value on the row y and column x.
* You can access m_yx using the double-bracket notation m[y][x]
*/
class Matrix4x4 {
public:
static const Matrix4x4 Zero;
static const Matrix4x4 Identity;
Vector3 GetTranslationComponent() const;
Matrix3x3 GetRotationComponent() const;
Vector4 GetRow() const;
Vector4 GetColumn() const;
protected:
float elems[4][4];
};
}

View File

@@ -0,0 +1,93 @@
#pragma once
namespace LinearAlgebra
{
class Quaternion : public Vector4
{
public:
Quaternion() {}
Quaternion(const Quaternion& rhs) = default;
explicit Quaternion(Matrix3x3& rotationMtrx) {}
explicit Quaternion(Matrix4x4& rotationMtrx) {}
// @note The input data is not normalized after construction, this has to be done manually.
Quaternion(float x, float y, float z, float w);
// Constructs this quaternion by specifying a rotation axis and the amount of rotation to be performed about that axis
// @param rotationAxis The normalized rotation axis to rotate about. If using Vector4 version of the constructor, the w component of this vector must be 0.
Quaternion(const Vector3& rotationAxis, float rotationAngleBetween) { SetFromAxisAngle(rotationAxis, rotationAngleBetween); }
Quaternion(const Vector4& rotationAxis, float rotationAngleBetween) { SetFromAxisAngle(rotationAxis, rotationAngleBetween); }
//void Inverse();
Quaternion Inverse() const;
//void Normalize();
Quaternion Normalize() const;
Vector3 GetWorldX() const { return Transform(1.f, 0.f, 0.f); }
Vector3 GetWorldY() const { return Transform(0.f, 1.f, 0.f); }
Vector3 GetWorldZ() const { return Transform(0.f, 0.f, 1.f); }
Matrix3x3 ToMatrix3x3() const;
Vector3 Transform(const Vector3& vec) const
{
Matrix3x3 mat = this->ToMatrix3x3();
return mat * vec;
}
Vector3 Transform(float X, float Y, float Z) const
{
return Transform(Vector3{X, Y, Z});
}
// Note: We only transform the x,y,z components of 4D vectors, w is left untouched
Vector4 Transform(const Vector4& vec) const
{
return Vector4(Transform(vec.x, vec.y, vec.z), vec.w);
}
Vector4 Transform(float X, float Y, float Z, float W) const
{
return Transform(Vector4(X, Y, Z, W));
}
Quaternion GetInverse() const;
Quaternion Lerp(const Quaternion& b, float t) const
{
float angle = this->dot(b);
if (angle >= 0.f) // Make sure we rotate the shorter arc
return (*this * (1.f - t) + b * t).Normalize();
else
return (*this * (t - 1.f) + b * t).Normalize();
}
Quaternion Slerp(const Quaternion& target) const;
void SetFromAxisAngle(const Vector3& axis, float angle)
{
float sinz, cosz;
}
void SetFromAxisAngle(const Vector4& axis, float angle)
{
}
static Quaternion LookAt(const Vector3& position, const Vector3& direction, const Vector3& axisUp);
// Multiplies two quaternions together.
// The product q1 * q2 returns a quaternion that concatenates the two orientation rotations.
// The rotation q2 is applied first before q1.
Quaternion operator * (const Quaternion& rhs) const;
Quaternion operator * (float scalar) const
{
return Quaternion(x * scalar, y * scalar, z * scalar, w * scalar);
}
// Transforms the given vector by this Quaternion.
Vector3 operator * (const Vector3& rhs) const;
Vector4 operator * (const Vector4& rhs) const;
// Divides a quaternion by another. Divison "a / b" results in a quaternion that rotates the orientation b to coincide with orientation of
Quaternion operator / (const Quaternion& rhs) const;
Quaternion operator +(const Quaternion& rhs) const;
Quaternion operator +() const { return *this; }
Quaternion operator -() const;
};
}

View File

@@ -0,0 +1,13 @@
#pragma once
class Transform2D {
protected:
Matrix3x3 transformation;
public:
Transform2D Translate(const Vector2& offset) const;
Transform2D Translate(float x, float y) const;
Transform2D Scale(float scale); // Perform Uniform Scale
Transform2D Scale(float x, float y); // Perform Nonunform Scale
Transform2D Scale(const Vector2& scales); // Perform Nonuniform Scale
Transform2D Rotate();
};

View File

@@ -0,0 +1,133 @@
#include <cstddef>
#pragma once
namespace LinearAlgebra {
// A 2D (x, y) ordered pair.
class Vector2 {
public:
// Default Constructor - Initializes values to zero
Vector2();
// Constructs a new Vector2 with the value (X, Y)
Vector2(float X, float Y);
Vector2(const Vector2& rhs); // Copy Constructor
Vector2(Vector2&&) = default; // Move Constructor
float GetX() const;
float GetY() const;
#if MUTABLE
void SetX(float newX) { x = newX;}
void SetY(float newY) { y = newY; }
#endif
static const Vector2 Zero;
static const Vector2 Up;
static const Vector2 Left;
static const Vector2 Down;
static const Vector2 Right;
float operator[](std::size_t index);
bool IsWithinMarginOfError(const Vector2& rhs, float margin=0.001f) const;
bool IsNormalized(float epsilonSq = 1e-5f) const;
bool IsZero(float epsilonSq = 1e-6f) const;
bool IsFinite() const;
bool IsPerpendicular(const Vector2& other, float epsilonSq=1e-5f) const;
bool operator == (const Vector2& rhs) const;
bool operator != (const Vector2& rhs) const;
Vector2 Min(const Vector2& min) const;
static Vector2 Min(const Vector2& value, const Vector2& minimum);
Vector2 Max(const Vector2& max) const;
static Vector2 Max(const Vector2& value, const Vector2& maximum);
Vector2 Clamp(const Vector2& min, const Vector2& max) const;
static Vector2 Clamp(const Vector2& min, const Vector2& middle, const Vector2& max);
// Returns the magnitude between the two vectors.
float Distance(const Vector2& to) const;
static float Distance(const Vector2& from, const Vector2& to);
float Length() const;
static float Length(const Vector2& of);
float LengthSquared() const;
static float LengthSquared(const Vector2& of);
// Returns the length of the vector, which is sqrt(x^2 + y^2)
float Magnitude() const;
static float Magnitude(const Vector2& of) { return of.Magnitude();}
// Returns a float value equal to the magnitudes of the two vectors multiplied together and then multiplied by the cosine of the angle between them.
// For normalized vectors, dot returns 1 if they point in exactly the same direction,
// -1 if they point in completely opposite directions, and 0 if the vectors are perpendicular.
float Dot(const Vector2& rhs) const;
static float Dot(const Vector2& lhs, const Vector2& rhs) { return lhs.Dot(rhs); }
// Projects one vector onto another and returns the result. (IDK)
Vector2 Project(const Vector2& rhs) const;
// @see Project
static Vector2 Project(const Vector2& lhs, const Vector2& rhs) { return lhs.Project(rhs); }
// Returns a copy of this vector, resized to have a magnitude of 1, while preserving "direction"
Vector2 Normalize() const;
static Vector2 Normalize(const Vector2& of) { return of.Normalize(); }
// Linearly interpolates between two points.
// Interpolates between the points and b by the interpolant t.
// The parameter is (TODO: SHOULD BE!) clamped to the range[0, 1].
// This is most commonly used to find a point some fraction of the wy along a line between two endpoints (eg. to move an object gradually between those points).
Vector2 Lerp(const Vector2& rhs, float alpha) const;
// @see Lerp
static Vector2 Lerp(const Vector2& lhs, const Vector2& rhs, float alpha) { return lhs.Lerp(rhs, alpha); }
float AngleBetween(const Vector2& rhs) const;
static float AngleBetween(const Vector2& lhs, const Vector2& rhs);
// Adds two vectors.
Vector2 operator +(const Vector2& rhs) const;
Vector2 Add(const Vector2& rhs) const;
static Vector2 Add(const Vector2& lhs, const Vector2& rhs);
// Subtracts two vectors.
Vector2 operator -(const Vector2& rhs) const;
Vector2 Sub(const Vector2& rhs) const;
static Vector2 Sub(const Vector2& lhs, const Vector2& rhs);
// Multiplies this vector by a scalar value.
Vector2 operator *(float rhs) const;
Vector2 Mul(float scalar) const;
static Vector2 Mul(const Vector2& lhs, float rhs);
// Divides this vector by a scalar.
Vector2 operator /(float rhs) const;
Vector2 Div(float scalar) const;
static Vector2 Div(const Vector2& lhs, float rhs);
// Unary operator +
Vector2 operator +() const; // TODO: Implement
Vector2 operator -() const;
// Assigns a vector to another
Vector2& operator=(const Vector2&v);
Vector2& operator+=(const Vector2& rhs); // Adds a vector to this vector, in-place.
Vector2& operator-=(const Vector2& rhs); // Subtracts a vector from this vector, in-place
Vector2& operator*=(float scalar);
Vector2& operator/=(float scalar);
public:
#if MUTABLE
float x = 0;
float y = 0;
#else
const float x = 0;
const float y = 0;
#endif
};
}

View File

@@ -0,0 +1,140 @@
#pragma once
#include <J3ML/LinearAlgebra/Vector3.h>
#include <cstddef>
namespace LinearAlgebra {
// A 3D (x, y, z) ordered pair.
class Vector3 {
public:
// Default Constructor - Initializes to zero
Vector3();
// Constructs a new Vector3 with the value (X, Y, Z)
Vector3(float X, float Y, float Z);
Vector3(const Vector3& rhs); // Copy Constructor
Vector3(Vector3&&) = default; // Move Constructor
Vector3& operator=(const Vector3& rhs);
float GetX() const;
float GetY() const;
float GetZ() const;
#if MUTABLE
void SetX(float newX) { x = newX;}
void SetY(float newY) { y = newY;}
void SetZ(float newZ) { z = newZ;}
#endif
static const Vector3 Zero;
static const Vector3 Up;
static const Vector3 Down;
static const Vector3 Left;
static const Vector3 Right;
static const Vector3 Forward;
static const Vector3 Backward;
static const Vector3 NaN;
float operator[](std::size_t index) const;
bool IsWithinMarginOfError(const Vector3& rhs, float margin=0.001f) const;
bool IsNormalized(float epsilonSq = 1e-5f) const;
bool IsZero(float epsilonSq = 1e-6f) const;
bool IsFinite() const;
bool IsPerpendicular(const Vector3& other, float epsilonSq=1e-5f) const;
bool operator == (const Vector3& rhs) const;
bool operator != (const Vector3& rhs) const;
Vector3 Min(const Vector3& min) const;
static Vector3 Min(const Vector3& lhs, const Vector3& rhs);
Vector3 Max(const Vector3& max) const;
static Vector3 Max(const Vector3& lhs, const Vector3& rhs);
Vector3 Clamp(const Vector3& min, const Vector3& max) const;
static Vector3 Clamp(const Vector3& min, const Vector3& input, const Vector3& max);
// Returns the magnitude between the two vectors.
float Distance(const Vector3& to) const;
static float Distance(const Vector3& from, const Vector3& to);
float Length() const;
static float Length(const Vector3& of);
float LengthSquared() const;
static float LengthSquared(const Vector3& of);
// Returns the length of the vector, which is sqrt(x^2 + y^2 + z^2)
float Magnitude() const;
static float Magnitude(const Vector3& of);
// Returns a float value equal to the magnitudes of the two vectors multiplied together and then multiplied by the cosine of the angle between them.
// For normalized vectors, dot returns 1 if they point in exactly the same direction,
// -1 if they point in completely opposite directions, and 0 if the vectors are perpendicular.
float Dot(const Vector3& rhs) const;
static float Dot(const Vector3& lhs, const Vector3& rhs);
// Projects one vector onto another and returns the result. (IDK)
Vector3 Project(const Vector3& rhs) const;
static Vector3 Project(const Vector3& lhs, const Vector3& rhs);
// The cross product of two vectors results in a third vector which is perpendicular to the two input vectors.
// The result's magnitude is equal to the magnitudes of the two inputs multiplied together and then multiplied by the sine of the angle between the inputs.
Vector3 Cross(const Vector3& rhs) const;
static Vector3 Cross(const Vector3& lhs, const Vector3& rhs);
// Returns a copy of this vector, resized to have a magnitude of 1, while preserving "direction"
Vector3 Normalize() const;
static Vector3 Normalize(const Vector3& targ);
// Linearly interpolates between two points.
// Interpolates between the points and b by the interpolant t.
// The parameter is (TODO: SHOULD BE!) clamped to the range[0, 1].
// This is most commonly used to find a point some fraction of the wy along a line between two endpoints (eg. to move an object gradually between those points).
Vector3 Lerp(const Vector3& goal, float alpha) const;
static Vector3 Lerp(const Vector3& lhs, const Vector3& rhs, float alpha);
float AngleBetween(const Vector3& rhs) const; // TODO: 3D Angle representation?
static float AngleBetween(const Vector3& lhs, const Vector3& rhs); // TODO: 3D Angle representation?
// Adds two vectors
Vector3 operator+(const Vector3& rhs) const;
Vector3 Add(const Vector3& rhs) const;
static Vector3 Add(const Vector3& lhs, const Vector3& rhs);
// Subtracts two vectors
Vector3 operator-(const Vector3& rhs) const;
Vector3 Sub(const Vector3& rhs) const;
static Vector3 Sub(const Vector3& lhs, const Vector3& rhs);
// Multiplies this vector by a scalar value
Vector3 operator*(float rhs) const;
Vector3 Mul(float scalar) const;
static Vector3 Mul(const Vector3& lhs, float rhs);
// Divides this vector by a scalar
Vector3 operator/(float rhs) const;
Vector3 Div(float scalar) const;
static Vector3 Div(const Vector3& lhs, float rhs);
// Unary + operator
Vector3 operator+() const; // TODO: Implement
// Unary - operator (Negation)
Vector3 operator-() const;
public:
#if MUTABLE
float x = 0;
float y = 0;
float z = 0;
#else
const float x = 0;
const float y = 0;
const float z = 0;
#endif
};
}

View File

@@ -0,0 +1,99 @@
#pragma once
#include <J3ML/LinearAlgebra/Vector3.h>
namespace LinearAlgebra {
class Vector4 {
public:
// Default Constructor
Vector4();
// Constructs a new Vector4 with x,y,z values from a Vector3
Vector4(const Vector3& xyz, float w = 0);
// Constructs a new Vector4 with the value (X, Y, Z, W)
Vector4(float X, float Y, float Z, float W);
Vector4(const Vector4& copy) = default;
Vector4(Vector4&& move) = default;
Vector4& operator=(const Vector4& rhs);
float GetX() const;
float GetY() const;
float GetZ() const;
float GetW() const;
#if MUTABLE
void SetX(float newX) { x = newX;}
void SetY(float newY) { y = newY;}
void SetZ(float newZ) { z = newZ;}
void SetW(float newW) { w = newW;}
#endif
static const Vector4 Zero;
static const Vector4 NaN;
float operator[](std::size_t index) const;
bool IsWithinMarginOfError(const Vector4& rhs, float margin=0.0001f) const;
bool IsNormalized(float epsilonSq = 1e-5f) const;
bool IsZero(float epsilonSq = 1e-6f) const;
bool IsFinite() const;
bool IsPerpendicular(const Vector4& other, float epsilonSq=1e-5f) const;
bool operator==(const Vector4& rhs) const;
bool operator!=(const Vector4& rhs) const;
Vector4 Min(const Vector4& min) const;
Vector4 Max(const Vector4& max) const;
Vector4 Clamp(const Vector4& min, const Vector4& max) const;
float Distance(const Vector4& to) const;
float Length() const;
float LengthSquared() const;
float Magnitude() const;
float Dot(const Vector4& rhs) const;
Vector4 Project(const Vector4& rhs) const;
// While it is feasable to compute a cross-product in four dimensions
// the cross product only has the orthogonality property in 3 and 7 dimensions
// You should consider instead looking at Gram-Schmidt Orthogonalization
// to find orthonormal vectors.
Vector4 Cross(const Vector4& rhs) const;
Vector4 Normalize() const;
Vector4 Lerp(const Vector4& goal, float alpha) const;
float AngleBetween(const Vector4& rhs) const;
// Adds two vectors
Vector4 operator+(const Vector4& rhs) const;
Vector4 Add(const Vector4& rhs) const;
static Vector4 Add(const Vector4& lhs, const Vector4& rhs);
// Subtracts two vectors
Vector4 operator-(const Vector4& rhs) const;
Vector4 Sub(const Vector4& rhs) const;
static Vector4 Sub(const Vector4& lhs, const Vector4& rhs);
// Multiplies this vector by a scalar value
Vector4 operator*(float rhs) const;
Vector4 Mul(float scalar) const;
static Vector4 Mul(const Vector4& lhs, float rhs);
// Divides this vector by a scalar
Vector4 operator/(float rhs) const;
Vector4 Div(float scalar) const;
static Vector4 Div(const Vector4& rhs, float scalar);
Vector4 operator+() const; // Unary + Operator
Vector4 operator-() const; // Unary - Operator (Negation)
public:
#if MUTABLE
float x = 0;
float y = 0;
float z = 0;
float w = 0;
#else
const float x = 0;
const float y = 0;
const float z = 0;
const float w = 0;
#endif
};
}

View File

@@ -1,8 +0,0 @@
//
// Created by josh on 12/25/2023.
//
#ifndef J3ML_MATRIX_H
#define J3ML_MATRIX_H
#endif //J3ML_MATRIX_H

View File

@@ -1,8 +0,0 @@
//
// Created by josh on 12/25/2023.
//
#ifndef J3ML_MATRIX2X2_H
#define J3ML_MATRIX2X2_H
#endif //J3ML_MATRIX2X2_H

View File

@@ -1,8 +0,0 @@
//
// Created by josh on 12/25/2023.
//
#ifndef J3ML_MATRIX3X3_H
#define J3ML_MATRIX3X3_H
#endif //J3ML_MATRIX3X3_H

View File

@@ -1,8 +0,0 @@
//
// Created by josh on 12/25/2023.
//
#ifndef J3ML_MATRIX4X4_H
#define J3ML_MATRIX4X4_H
#endif //J3ML_MATRIX4X4_H

View File

@@ -1,8 +0,0 @@
//
// Created by josh on 12/25/2023.
//
#ifndef J3ML_QUATERNION_H
#define J3ML_QUATERNION_H
#endif //J3ML_QUATERNION_H

View File

@@ -1,365 +0,0 @@
#include <LinearAlgebra/LinearAlgebra.h>
namespace LinearAlgebra {
class Vector2 {
public:
Vector2();
// Constructs a new Vector2 with the value (X, Y)
Vector2(float X, float Y);
Vector2(const Vector2 &rhs); // Copy Constructor
Vector2(Vector2 &&) = default; // Move Constructor
float GetX() const { return x; }
float GetY() const { return y; }
#if MUTABLE
void SetX(float newX) { x = newX;}
void SetY(float newY) { y = newY; }
#endif
static const Vector2 Zero;
static const Vector2 Up;
static const Vector2 Left;
static const Vector2 Down;
static const Vector2 Right;
float operator[](std::size_t index);
bool IsWithinMarginOfError(const Vector2 &rhs, float margin = 0.001f) const;
bool operator==(const Vector2 &rhs) const;
bool operator!=(const Vector2 &rhs) const;
Vector2 Min(const Vector2 &min) const;
static Vector2 Min(const Vector2 &value, const Vector2 &minimum) { return value.Min(minimum); }
Vector2 Max(const Vector2 &max) const;
static Vector2 Max(const Vector2 &value, const Vector2 &maximum) { return value.Max(maximum); }
Vector2 Clamp(const Vector2 &min, const Vector2 &max) const;
static Vector2 Clamp(const Vector2 &min, const Vector2 &middle, const Vector2 &max);
// Returns the magnitude between the two vectors.
float Distance(const Vector2 &to) const;
static float Distance(const Vector2 &from, const Vector2 &to);
float Length() const;
static float Length(const Vector2 &of) { return of.Length(); }
float LengthSquared() const;
static float LengthSquared(const Vector2 &of) { return of.LengthSquared(); }
// Returns the length of the vector, which is sqrt(x^2 + y^2)
float Magnitude() const;
static float Magnitude(const Vector2 &of) { return of.Magnitude(); }
// Returns a float value equal to the magnitudes of the two vectors multiplied together and then multiplied by the cosine of the angle between them.
// For normalized vectors, dot returns 1 if they point in exactly the same direction,
// -1 if they point in completely opposite directions, and 0 if the vectors are perpendicular.
float Dot(const Vector2 &rhs) const;
static float Dot(const Vector2 &lhs, const Vector2 &rhs) { return lhs.Dot(rhs); }
// Projects one vector onto another and returns the result. (IDK)
Vector2 Project(const Vector2 &rhs) const;
// @see Project
static Vector2 Project(const Vector2 &lhs, const Vector2 &rhs) { return lhs.Project(rhs); }
// Returns a copy of this vector, resized to have a magnitude of 1, while preserving "direction"
Vector2 Normalize() const;
static Vector2 Normalize(const Vector2 &of) { return of.Normalize(); }
// Linearly interpolates between two points.
// Interpolates between the points and b by the interpolant t.
// The parameter is (TODO: SHOULD BE!) clamped to the range[0, 1].
// This is most commonly used to find a point some fraction of the wy along a line between two endpoints (eg. to move an object gradually between those points).
Vector2 Lerp(const Vector2 &rhs, float alpha) const;
// @see Lerp
static Vector2 Lerp(const Vector2 &lhs, const Vector2 &rhs, float alpha) { return lhs.Lerp(rhs, alpha); }
float AngleBetween(const Vector2 &rhs) const;
static float AngleBetween(const Vector2 &lhs, const Vector2 &rhs);
// Adds two vectors.
Vector2 operator+(const Vector2 &rhs) const;
Vector2 Add(const Vector2 &rhs) const;
static Vector2 Add(const Vector2 &lhs, const Vector2 &rhs);
// Subtracts two vectors.
Vector2 operator-(const Vector2 &rhs) const;
Vector2 Sub(const Vector2 &rhs) const;
static Vector2 Sub(const Vector2 &lhs, const Vector2 &rhs);
// Multiplies this vector by a scalar value.
Vector2 operator*(float rhs) const;
Vector2 Mul(float scalar) const;
static Vector2 Mul(const Vector2 &lhs, float rhs);
// Divides this vector by a scalar.
Vector2 operator/(float rhs) const;
Vector2 Div(float scalar) const;
static Vector2 Div(const Vector2 &lhs, float rhs);
// Unary operator +
Vector2 operator+() const; // TODO: Implement
Vector2 operator-() const;
// Assigns a vector to another
Vector2 &operator=(const Vector2 &v);
Vector2 &operator+=(const Vector2 &rhs); // Adds a vector to this vector, in-place.
Vector2 &operator-=(const Vector2 &rhs); // Subtracts a vector from this vector, in-place
Vector2 &operator*=(float scalar);
Vector2 &operator/=(float scalar);
public:
#if MUTABLE
float x = 0;
float y = 0;
#else
const float x = 0;
const float y = 0;
#endif
};
class Vector3 {
public:
Vector3();
Vector3(float X, float Y, float Z);
Vector3(const Vector3 &rhs);
Vector3(Vector3 &&) = default;
Vector3 &operator=(const Vector3 &rhs);
float getX() const;
float getY() const;
float getZ() const;
#if MUTABLE
void setX(float newX);
void setY(float newY);
void setZ(float newZ);
#endif
static const Vector3 Zero;
static const Vector3 Up;
static const Vector3 Down;
static const Vector3 Left;
static const Vector3 Right;
static const Vector3 Forward;
static const Vector3 Backward;
float operator[](std::size_t index) const;
bool IsWithinMarginOfError(const Vector3 &rhs, float margin = 0.001f) const;
bool IsNormalized(float epsilonSq = 1e-5f) const;
bool IsZero(float epsilonSq = 1e-6f) const;
bool IsFinite() const;
bool IsPerpendicular(const Vector2 &other, float epsilonSq = 1e-5f) const;
bool operator==(const Vector3 &rhs) const;
bool operator!=(const Vector3 &rhs) const;
Vector3 Min(const Vector3 &min) const;
static Vector3 Min(const Vector3 &lhs, const Vector3 &rhs);
Vector3 Max(const Vector3 &max) const;
static Vector3 Max(const Vector3 &lhs, const Vector3 &rhs);
Vector3 Clamp(const Vector3 &min, const Vector3 &max) const;
static Vector3 Clamp(const Vector3 &min, const Vector3 &input, const Vector3 &max);
float Distance(const Vector3 &to) const;
static float Distance(const Vector3 &from, const Vector3 &to);
float Length() const;
static float Length(const Vector3 &of);
float LengthSquared() const;
static float LengthSquared(const Vector3 &of);
// Returns the length of the vector, which is sqrt(x^2 + y^2 + z^2)
float Magnitude() const;
static float Magnitude(const Vector3 &of);
// Returns a float value equal to the magnitudes of the two vectors multiplied together and then multiplied by the cosine of the angle between them.
// For normalized vectors, dot returns 1 if they point in exactly the same direction,
// -1 if they point in completely opposite directions, and 0 if the vectors are perpendicular.
float Dot(const Vector3 &rhs) const;
static float Dot(const Vector3 &lhs, const Vector3 &rhs);
Vector3 Project(const Vector3 &rhs) const;
static Vector3 Project(const Vector3 &lhs, const Vector3 &rhs);
// The cross product of two vectors results in a third vector which is perpendicular to the two input vectors.
// The result's magnitude is equal to the magnitudes of the two inputs multiplied together and then multiplied by the sine of the angle between the inputs.
Vector3 Cross(const Vector3 &rhs) const;
static Vector3 Cross(const Vector3 &lhs, const Vector3 &rhs);
// Returns a copy of this vector, resized to have a magnitude of 1, while preserving "direction"
Vector3 Normalize() const;
static Vector3 Normalize(const Vector3 &targ);
// Linearly interpolates between two points.
// Interpolates between the points and b by the interpolant t.
// The parameter is (TODO: SHOULD BE!) clamped to the range[0, 1].
// This is most commonly used to find a point some fraction of the wy along a line between two endpoints (eg. to move an object gradually between those points).
Vector3 Lerp(const Vector3 &goal, float alpha) const;
Vector3 operator+(const Vector3 &rhs) const;
Vector3 operator-(const Vector3 &rhs) const;
Vector3 operator*(float rhs) const;
Vector3 operator/(float rhs) const;
Vector3 operator+() const; // TODO: Implement
Vector3 operator-() const;
public:
#if MUTABLE
float x = 0;
float y = 0;
float z = 0;
#else
const float x = 0;
const float y = 0;
const float z = 0;
#endif
};
class Vector4 {
public:
Vector4();
Vector4(const Vector3 &xyz, float w = 0);
Vector4(float X, float Y, float Z, float W);
Vector4(const Vector4 &copy) = default;
Vector4(Vector4 &&move) = default;
float getX() const;
float getY() const;
float getZ() const;
float getW() const;
#if MUTABLE
void setX(float newX);
void setY(float newY);
void setZ(float newZ);
void setW(float newW);
#endif
float operator[](int index) const;
bool IsWithinMarginOfError(const Vector4 &rhs, float margin = 0.0001f) const;
bool operator==(const Vector4 &rhs) const;
bool operator!=(const Vector4 &rhs) const;
Vector4 min(const Vector4 &min) const;
Vector4 max(const Vector4 &max) const;
Vector4 clamp(const Vector4 &min, const Vector4 &max) const;
float distance(const Vector4 &to) const;
float length() const;
float lengthSquared() const;
float magnitude() const;
float dot(const Vector4 &rhs) const;
Vector4 project(const Vector4 &rhs) const;
// While it is feasable to compute a cross-product in four dimensions
// the cross product only has the orthogonality property in 3 and 7 dimensions
// You should consider instead looking at Gram-Schmidt Orthogonalization
// to find orthonormal vectors.
Vector4 cross(const Vector4 &rhs) const;
Vector4 normalize() const;
Vector4 lerp(const Vector4 &goal, float alpha) const;
Vector4 operator+(const Vector4 &rhs) const;
Vector4 operator-(const Vector4 &rhs) const;
Vector4 operator*(float rhs) const;
Vector4 operator/(float rhs) const;
Vector4 operator+() const;
Vector4 operator-() const;
public:
#if MUTABLE
float x = 0;
float y = 0;
float z = 0;
float w = 0;
#else
const float x = 0;
const float y = 0;
const float z = 0;
const float w = 0;
#endif
};
}

View File

@@ -1,8 +0,0 @@
//
// Created by josh on 12/25/2023.
//
#ifndef J3ML_VECTOR2_H
#define J3ML_VECTOR2_H
#endif //J3ML_VECTOR2_H

View File

@@ -1,8 +0,0 @@
//
// Created by josh on 12/25/2023.
//
#ifndef J3ML_VECTOR3_H
#define J3ML_VECTOR3_H
#endif //J3ML_VECTOR3_H

View File

@@ -1,8 +0,0 @@
//
// Created by josh on 12/25/2023.
//
#ifndef J3ML_VECTOR4_H
#define J3ML_VECTOR4_H
#endif //J3ML_VECTOR4_H

8
main.cpp Normal file
View File

@@ -0,0 +1,8 @@
#include <iostream>
int main(int argc, char** argv)
{
std::cout << "j3ml demo coming soon" << std::endl;
return 0;
}

View File

@@ -1,613 +1,6 @@
#include <types/vector.h>
#include <J3ML/LinearAlgebra.h>
#include <cassert>
namespace LinearAlgebra {
#pragma region vector2
Vector2::Vector2(): x(0), y(0)
{}
Vector2::Vector2(float X, float Y): x(X), y(Y)
{}
Vector2::Vector2(const Vector2& rhs): x(rhs.x), y(rhs.y)
{}
float Vector2::operator[](std::size_t index)
{
assert(index < 2);
if (index == 0) return x;
if (index == 1) return y;
return 0;
}
bool Vector2::IsWithinMarginOfError(const Vector2& rhs, float margin) const
{
return this->Distance(rhs) <= margin;
}
bool Vector2::operator==(const Vector2& rhs) const
{
return this->IsWithinMarginOfError(rhs);
}
bool Vector2::operator!=(const Vector2& rhs) const
{
return this->IsWithinMarginOfError(rhs) == false;
}
Vector2 Vector2::Min(const Vector2& min) const
{
return {
std::min(this->x, min.x),
std::min(this->y, min.y)
};
}
Vector2 Vector2::Max(const Vector2& max) const
{
return {
std::max(this->x, max.x),
std::max(this->y, max.y)
};
}
Vector2 Vector2::Clamp(const Vector2& min, const Vector2& max) const
{
return {
std::clamp(this->x, min.x, max.x),
std::clamp(this->y, min.y, max.y)
};
}
float Vector2::Distance(const Vector2& to) const
{
return ((*this)-to).Magnitude();
}
float Vector2::Length() const
{
return std::sqrt(LengthSquared());
}
float Vector2::LengthSquared() const
{
return (x*x + y*y);
}
float Vector2::Magnitude() const
{
return std::sqrt(LengthSquared());
}
float Vector2::Dot(const Vector2& rhs) const
{
auto a = this->Normalize();
auto b = rhs.Normalize();
return a.x * b.x + a.y * b.y;
}
Vector2 Vector2::Project(const Vector2& rhs) const
{
float scalar = this->Dot(rhs) / (rhs.Magnitude()*rhs.Magnitude());
return rhs * scalar;
}
Vector2 Vector2::Normalize() const
{
if (Length() > 0)
return {
x / Length(),
y / Length()
};
else
return {0,0};
}
Vector2 Vector2::Lerp(const Vector2& rhs, float alpha) const
{
return this->operator*(1.0f - alpha) + (rhs * alpha);
}
float Vector2::AngleBetween(const Vector2& rhs) const
{
auto numer = this->Dot(rhs);
auto denom = this->Magnitude() * rhs.Magnitude();
return std::acos(numer / denom);
}
float Vector2::AngleBetween(const Vector2& lhs, const Vector2& rhs)
{ return lhs.AngleBetween(rhs); }
Vector2 Vector2::operator+(const Vector2& rhs) const
{
return {this->x + rhs.x, this->y + rhs.y};
}
Vector2 Vector2::operator-(const Vector2& rhs) const
{
return {this->x - rhs.x, this->y - rhs.y};
}
Vector2 Vector2::operator*(float rhs) const
{
return {
this->x * rhs,
this->y * rhs
};
}
Vector2 Vector2::operator/(float rhs) const
{
return {
this->x / rhs,
this->y / rhs
};
}
Vector2 Vector2::operator-() const
{
return {-x, -y};
}
const Vector2 Vector2::Zero = {0, 0};
const Vector2 Vector2::Up = {0, -1};
const Vector2 Vector2::Down = {0, 1};
const Vector2 Vector2::Left = {-1, 0};
const Vector2 Vector2::Right = {1, 0};
#pragma endregion
#pragma region vector3
const Vector3 Vector3::Zero = {0,0,0};
const Vector3 Vector3::Up = {0, -1, 0};
const Vector3 Vector3::Down = {0, 1, 0};
const Vector3 Vector3::Left = {-1, 0, 0};
const Vector3 Vector3::Right = {1, 0, 0};
const Vector3 Vector3::Forward = {0, 0, -1};
const Vector3 Vector3::Backward = {0, 0, 1};
Vector3 Vector3::operator+(const Vector3& rhs) const
{
return {this->x + rhs.x, this->y + rhs.y, this->z + rhs.z};
}
Vector3 Vector3::operator-(const Vector3& rhs) const
{
return {
this->x- rhs.x,
this->y-rhs.y,
this->z-rhs.z
};
}
Vector3 Vector3::operator*(float rhs) const
{
return {
this->x * rhs,
this->y * rhs,
this->z * rhs
};
}
Vector3 Vector3::operator/(float rhs) const
{
return {
this->x / rhs,
this->y / rhs,
this->z / rhs
};
}
Vector3 Vector3::operator-() const
{
return {-x, -y, -z};
}
Vector4::Vector4(): x(0), y(0), z(0), w(0)
{}
Vector4::Vector4(float X, float Y, float Z, float W): x(X),y(Y),z(Z),w(W)
{ }
Vector3::Vector3(): x(0), y(0), z(0)
{}
Vector3::Vector3(float X, float Y, float Z): x(X), y(Y), z(Z)
{}
Vector3::Vector3(const Vector3& rhs)
{
this->x = rhs.x;
this->y = rhs.y;
this->z = rhs.z;
}
Vector3& Vector3::operator=(const Vector3& rhs)
{
this->x = rhs.x;
this->y = rhs.y;
this->z = rhs.z;
return *this;
}
float Vector3::operator[](std::size_t index) const
{
assert(index < 3);
if (index==0) return x;
if (index==1) return y;
if (index==2) return z;
return 0;
}
bool Vector3::IsWithinMarginOfError(const Vector3& rhs, float margin) const
{
return this->Distance(rhs) <= margin;
}
bool Vector3::operator==(const Vector3& rhs) const
{
return this->IsWithinMarginOfError(rhs);
}
bool Vector3::operator!=(const Vector3& rhs) const
{
return this->IsWithinMarginOfError(rhs) == false;
}
Vector3 Vector3::Min(const Vector3& min) const
{
return {
std::min(this->x, min.x),
std::min(this->y, min.y),
std::min(this->z, min.z)
};
}
Vector3 Vector3::Max(const Vector3& max) const
{
return {
std::max(this->x, max.x),
std::max(this->y, max.y),
std::max(this->z, max.z)
};
}
Vector3 Vector3::Clamp(const Vector3& min, const Vector3& max) const
{
return {
std::clamp(this->x, min.x, max.x),
std::clamp(this->y, min.y, max.y),
std::clamp(this->z, min.z, max.z)
};
}
float Vector3::Distance(const Vector3& to) const
{
return ((*this)-to).Magnitude();
}
float Vector3::Length() const
{
return std::sqrt(LengthSquared());
}
float Vector3::LengthSquared() const
{
return (x*x + y*y + z*z);
}
float Vector3::Magnitude() const
{
return std::sqrt(x*x + y*y + z*z);
}
float Vector3::Dot(const Vector3& rhs) const
{
auto a = this->Normalize();
auto b = rhs.Normalize();
return a.x * b.x +
a.y * b.y +
a.z * b.z;
}
Vector3 Vector3::Project(const Vector3& rhs) const
{
float scalar = this->Dot(rhs) / (rhs.Magnitude()*rhs.Magnitude());
return rhs * scalar;
}
Vector3 Vector3::Cross(const Vector3& rhs) const
{
return {
this->y * rhs.z - this->z * rhs.y,
this->z * rhs.x - this->x * rhs.z,
this->x * rhs.y - this->y * rhs.x
};
}
Vector3 Vector3::Normalize() const
{
if (Length() > 0)
return {
x / Length(),
y / Length(),
z / Length()
};
else
return {0,0,0};
}
Vector3 Vector3::Lerp(const Vector3& goal, float alpha) const
{
return this->operator*(1.0f - alpha) + (goal * alpha);
}
#pragma endregion
#pragma region vector4
bool Vector4::operator==(const Vector4& rhs) const
{
return this->IsWithinMarginOfError(rhs);
}
bool Vector4::operator!=(const Vector4& rhs) const
{
return this->IsWithinMarginOfError(rhs) == false;
}
Vector4 Vector4::min(const Vector4& min) const
{
return {
std::min(this->x, min.x),
std::min(this->y, min.y),
std::min(this->z, min.z),
std::min(this->w, min.w)
};
}
Vector4 Vector4::max(const Vector4& max) const
{
return {
std::max(this->x, max.x),
std::max(this->y, max.y),
std::max(this->z, max.z),
std::max(this->w, max.w)
};
}
Vector4 Vector4::clamp(const Vector4& min, const Vector4& max) const
{
return {
std::clamp(this->x, min.x, max.x),
std::clamp(this->y, min.y, max.y),
std::clamp(this->z, min.z, max.z),
std::clamp(this->w, min.w, max.w)
};
}
float Vector4::distance(const Vector4& to) const
{
return ( (*this) - to ).magnitude();
}
float Vector4::length() const
{
return std::sqrt(lengthSquared());
}
float Vector4::lengthSquared() const
{
return (x*x + y*y + z*z + w*w);
}
float Vector4::magnitude() const
{
return std::sqrt(x*x + y*y + z*z + w*w);
}
float Vector4::dot(const Vector4& rhs) const
{
auto a = this->normalize();
auto b = rhs.normalize();
return a.x * b.x +
a.y * b.y +
a.z * b.z +
a.w * b.w;
}
Vector4 Vector4::project(const Vector4& rhs) const
{
float scalar = this->dot(rhs) / (rhs.magnitude()* rhs.magnitude());
return rhs * scalar;
}
Vector4 Vector4::normalize() const
{
if (length() > 0)
return {
x / length(),
y / length(),
z / length(),
w / length()
};
else
return {0,0,0,0};
}
Vector4 Vector4::lerp(const Vector4& goal, float alpha) const
{
return this->operator*(1.0f - alpha) + (goal * alpha);
}
Vector4 Vector4::operator+(const Vector4& rhs) const
{
return {x+rhs.x, y+rhs.y, z+rhs.z, w+rhs.w};
}
Vector4 Vector4::operator-(const Vector4& rhs) const
{
return {x-rhs.x, y-rhs.y, z-rhs.z, w-rhs.w};
}
#pragma endregion
#pragma region EulerAngle
EulerAngle::EulerAngle(float pitch, float yaw, float roll): pitch(pitch), yaw(yaw), roll(roll)
{}
float EulerAngle::GetPitch(float pitch_limit) const
{ return std::clamp( std::remainderf(pitch,360.f), -pitch_limit, pitch_limit); }
float EulerAngle::GetYaw(float yaw_limit) const
{ return std::clamp(std::remainderf(yaw, 360.f), -yaw_limit, yaw_limit); }
float EulerAngle::GetRoll(float pitch_limit) const
{ return std::clamp( std::remainderf(pitch,360.f), -pitch_limit, pitch_limit); }
bool EulerAngle::operator==(const EulerAngle& a) const
{
return (pitch == a.pitch) && (yaw == a.yaw) && (roll == a.roll);
}
void EulerAngle::clamp()
{
if (this->pitch > 89.0f)
this->pitch = 89.0f;
if (this->pitch <= -89.0f)
this->pitch = -89.0f;
//TODO: Make this entirely seamless by getting the amount they rotated passed -180 and +180 by.
if (this->yaw <= -180.0f)
this->yaw = 180.0f;
if (this->yaw >= 180.01f)
this->yaw = -179.9f;
if (this->roll >= 360.0f)
this->roll = 0.0;
if (this->roll <= -360.0f)
this->roll = 0.0;
}
EulerAngle EulerAngle::movementAngle() const
{
EulerAngle a;
a.pitch = (cos(glm::radians(yaw)) * cos(glm::radians(pitch)));
a.yaw = -sin(glm::radians(pitch));
a.roll = (sin(glm::radians(yaw)) * cos(glm::radians(pitch)));
return a;
}
const Matrix3x3 Matrix3x3::Zero = Matrix3x3(0,0,0, 0,0,0, 0,0,0);
const Matrix3x3 Matrix3x3::Identity = Matrix3x3(1,0,0, 0,1,0, 0,0,1);
const Matrix3x3 Matrix3x3::NaN = Matrix3x3(NAN);
Matrix3x3::Matrix3x3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21,
float m22)
{
this->elems[0][0] = m00;
this->elems[0][1] = m01;
this->elems[0][2] = m02;
this->elems[1][0] = m10;
this->elems[1][1] = m11;
this->elems[1][2] = m12;
this->elems[2][0] = m20;
this->elems[2][1] = m21;
this->elems[2][2] = m22;
}
Vector3 Matrix3x3::GetRow(int index) const
{
float x = this->elems[index][0];
float y = this->elems[index][1];
float z = this->elems[index][2];
return {x,y,z};
}
Vector3 Matrix3x3::GetColumn(int index) const
{
float x = this->elems[0][index];
float y = this->elems[1][index];
float z = this->elems[2][index];
return {x,y,z};
}
float Matrix3x3::At(int x, int y) const
{
return this->elems[x][y];
}
Vector3 Matrix3x3::operator*(const Vector3& rhs) const
{
return {
At(0,0) * rhs.x + At(0, 1) * rhs.y + At(0, 2) * rhs.z,
At(1, 0) * rhs.x + At(1, 1) * rhs.y + At(1, 2) * rhs.z,
At(2, 0) * rhs.x + At(2, 1) * rhs.y + At(2,2) * rhs.z
};
}
Matrix3x3 Matrix3x3::operator*(const Matrix3x3& rhs) const
{
//Matrix3x3 r;
auto m00 = At(0, 0) * rhs.At(0, 0) + At(0, 1) * rhs.At(1, 0) + At(0, 2) * rhs.At(2, 0);
auto m01 = At(0, 0) * rhs.At(0, 1) + At(0, 1) * rhs.At(1, 1) + At(0, 2) * rhs.At(2, 1);
auto m02 = At(0, 0) * rhs.At(0, 2) + At(0, 1) * rhs.At(1, 2) + At(0, 2) * rhs.At(2, 2);
auto m10 = At(1, 0) * rhs.At(0, 0) + At(1, 1) * rhs.At(1, 0) + At(1, 2) * rhs.At(2, 0);
auto m11 = At(1, 0) * rhs.At(0, 1) + At(1, 1) * rhs.At(1, 1) + At(1, 2) * rhs.At(2, 1);
auto m12 = At(1, 0) * rhs.At(0, 2) + At(1, 1) * rhs.At(1, 2) + At(1, 2) * rhs.At(2,2);
auto m20 = At(2, 0) * rhs.At(0, 0) + At(2, 1) * rhs.At(1, 0) + At(2,2) * rhs.At(2, 0);
auto m21 = At(2, 0) * rhs.At(0, 1) + At(2, 1) * rhs.At(1, 1) + At(2,2) * rhs.At(2, 1);
auto m22 = At(2, 0) * rhs.At(0, 2) + At(2, 1) * rhs.At(1, 2) + At(2,2) * rhs.At(2,2);
return Matrix3x3({m00, m01, m02}, {m10, m11, m12}, {m20, m21, m22});
}
Quaternion Quaternion::operator-() const
{
return {-x, -y, -z, -w};
}
#pragma endregion
#pragma region Matrix2x2
#pragma endregion
#pragma region Matrix3x3
#pragma endregion
#pragma region Matrix4x4
#pragma endregion
#pragma region Quaternion
#pragma endregion
}

View File

@@ -0,0 +1,50 @@
#include <J3ML/LinearAlgebra/EulerAngle.h>
#include <cmath>
#include <algorithm>
#pragma region EulerAngle
namespace LinearAlgebra {
EulerAngle::EulerAngle(float pitch, float yaw, float roll): pitch(pitch), yaw(yaw), roll(roll)
{}
float EulerAngle::GetPitch(float pitch_limit) const
{ return std::clamp( std::remainderf(pitch,360.f), -pitch_limit, pitch_limit); }
float EulerAngle::GetYaw(float yaw_limit) const
{ return std::clamp(std::remainderf(yaw, 360.f), -yaw_limit, yaw_limit); }
float EulerAngle::GetRoll(float pitch_limit) const
{ return std::clamp( std::remainderf(pitch,360.f), -pitch_limit, pitch_limit); }
bool EulerAngle::operator==(const EulerAngle& a) const
{
return (pitch == a.pitch) && (yaw == a.yaw) && (roll == a.roll);
}
void EulerAngle::clamp()
{
if (this->pitch > 89.0f)
this->pitch = 89.0f;
if (this->pitch <= -89.0f)
this->pitch = -89.0f;
//TODO: Make this entirely seamless by getting the amount they rotated passed -180 and +180 by.
if (this->yaw <= -180.0f)
this->yaw = 180.0f;
if (this->yaw >= 180.01f)
this->yaw = -179.9f;
if (this->roll >= 360.0f)
this->roll = 0.0;
if (this->roll <= -360.0f)
this->roll = 0.0;
}
EulerAngle EulerAngle::movementAngle() const
{
EulerAngle a;
a.pitch = (cos(Math::Radians(yaw)) * cos(Math::Radians(pitch)));
a.yaw = -sin(Math::Radians(pitch));
a.roll = (sin(Math::Radians(yaw)) * cos(Math::Radians(pitch)));
return a;
}
}

View File

@@ -0,0 +1,5 @@
#include <J3ML/LinearAlgebra/Matrix2x2.h>
namespace LinearAlgebra {
}

View File

@@ -0,0 +1,99 @@
#include <J3ML/LinearAlgebra/Matrix3x3.h>
namespace LinearAlgebra {
const Matrix3x3 Matrix3x3::Zero = Matrix3x3(0, 0, 0, 0, 0, 0, 0, 0, 0);
const Matrix3x3 Matrix3x3::Identity = Matrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);
const Matrix3x3 Matrix3x3::NaN = Matrix3x3(NAN);
Matrix3x3::Matrix3x3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21,
float m22) {
this->elems[0][0] = m00;
this->elems[0][1] = m01;
this->elems[0][2] = m02;
this->elems[1][0] = m10;
this->elems[1][1] = m11;
this->elems[1][2] = m12;
this->elems[2][0] = m20;
this->elems[2][1] = m21;
this->elems[2][2] = m22;
}
Vector3 Matrix3x3::GetRow(int index) const {
float x = this->elems[index][0];
float y = this->elems[index][1];
float z = this->elems[index][2];
return {x, y, z};
}
Vector3 Matrix3x3::GetColumn(int index) const {
float x = this->elems[0][index];
float y = this->elems[1][index];
float z = this->elems[2][index];
return {x, y, z};
}
float Matrix3x3::At(int x, int y) const {
return this->elems[x][y];
}
Vector3 Matrix3x3::operator*(const Vector3 &rhs) const {
return {
At(0, 0) * rhs.x + At(0, 1) * rhs.y + At(0, 2) * rhs.z,
At(1, 0) * rhs.x + At(1, 1) * rhs.y + At(1, 2) * rhs.z,
At(2, 0) * rhs.x + At(2, 1) * rhs.y + At(2, 2) * rhs.z
};
}
Matrix3x3 Matrix3x3::operator*(const Matrix3x3 &rhs) const {
//Matrix3x3 r;
auto m00 = At(0, 0) * rhs.At(0, 0) + At(0, 1) * rhs.At(1, 0) + At(0, 2) * rhs.At(2, 0);
auto m01 = At(0, 0) * rhs.At(0, 1) + At(0, 1) * rhs.At(1, 1) + At(0, 2) * rhs.At(2, 1);
auto m02 = At(0, 0) * rhs.At(0, 2) + At(0, 1) * rhs.At(1, 2) + At(0, 2) * rhs.At(2, 2);
auto m10 = At(1, 0) * rhs.At(0, 0) + At(1, 1) * rhs.At(1, 0) + At(1, 2) * rhs.At(2, 0);
auto m11 = At(1, 0) * rhs.At(0, 1) + At(1, 1) * rhs.At(1, 1) + At(1, 2) * rhs.At(2, 1);
auto m12 = At(1, 0) * rhs.At(0, 2) + At(1, 1) * rhs.At(1, 2) + At(1, 2) * rhs.At(2, 2);
auto m20 = At(2, 0) * rhs.At(0, 0) + At(2, 1) * rhs.At(1, 0) + At(2, 2) * rhs.At(2, 0);
auto m21 = At(2, 0) * rhs.At(0, 1) + At(2, 1) * rhs.At(1, 1) + At(2, 2) * rhs.At(2, 1);
auto m22 = At(2, 0) * rhs.At(0, 2) + At(2, 1) * rhs.At(1, 2) + At(2, 2) * rhs.At(2, 2);
return Matrix3x3({m00, m01, m02}, {m10, m11, m12}, {m20, m21, m22});
}
Matrix3x3::Matrix3x3(float val) {
this->elems[0][0] = val;
this->elems[0][1] = val;
this->elems[0][2] = val;
this->elems[1][0] = val;
this->elems[1][1] = val;
this->elems[1][2] = val;
this->elems[2][0] = val;
this->elems[2][1] = val;
this->elems[2][2] = val;
}
Matrix3x3::Matrix3x3(const Vector3 &r1, const Vector3 &r2, const Vector3 &r3) {
this->elems[0][0] = r1.x;
this->elems[0][1] = r1.y;
this->elems[0][2] = r1.z;
this->elems[1][0] = r2.x;
this->elems[1][1] = r2.y;
this->elems[1][2] = r2.z;
this->elems[2][0] = r3.x;
this->elems[2][1] = r3.y;
this->elems[2][2] = r3.z;
}
}

View File

@@ -0,0 +1 @@
#include <J3ML/LinearAlgebra/Matrix4x4.h>

View File

@@ -0,0 +1,8 @@
#include <J3ML/LinearAlgebra/Quaternion.h>
namespace LinearAlgebra {
Quaternion Quaternion::operator-() const
{
return {-x, -y, -z, -w};
}
}

View File

@@ -0,0 +1,175 @@
#include <J3ML/LinearAlgebra/Vector2.h>
namespace LinearAlgebra {
#pragma region vector2
Vector2::Vector2(): x(0), y(0)
{}
Vector2::Vector2(float X, float Y): x(X), y(Y)
{}
Vector2::Vector2(const Vector2& rhs): x(rhs.x), y(rhs.y)
{}
float Vector2::operator[](std::size_t index)
{
assert(index < 2);
if (index == 0) return x;
if (index == 1) return y;
return 0;
}
bool Vector2::IsWithinMarginOfError(const Vector2& rhs, float margin) const
{
return this->Distance(rhs) <= margin;
}
bool Vector2::operator==(const Vector2& rhs) const
{
return this->IsWithinMarginOfError(rhs);
}
bool Vector2::operator!=(const Vector2& rhs) const
{
return this->IsWithinMarginOfError(rhs) == false;
}
Vector2 Vector2::Min(const Vector2& min) const
{
return {
std::min(this->x, min.x),
std::min(this->y, min.y)
};
}
Vector2 Vector2::Max(const Vector2& max) const
{
return {
std::max(this->x, max.x),
std::max(this->y, max.y)
};
}
Vector2 Vector2::Clamp(const Vector2& min, const Vector2& max) const
{
return {
std::clamp(this->x, min.x, max.x),
std::clamp(this->y, min.y, max.y)
};
}
float Vector2::Distance(const Vector2& to) const
{
return ((*this)-to).Magnitude();
}
float Vector2::Length() const
{
return std::sqrt(LengthSquared());
}
float Vector2::LengthSquared() const
{
return (x*x + y*y);
}
float Vector2::Magnitude() const
{
return std::sqrt(LengthSquared());
}
float Vector2::Dot(const Vector2& rhs) const
{
auto a = this->Normalize();
auto b = rhs.Normalize();
return a.x * b.x + a.y * b.y;
}
Vector2 Vector2::Project(const Vector2& rhs) const
{
float scalar = this->Dot(rhs) / (rhs.Magnitude()*rhs.Magnitude());
return rhs * scalar;
}
Vector2 Vector2::Normalize() const
{
if (Length() > 0)
return {
x / Length(),
y / Length()
};
else
return {0,0};
}
Vector2 Vector2::Lerp(const Vector2& rhs, float alpha) const
{
return this->operator*(1.0f - alpha) + (rhs * alpha);
}
float Vector2::AngleBetween(const Vector2& rhs) const
{
auto numer = this->Dot(rhs);
auto denom = this->Magnitude() * rhs.Magnitude();
return std::acos(numer / denom);
}
float Vector2::AngleBetween(const Vector2& lhs, const Vector2& rhs)
{ return lhs.AngleBetween(rhs); }
Vector2 Vector2::operator+(const Vector2& rhs) const
{
return {this->x + rhs.x, this->y + rhs.y};
}
Vector2 Vector2::operator-(const Vector2& rhs) const
{
return {this->x - rhs.x, this->y - rhs.y};
}
Vector2 Vector2::operator*(float rhs) const
{
return {
this->x * rhs,
this->y * rhs
};
}
Vector2 Vector2::operator/(float rhs) const
{
return {
this->x / rhs,
this->y / rhs
};
}
Vector2 Vector2::operator-() const
{
return {-x, -y};
}
const Vector2 Vector2::Zero = {0, 0};
const Vector2 Vector2::Up = {0, -1};
const Vector2 Vector2::Down = {0, 1};
const Vector2 Vector2::Left = {-1, 0};
const Vector2 Vector2::Right = {1, 0};
float Vector2::GetX() const { return x; }
float Vector2::GetY() const { return y; }
float Vector2::LengthSquared(const Vector2 &of) { return of.LengthSquared(); }
Vector2 Vector2::Min(const Vector2 &value, const Vector2 &minimum) { return value.Min(minimum); }
Vector2 Vector2::Max(const Vector2 &value, const Vector2 &maximum) { return value.Max(maximum);}
float Vector2::Length(const Vector2 &of) { return of.Length(); }
#pragma endregion
}

View File

@@ -0,0 +1,198 @@
#include <J3ML/LinearAlgebra/Vector3.h>
#include <algorithm>
#include <cassert>
namespace LinearAlgebra {
#pragma region vector3
const Vector3 Vector3::Zero = {0,0,0};
const Vector3 Vector3::Up = {0, -1, 0};
const Vector3 Vector3::Down = {0, 1, 0};
const Vector3 Vector3::Left = {-1, 0, 0};
const Vector3 Vector3::Right = {1, 0, 0};
const Vector3 Vector3::Forward = {0, 0, -1};
const Vector3 Vector3::Backward = {0, 0, 1};
Vector3 Vector3::operator+(const Vector3& rhs) const
{
return {this->x + rhs.x, this->y + rhs.y, this->z + rhs.z};
}
Vector3 Vector3::operator-(const Vector3& rhs) const
{
return {
this->x- rhs.x,
this->y-rhs.y,
this->z-rhs.z
};
}
Vector3 Vector3::operator*(float rhs) const
{
return {
this->x * rhs,
this->y * rhs,
this->z * rhs
};
}
Vector3 Vector3::operator/(float rhs) const
{
return {
this->x / rhs,
this->y / rhs,
this->z / rhs
};
}
Vector3 Vector3::operator-() const
{
return {-x, -y, -z};
}
Vector3::Vector3(): x(0), y(0), z(0)
{}
Vector3::Vector3(float X, float Y, float Z): x(X), y(Y), z(Z)
{}
Vector3::Vector3(const Vector3& rhs)
{
this->x = rhs.x;
this->y = rhs.y;
this->z = rhs.z;
}
Vector3& Vector3::operator=(const Vector3& rhs)
{
this->x = rhs.x;
this->y = rhs.y;
this->z = rhs.z;
return *this;
}
float Vector3::operator[](std::size_t index) const
{
assert(index < 3);
if (index==0) return x;
if (index==1) return y;
if (index==2) return z;
return 0;
}
bool Vector3::IsWithinMarginOfError(const Vector3& rhs, float margin) const
{
return this->Distance(rhs) <= margin;
}
bool Vector3::operator==(const Vector3& rhs) const
{
return this->IsWithinMarginOfError(rhs);
}
bool Vector3::operator!=(const Vector3& rhs) const
{
return this->IsWithinMarginOfError(rhs) == false;
}
Vector3 Vector3::Min(const Vector3& min) const
{
return {
std::min(this->x, min.x),
std::min(this->y, min.y),
std::min(this->z, min.z)
};
}
Vector3 Vector3::Max(const Vector3& max) const
{
return {
std::max(this->x, max.x),
std::max(this->y, max.y),
std::max(this->z, max.z)
};
}
Vector3 Vector3::Clamp(const Vector3& min, const Vector3& max) const
{
return {
std::clamp(this->x, min.x, max.x),
std::clamp(this->y, min.y, max.y),
std::clamp(this->z, min.z, max.z)
};
}
float Vector3::Distance(const Vector3& to) const
{
return ((*this)-to).Magnitude();
}
float Vector3::Length() const
{
return std::sqrt(LengthSquared());
}
float Vector3::LengthSquared() const
{
return (x*x + y*y + z*z);
}
float Vector3::Magnitude() const
{
return std::sqrt(x*x + y*y + z*z);
}
float Vector3::Dot(const Vector3& rhs) const
{
auto a = this->Normalize();
auto b = rhs.Normalize();
return a.x * b.x +
a.y * b.y +
a.z * b.z;
}
Vector3 Vector3::Project(const Vector3& rhs) const
{
float scalar = this->Dot(rhs) / (rhs.Magnitude()*rhs.Magnitude());
return rhs * scalar;
}
Vector3 Vector3::Cross(const Vector3& rhs) const
{
return {
this->y * rhs.z - this->z * rhs.y,
this->z * rhs.x - this->x * rhs.z,
this->x * rhs.y - this->y * rhs.x
};
}
Vector3 Vector3::Normalize() const
{
if (Length() > 0)
return {
x / Length(),
y / Length(),
z / Length()
};
else
return {0,0,0};
}
Vector3 Vector3::Lerp(const Vector3& goal, float alpha) const
{
return this->operator*(1.0f - alpha) + (goal * alpha);
}
float Vector3::GetX() const { return x;}
float Vector3::GetY() const { return y;}
float Vector3::GetZ() const { return z;}
#pragma endregion
}

View File

@@ -0,0 +1,123 @@
#include <J3ML/LinearAlgebra/Vector4.h>
#pragma region vector4
#include <cmath>
#include <algorithm>
namespace LinearAlgebra {
Vector4::Vector4(): x(0), y(0), z(0), w(0)
{}
Vector4::Vector4(float X, float Y, float Z, float W): x(X),y(Y),z(Z),w(W)
{ }
bool Vector4::operator==(const Vector4& rhs) const
{
return this->IsWithinMarginOfError(rhs);
}
bool Vector4::operator!=(const Vector4& rhs) const
{
return this->IsWithinMarginOfError(rhs) == false;
}
Vector4 Vector4::Min(const Vector4& min) const
{
return {
std::min(this->x, min.x),
std::min(this->y, min.y),
std::min(this->z, min.z),
std::min(this->w, min.w)
};
}
Vector4 Vector4::Max(const Vector4& max) const
{
return {
std::max(this->x, max.x),
std::max(this->y, max.y),
std::max(this->z, max.z),
std::max(this->w, max.w)
};
}
Vector4 Vector4::Clamp(const Vector4& min, const Vector4& max) const
{
return {
std::clamp(this->x, min.x, max.x),
std::clamp(this->y, min.y, max.y),
std::clamp(this->z, min.z, max.z),
std::clamp(this->w, min.w, max.w)
};
}
float Vector4::Distance(const Vector4& to) const
{
return ( (*this) - to ).Magnitude();
}
float Vector4::Length() const
{
return std::sqrt(LengthSquared());
}
float Vector4::LengthSquared() const
{
return (x*x + y*y + z*z + w*w);
}
float Vector4::Magnitude() const
{
return std::sqrt(x*x + y*y + z*z + w*w);
}
float Vector4::Dot(const Vector4& rhs) const
{
auto a = this->Normalize();
auto b = rhs.Normalize();
return a.x * b.x +
a.y * b.y +
a.z * b.z +
a.w * b.w;
}
Vector4 Vector4::Project(const Vector4& rhs) const
{
float scalar = this->Dot(rhs) / (rhs.Magnitude()* rhs.Magnitude());
return rhs * scalar;
}
Vector4 Vector4::Normalize() const
{
if (Length() > 0)
return {
x / Length(),
y / Length(),
z / Length(),
w / Length()
};
else
return {0,0,0,0};
}
Vector4 Vector4::Lerp(const Vector4& goal, float alpha) const
{
return this->operator*(1.0f - alpha) + (goal * alpha);
}
Vector4 Vector4::operator+(const Vector4& rhs) const
{
return {x+rhs.x, y+rhs.y, z+rhs.z, w+rhs.w};
}
Vector4 Vector4::operator-(const Vector4& rhs) const
{
return {x-rhs.x, y-rhs.y, z-rhs.z, w-rhs.w};
}
}
#pragma endregion

19
tests/CMakeLists.txt Normal file
View File

@@ -0,0 +1,19 @@
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.11.0
)
FetchContent_MakeAvailable(googletest)
add_library(GTest::GTest INTERFACE IMPORTED)
target_link_libraries(GTest::GTest INTERFACE gtest_main)
file(GLOB_RECURSE TEST_SRC "*.cpp")
add_executable(Test ${TEST_SRC})
target_link_libraries(Test PUBLIC J3ML)
#find_package(GTest REQUIRED)
target_link_libraries(Test PRIVATE GTest::GTest)
include_directories("include")
add_test(NAME "J3MLTestSuite" COMMAND J3MLTestSuite)

7
tests/tests.cpp Normal file
View File

@@ -0,0 +1,7 @@
#include <gtest/gtest.h>
GTEST_API_ int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}