Compare commits
22 Commits
Prerelease
...
Prerelease
Author | SHA1 | Date | |
---|---|---|---|
fd2e3f894a | |||
efead577a5 | |||
92a20a9347 | |||
00c0d30d6d | |||
8fa94c1519 | |||
e18a2634de | |||
cb5e6b4f99 | |||
9a5f12e505 | |||
d37b685df9 | |||
792f7801bb | |||
12bf687f33 | |||
432fa32f57 | |||
0597b4c937 | |||
69ca7c5c05 | |||
c858d3b889 | |||
35fded8ec0 | |||
6b78a0b731 | |||
ea61b5ea51 | |||
a32719cdeb | |||
19b5630deb | |||
5080305965 | |||
40e69d5c4f |
@@ -57,7 +57,11 @@ add_library(J3ML SHARED ${J3ML_SRC}
|
||||
include/J3ML/Geometry/AABB2D.h
|
||||
src/J3ML/Geometry/Polygon.cpp
|
||||
include/J3ML/Geometry/Polyhedron.h
|
||||
src/J3ML/Geometry/Polyhedron.cpp)
|
||||
src/J3ML/Geometry/Polyhedron.cpp
|
||||
include/J3ML/Algorithm/RNG.h
|
||||
src/J3ML/Algorithm/RNG.cpp
|
||||
include/J3ML/Algorithm/Spring.h
|
||||
include/J3ML/Algorithm/DifferentialSolvers.h)
|
||||
set_target_properties(J3ML PROPERTIES LINKER_LANGUAGE CXX)
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} DESTINATION lib/${PROJECT_NAME})
|
||||
|
36
include/J3ML/Algorithm/DifferentialSolvers.h
Normal file
36
include/J3ML/Algorithm/DifferentialSolvers.h
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Created by dawsh on 2/8/24.
|
||||
//
|
||||
|
||||
namespace J3ML::Algorithm
|
||||
{
|
||||
/// Implementations for a variety of Differential Equation Solving algorithms
|
||||
namespace Solvers
|
||||
{
|
||||
|
||||
// Consider a differential equation
|
||||
// dy/dx = (x + y + xy)
|
||||
float eq(float x, float y)
|
||||
{
|
||||
return (x + y + x*y);
|
||||
}
|
||||
|
||||
float euler(float x0, float y, float h, float x)
|
||||
{
|
||||
float temp = -0.f;
|
||||
// Iterating till the point at which we need approximation
|
||||
while (x0 < x) {
|
||||
temp = y;
|
||||
y = y + h * eq(x0, y);
|
||||
x0 = x0 + h;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
class EulerMethodSolver {};
|
||||
class SemiImplicitEulerMethodSolver {};
|
||||
class GaussSeidelMethodSolver {};
|
||||
class GradientDescentSolver {};
|
||||
class VerletIntegrationSolver {};
|
||||
}
|
||||
}
|
99
include/J3ML/Algorithm/RNG.h
Normal file
99
include/J3ML/Algorithm/RNG.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "J3ML/J3ML.h"
|
||||
|
||||
namespace J3ML::Algorithm
|
||||
{
|
||||
/** @brief A linear congruential random number generator.
|
||||
|
||||
Uses D.H. Lehmer's Linear Congruential Method (1949) for generating random numbers.
|
||||
Supports both Multiplicative Congruential Method (increment==0) and
|
||||
Mixed Congruential Method (increment!=0)
|
||||
It is perhaps the simplest and fastest method to generate pseudo-random numbers on
|
||||
a computer. Per default uses the values for Minimal Standard LCG.
|
||||
http://en.wikipedia.org/wiki/Linear_congruential_generator
|
||||
http://www.math.rutgers.edu/~greenfie/currentcourses/sem090/pdfstuff/jp.pdf
|
||||
|
||||
Pros:
|
||||
<ul>
|
||||
<li> Easy to implement.
|
||||
<li> Fast.
|
||||
</ul>
|
||||
|
||||
Cons:
|
||||
<ul>
|
||||
<li> NOT safe for cryptography because of the easily calculatable sequential
|
||||
correlation between successive calls. A case study:
|
||||
http://www.cigital.com/papers/download/developer_gambling.php
|
||||
|
||||
<li> Tends to have less random low-order bits (compared to the high-order bits)
|
||||
Thus, NEVER do something like this:
|
||||
|
||||
u32 numBetween1And10 = 1 + LCGRand.Int() % 10;
|
||||
|
||||
Instead, take into account EVERY bit of the generated number, like this:
|
||||
|
||||
u32 numBetween1And10 = 1 + (int)(10.0 * (double)LCGRand.Int()
|
||||
/(LCGRand.Max()+1.0));
|
||||
or simply
|
||||
|
||||
u32 numBetween1And10 = LCGRand.Float(1.f, 10.f);
|
||||
</ul> */
|
||||
|
||||
|
||||
class RNG {
|
||||
public:
|
||||
/// Initializes the generator from the current system clock.
|
||||
RNG();
|
||||
RNG(u32 seed, u32 multiplier = 69621,
|
||||
u32 increment = 0, u32 modulus = 0x7FFFFFFF) // 2^31 - 1
|
||||
{
|
||||
Seed(seed, multiplier, increment, modulus);
|
||||
}
|
||||
/// Reinitializes the generator to the new settings.
|
||||
void Seed(u32 seed, u32 multiplier, u32 increment, u32 modulus = 0x7FFFFFFF);
|
||||
/// Returns a random integer picked uniformly in the range [0, MaxInt()]
|
||||
u32 Int();
|
||||
/// Returns the biggest number the generator can yield. [modulus - 1]
|
||||
u32 MaxInt() const { return modulus - 1;}
|
||||
/// Returns a random integer picked uniformly in the range [0, 2^32-1].
|
||||
/// @note The configurable modulus and increment are not used by this function, but are always increment == 0, modulus=2^32
|
||||
u32 IntFast();
|
||||
/// Returns a random integer picked uniformly in the range [a, b]
|
||||
/// @param a Lower bound, inclusive.
|
||||
/// @param b Upper bound, inclusive.
|
||||
/// @return A random integer picked uniformly in the range [a, b]
|
||||
int Int(int a, int b);
|
||||
|
||||
/// Returns a random float picked uniformly in the range [0, 1].
|
||||
float Float();
|
||||
|
||||
/// Returns a random float picked uniformly in the range [0, 1].
|
||||
/// @note this is much slower than Float()! Prefer that function if possible.
|
||||
float Float01Incl();
|
||||
|
||||
/// Returns a random float picked uniformly in the range ]-1, 1[.
|
||||
/// @note This function has one more bit of randomness compared to Float(), but has a theoretical bias
|
||||
/// towards 0.0, since floating point has two representations for 0 (+0, and -0).
|
||||
float FloatNeg1_1();
|
||||
|
||||
/// Returns a random float picked uniformly in the range [a, b[.
|
||||
/// @param a Lower bound, inclusive.
|
||||
/// @param b Upper bound, exclusive.
|
||||
/// @return A random float picked uniformly in the range [a, b[
|
||||
/// @note This function is slower than RNG::FloatIncl(). If you don't care about the open/closed interval, prefer that function.
|
||||
float Float(float a, float b);
|
||||
|
||||
/// Returns a random float picked uniformly in the range [a, b].
|
||||
/// @param a Lower bound, inclusive.
|
||||
/// @param b Upper bound, inclusive.
|
||||
/// @return A random float picked uniformly in the range [a, b]
|
||||
float FloatIncl(float a, float b);
|
||||
|
||||
u32 multiplier;
|
||||
u32 increment;
|
||||
u32 modulus;
|
||||
u32 lastNumber;
|
||||
};
|
||||
}
|
21
include/J3ML/Algorithm/Spring.h
Normal file
21
include/J3ML/Algorithm/Spring.h
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// Created by dawsh on 2/8/24.
|
||||
//
|
||||
|
||||
namespace J3ML::Algorithm
|
||||
{
|
||||
// Numerical model of a "Spring" object
|
||||
// Simulates any oscillating system i.e. a mass suspended from a spring.
|
||||
class Spring
|
||||
{
|
||||
float Dampening;
|
||||
float Stiffness;
|
||||
float Goal;
|
||||
float RestLength = 1.f;
|
||||
|
||||
bool Overdamped() const;
|
||||
bool Undamped() const;
|
||||
bool Underdamped() const;
|
||||
bool CriticallyDamped() const;
|
||||
};
|
||||
}
|
@@ -3,9 +3,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Geometry {
|
||||
using Vector2 = LinearAlgebra::Vector2;
|
||||
using Vector3 = LinearAlgebra::Vector3;
|
||||
namespace J3ML::Geometry {
|
||||
using Vector2 = J3ML::LinearAlgebra::Vector2;
|
||||
using Vector3 = J3ML::LinearAlgebra::Vector3;
|
||||
|
||||
class LineSegment2D
|
||||
{
|
||||
|
@@ -22,9 +22,8 @@
|
||||
|
||||
|
||||
|
||||
namespace Geometry
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
|
||||
using namespace LinearAlgebra;
|
||||
// A 3D axis-aligned bounding box
|
||||
// This data structure can be used to represent coarse bounds of objects, in situations where detailed triangle-level
|
||||
@@ -35,36 +34,74 @@ namespace Geometry
|
||||
// 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
|
||||
{
|
||||
static AABB FromCenterAndSize(const Vector3 FromSize);
|
||||
float MinX();
|
||||
// Returns the smallest sphere that contains this AABB.
|
||||
// This function computes the minimal volume sphere that contains all the points inside this AABB
|
||||
class AABB {
|
||||
public:
|
||||
Vector3 minPoint;
|
||||
Vector3 maxPoint;
|
||||
|
||||
static int NumFaces() { return 6; }
|
||||
|
||||
static int NumEdges() { return 12; }
|
||||
|
||||
static int NumVertices() { return 8; }
|
||||
|
||||
static AABB FromCenterAndSize(const Vector3 ¢er, const Vector3 &size);
|
||||
|
||||
float MinX() const;
|
||||
|
||||
float MinY() const;
|
||||
|
||||
float MinZ() const;
|
||||
|
||||
float MaxX() const;
|
||||
|
||||
float MaxY() const;
|
||||
|
||||
float MaxZ() const;
|
||||
|
||||
/// Returns the smallest sphere that contains this AABB.
|
||||
/// This function computes the minimal volume sphere that contains all the points inside this AABB
|
||||
Sphere MinimalEnclosingSphere() const;
|
||||
// Returns the largest sphere that can fit inside this AABB
|
||||
// This function computes the largest sphere that can fit inside this AABB.
|
||||
|
||||
Vector3 HalfSize() const;
|
||||
|
||||
/// Returns the largest sphere that can fit inside this AABB
|
||||
/// This function computes the largest sphere that can fit inside this AABB.
|
||||
Sphere MaximalContainedSphere() const;
|
||||
Vector3 GetCentroid() const;
|
||||
|
||||
bool IsFinite() const;
|
||||
|
||||
Vector3 Centroid() const;
|
||||
|
||||
Vector3 Size() const;
|
||||
|
||||
// Quickly returns an arbitrary point inside this AABB
|
||||
Vector3 AnyPointFast() const;
|
||||
|
||||
Vector3 PointInside(float x, float y, float z) const;
|
||||
|
||||
// Returns an edge of this AABB
|
||||
LineSegment Edge(int edgeIndex) const;
|
||||
Vector3 CornerPoint(int cornerIndex);
|
||||
Vector3 ExtremePoint(const Vector3& direction) const;
|
||||
Vector3 ExtremePoint(const Vector3& direction, float projectionDistance);
|
||||
|
||||
Vector3 CornerPoint(int cornerIndex) const;
|
||||
|
||||
Vector3 ExtremePoint(const Vector3 &direction) const;
|
||||
|
||||
Vector3 ExtremePoint(const Vector3 &direction, float &projectionDistance);
|
||||
|
||||
Vector3 PointOnEdge(int edgeIndex, float u) const;
|
||||
|
||||
Vector3 FaceCenterPoint(int faceIndex) const;
|
||||
|
||||
Vector3 FacePoint(int faceIndex, float u, float v) const;
|
||||
|
||||
Vector3 FaceNormal(int faceIndex) const;
|
||||
Plane FacePlane(int faceIndex);
|
||||
static AABB MinimalEnclosingAABB(const Vector3* pointArray, int numPoints);
|
||||
Vector3 GetSize();
|
||||
Vector3 GetVolume();
|
||||
float GetVolumeCubed();
|
||||
float GetSurfaceArea();
|
||||
|
||||
Plane FacePlane(int faceIndex) const;
|
||||
|
||||
static AABB MinimalEnclosingAABB(const Vector3 *pointArray, int numPoints);
|
||||
float GetVolume() const;
|
||||
float GetSurfaceArea() const;
|
||||
Vector3 GetRandomPointInside();
|
||||
Vector3 GetRandomPointOnSurface();
|
||||
Vector3 GetRandomPointOnEdge();
|
||||
@@ -96,5 +133,26 @@ namespace Geometry
|
||||
TriangleMesh Triangulate(int numFacesX, int numFacesY, int numFacesZ, bool ccwIsFrontFacing) const;
|
||||
AABB Intersection(const AABB& rhs) const;
|
||||
bool IntersectLineAABB(const Vector3& linePos, const Vector3& lineDir, float tNear, float tFar) const;
|
||||
|
||||
|
||||
void SetFrom(const Vector3 *pVector3, int i);
|
||||
|
||||
void SetFromCenterAndSize(const Vector3 ¢er, const Vector3 &size);
|
||||
|
||||
void SetFrom(const OBB &obb);
|
||||
|
||||
void SetFrom(const Sphere &s);
|
||||
|
||||
Vector3 GetRandomPointInside() const;
|
||||
|
||||
void SetNegativeInfinity();
|
||||
|
||||
void Enclose(const Vector3 &point);
|
||||
|
||||
void Enclose(const Vector3 &aabbMinPt, const Vector3 &aabbMaxPt);
|
||||
|
||||
void Enclose(const LineSegment &lineSegment);
|
||||
|
||||
void Enclose(const OBB &obb);
|
||||
};
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <J3ML/LinearAlgebra/Vector2.h>
|
||||
|
||||
namespace Geometry
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
using LinearAlgebra::Vector2;
|
||||
// CaveGame AABB
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include "LineSegment.h"
|
||||
#include <J3ML/LinearAlgebra/Vector3.h>
|
||||
|
||||
namespace Geometry
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
using namespace LinearAlgebra;
|
||||
class Capsule
|
||||
@@ -13,10 +13,10 @@ namespace Geometry
|
||||
// Specifies the radius of this capsule
|
||||
float r;
|
||||
|
||||
Capsule() {}
|
||||
Capsule();
|
||||
Capsule(const LineSegment& endPoints, float radius);
|
||||
Capsule(const Vector3& bottomPt, const Vector3& topPt, float radius);
|
||||
bool IsDegenerate()const;
|
||||
bool IsDegenerate() const;
|
||||
float Height() const;
|
||||
float Diameter() const;
|
||||
Vector3 Bottom() const;
|
||||
|
@@ -6,9 +6,11 @@
|
||||
#include "Plane.h"
|
||||
#include <J3ML/LinearAlgebra/CoordinateFrame.h>
|
||||
|
||||
namespace Geometry
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
|
||||
using J3ML::LinearAlgebra::CoordinateFrame;
|
||||
|
||||
enum class FrustumType
|
||||
{
|
||||
Invalid,
|
||||
|
@@ -2,11 +2,14 @@
|
||||
|
||||
#include <J3ML/LinearAlgebra/Vector3.h>
|
||||
|
||||
namespace Geometry
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
using LinearAlgebra::Vector3;
|
||||
class LineSegment
|
||||
{
|
||||
public:
|
||||
LineSegment();
|
||||
LineSegment(const Vector3& a, const Vector3& b);
|
||||
Vector3 A;
|
||||
Vector3 B;
|
||||
};
|
||||
|
@@ -5,7 +5,7 @@
|
||||
#include <J3ML/Geometry/LineSegment.h>
|
||||
#include <J3ML/Geometry/Polyhedron.h>
|
||||
|
||||
namespace Geometry {
|
||||
namespace J3ML::Geometry {
|
||||
class OBB
|
||||
{
|
||||
public:
|
||||
|
@@ -1,13 +1,18 @@
|
||||
#pragma once
|
||||
#include <J3ML/LinearAlgebra/Vector3.h>
|
||||
|
||||
using namespace LinearAlgebra;
|
||||
|
||||
class Plane
|
||||
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
public:
|
||||
Vector3 Position;
|
||||
Vector3 Normal;
|
||||
float distance = 0.f;
|
||||
using J3ML::LinearAlgebra::Vector3;
|
||||
|
||||
};
|
||||
class Plane
|
||||
{
|
||||
public:
|
||||
Vector3 Position;
|
||||
Vector3 Normal;
|
||||
float distance = 0.f;
|
||||
|
||||
};
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace Geometry {
|
||||
namespace J3ML::Geometry {
|
||||
class Polygon {
|
||||
|
||||
};
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace Geometry
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
class Polyhedron {
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
#include <J3ML/LinearAlgebra/Vector2.h>
|
||||
#include "AABB2D.h"
|
||||
|
||||
namespace Geometry {
|
||||
namespace J3ML::Geometry {
|
||||
|
||||
|
||||
using LinearAlgebra::Vector2;
|
||||
|
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <J3ML/LinearAlgebra/Vector3.h>
|
||||
|
||||
namespace Geometry
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
using LinearAlgebra::Vector3;
|
||||
class Ray
|
||||
|
@@ -1,9 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
namespace Geometry
|
||||
#include "J3ML/Geometry.h"
|
||||
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
class Sphere
|
||||
{
|
||||
public:
|
||||
Sphere(const Vector3& pos, float radius)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace Geometry
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
class Triangle
|
||||
{
|
||||
|
@@ -1,8 +1,10 @@
|
||||
//
|
||||
// Created by dawsh on 1/25/24.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#ifndef J3ML_TRIANGLE2D_H
|
||||
#define J3ML_TRIANGLE2D_H
|
||||
|
||||
#endif //J3ML_TRIANGLE2D_H
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
class Shape2D {};
|
||||
class Triangle2D {
|
||||
public:
|
||||
};
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace Geometry
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
class TriangleMesh
|
||||
{
|
||||
|
@@ -6,7 +6,7 @@
|
||||
#include <functional>
|
||||
|
||||
|
||||
namespace Math
|
||||
namespace J3ML::Math
|
||||
{
|
||||
const float Pi = M_PI;
|
||||
inline float Radians(float degrees) { return degrees * (Pi/180.f); }
|
||||
@@ -29,7 +29,7 @@ namespace Math
|
||||
|
||||
|
||||
// Dawsh Linear Algebra Library - Everything you need for 3D math
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
class Vector2; // A type representing a position in a 2-dimensional coordinate space.
|
||||
class Vector3; // A type representing a position in a 3-dimensional coordinate space.
|
||||
class Vector4; // A type representing a position in a 4-dimensional coordinate space.
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <J3ML/LinearAlgebra.h>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
class Angle2D {
|
||||
public:
|
||||
float x;
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include <J3ML/LinearAlgebra.h>
|
||||
#include <J3ML/LinearAlgebra/Vector3.h>
|
||||
|
||||
namespace LinearAlgebra
|
||||
namespace J3ML::LinearAlgebra
|
||||
{
|
||||
|
||||
/// Transitional datatype, not useful for internal representation of rotation
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include <J3ML/LinearAlgebra.h>
|
||||
#include <J3ML/LinearAlgebra/Vector3.h>
|
||||
|
||||
namespace LinearAlgebra
|
||||
namespace J3ML::LinearAlgebra
|
||||
{
|
||||
/// The CFrame is fundamentally 4 vectors (position, forward, right, up vector)
|
||||
class CoordinateFrame
|
||||
|
@@ -2,7 +2,7 @@
|
||||
#include <J3ML/LinearAlgebra.h>
|
||||
#include <J3ML/LinearAlgebra/Vector3.h>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
|
||||
// Essential Reading:
|
||||
// http://www.essentialmath.com/GDC2012/GDC2012_JMV_Rotations.pdf
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include <J3ML/LinearAlgebra.h>
|
||||
#include <J3ML/LinearAlgebra/Vector2.h>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
class Matrix2x2 {
|
||||
public:
|
||||
enum { Rows = 3 };
|
||||
|
@@ -5,7 +5,7 @@
|
||||
#include <J3ML/LinearAlgebra/Vector3.h>
|
||||
#include <J3ML/LinearAlgebra/Quaternion.h>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::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.
|
||||
@@ -44,6 +44,7 @@ namespace LinearAlgebra {
|
||||
Vector3 GetRow(int index) const;
|
||||
Vector3 GetColumn(int index) const;
|
||||
|
||||
float &At(int row, int col);
|
||||
float At(int x, int y) const;
|
||||
|
||||
void SetRotatePart(const Vector3& a, float angle);
|
||||
@@ -60,23 +61,11 @@ namespace LinearAlgebra {
|
||||
void SetColumn(int i, const Vector3& vector);
|
||||
void SetAt(int x, int y, float value);
|
||||
|
||||
void Orthonormalize(int c0, int c1, int c2)
|
||||
{
|
||||
Vector3 v0 = GetColumn(c0);
|
||||
Vector3 v1 = GetColumn(c1);
|
||||
Vector3 v2 = GetColumn(c2);
|
||||
Vector3::Orthonormalize(v0, v1, v2);
|
||||
SetColumn(c0, v0);
|
||||
SetColumn(c1, v1);
|
||||
SetColumn(c2, v2);
|
||||
}
|
||||
void Orthonormalize(int c0, int c1, int c2);
|
||||
|
||||
static Matrix3x3 LookAt(const Vector3& forward, const Vector3& target, const Vector3& localUp, const Vector3& worldUp);
|
||||
|
||||
static Matrix3x3 FromQuat(const Quaternion& orientation)
|
||||
{
|
||||
return Matrix3x3(orientation);
|
||||
}
|
||||
static Matrix3x3 FromQuat(const Quaternion& orientation);
|
||||
|
||||
Quaternion ToQuat() const;
|
||||
|
||||
@@ -86,20 +75,14 @@ namespace LinearAlgebra {
|
||||
// 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 Vector3& scale)
|
||||
{
|
||||
return Matrix3x3(rotate) * Matrix3x3::Scale(scale);
|
||||
}
|
||||
static Matrix3x3 FromRS(const Matrix3x3 &rotate, const Vector3& scale)
|
||||
{
|
||||
return rotate * Matrix3x3::Scale(scale);
|
||||
}
|
||||
static Matrix3x3 FromRS(const Quaternion& rotate, const Vector3& scale);
|
||||
static Matrix3x3 FromRS(const Matrix3x3 &rotate, const Vector3& 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 Vector3& scale);
|
||||
static Matrix3x3 FromScale(float sx, float sy, float sz);
|
||||
static Matrix3x3 FromScale(const Vector3& scale);
|
||||
|
||||
/// Returns the main diagonal.
|
||||
Vector3 Diagonal() const;
|
||||
@@ -133,6 +116,11 @@ namespace LinearAlgebra {
|
||||
Vector3 Transform(const Vector3& rhs) const;
|
||||
|
||||
|
||||
Matrix3x3 ScaleBy(const Vector3& rhs);
|
||||
Vector3 GetScale() const;
|
||||
|
||||
Vector3 operator[](int row) const;
|
||||
|
||||
Vector3 operator * (const Vector3& rhs) const;
|
||||
Matrix3x3 operator * (const Matrix3x3& rhs) const;
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include <J3ML/LinearAlgebra.h>
|
||||
#include <J3ML/LinearAlgebra/Quaternion.h>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::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,
|
||||
@@ -12,7 +12,7 @@ namespace LinearAlgebra {
|
||||
* 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, am_23,
|
||||
* 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.
|
||||
@@ -20,6 +20,7 @@ namespace LinearAlgebra {
|
||||
*/
|
||||
class Matrix4x4 {
|
||||
public:
|
||||
// TODO: Implement assertions to ensure matrix bounds are not violated!
|
||||
enum { Rows = 4 };
|
||||
enum { Cols = 4 };
|
||||
|
||||
@@ -43,9 +44,9 @@ namespace LinearAlgebra {
|
||||
/// The elements are specified in row-major format, i.e. the first row first followed by the second and third row.
|
||||
/// E.g. The element _10 denotes the scalar at second (index 1) row, first (index 0) column.
|
||||
Matrix4x4(float m00, float m01, float m02, float m03,
|
||||
float m10, float m11, float m12, float m13,
|
||||
float m20, float m21, float m22, float m23,
|
||||
float m30, float m31, float m32, float m33);
|
||||
float m10, float m11, float m12, float m13,
|
||||
float m20, float m21, float m22, float m23,
|
||||
float m30, float m31, float m32, float m33);
|
||||
/// Constructs the matrix by explicitly specifying the four column vectors.
|
||||
/** @param col0 The first column. If this matrix represents a change-of-basis transformation, this parameter is the world-space
|
||||
direction of the local X axis.
|
||||
@@ -57,37 +58,97 @@ namespace LinearAlgebra {
|
||||
position of the local space pivot. */
|
||||
Matrix4x4(const Vector4& r1, const Vector4& r2, const Vector4& r3, const Vector4& r4);
|
||||
|
||||
|
||||
explicit Matrix4x4(const Quaternion& orientation);
|
||||
|
||||
/// Constructs this float4x4 from the given quaternion and translation.
|
||||
/// Logically, the translation occurs after the rotation has been performed.
|
||||
Matrix4x4(const Quaternion& orientation, const Vector3 &translation);
|
||||
|
||||
/// Creates a LookAt matrix from a look-at direction vector.
|
||||
/** A LookAt matrix is a rotation matrix that orients an object to face towards a specified target direction.
|
||||
@param localForward Specifies the forward direction in the local space of the object. This is the direction
|
||||
the model is facing at in its own local/object space, often +X (1,0,0), +Y (0,1,0) or +Z (0,0,1). The
|
||||
vector to pass in here depends on the conventions you or your modeling software is using, and it is best
|
||||
pick one convention for all your objects, and be consistent.
|
||||
This input parameter must be a normalized vector.
|
||||
@param targetDirection Specifies the desired world space direction the object should look at. This function
|
||||
will compute a rotation matrix which will rotate the localForward vector to orient towards this targetDirection
|
||||
vector. This input parameter must be a normalized vector.
|
||||
@param localUp Specifies the up direction in the local space of the object. This is the up direction the model
|
||||
was authored in, often +Y (0,1,0) or +Z (0,0,1). The vector to pass in here depends on the conventions you
|
||||
or your modeling software is using, and it is best to pick one convention for all your objects, and be
|
||||
consistent. This input parameter must be a normalized vector. This vector must be perpendicular to the
|
||||
vector localForward, i.e. localForward.Dot(localUp) == 0.
|
||||
@param worldUp Specifies the global up direction of the scene in world space. Simply rotating one vector to
|
||||
coincide with another (localForward->targetDirection) would cause the up direction of the resulting
|
||||
orientation to drift (e.g. the model could be looking at its target its head slanted sideways). To keep
|
||||
the up direction straight, this function orients the localUp direction of the model to point towards the
|
||||
specified worldUp direction (as closely as possible). The worldUp and targetDirection vectors cannot be
|
||||
collinear, but they do not need to be perpendicular either.
|
||||
@return A matrix that maps the given local space forward direction vector to point towards the given target
|
||||
direction, and the given local up direction towards the given target world up direction. The returned
|
||||
matrix M is orthonormal with a determinant of +1. For the matrix M it holds that
|
||||
M * localForward = targetDirection, and M * localUp lies in the plane spanned by the vectors targetDirection
|
||||
and worldUp.
|
||||
@note The position of (the translation performed by) the resulting matrix will be set to (0,0,0), i.e. the object
|
||||
will be placed to origin. Call SetTranslatePart() on the resulting matrix to set the position of the model.
|
||||
@see RotateFromTo(). */
|
||||
static Matrix4x4 LookAt(const Vector3& localFwd, const Vector3& targetDir, const Vector3& localUp, const Vector3& worldUp);
|
||||
|
||||
/// Returns the translation part.
|
||||
/** The translation part is stored in the fourth column of this matrix.
|
||||
This is equivalent to decomposing this matrix in the form M = T * M', i.e. this translation is applied last,
|
||||
after applying rotation and scale. If this matrix represents a local->world space transformation for an object,
|
||||
then this gives the world space position of the object.
|
||||
@note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]). */
|
||||
Vector3 GetTranslatePart() const;
|
||||
Matrix3x3 GetRotatePart() const
|
||||
{
|
||||
return Matrix3x3 {
|
||||
At(0, 0), At(0, 1), At(0, 2),
|
||||
At(1, 0), At(1, 1), At(1, 2),
|
||||
At(2, 0), At(2, 1), At(2, 2)
|
||||
};
|
||||
}
|
||||
/// Returns the top-left 3x3 part of this matrix. This stores the rotation part of this matrix (if this matrix represents a rotation).
|
||||
Matrix3x3 GetRotatePart() const;
|
||||
void SetTranslatePart(float translateX, float translateY, float translateZ);
|
||||
void SetTranslatePart(const Vector3& offset);
|
||||
void SetRotatePart(const Quaternion& q);
|
||||
void SetRotatePart(const Matrix3x3& r);
|
||||
|
||||
void Set3x3Part(const Matrix3x3& r);
|
||||
|
||||
void SetRow(int row, const Vector3& rowVector, float m_r3);
|
||||
void SetRow(int row, const Vector4& rowVector);
|
||||
void SetRow(int row, float m_r0, float m_r1, float m_r2, float m_r3);
|
||||
|
||||
|
||||
Vector4 GetRow(int index) const;
|
||||
Vector4 GetColumn(int index) const;
|
||||
Vector3 GetRow3(int index) const;
|
||||
Vector3 GetColumn3(int index) const;
|
||||
|
||||
Vector3 GetScale() const
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float &At(int row, int col);
|
||||
float At(int x, int y) const;
|
||||
|
||||
template <typename T>
|
||||
void Swap(T &a, T &b)
|
||||
{
|
||||
T temp = std::move(a);
|
||||
a = std::move(b);
|
||||
b = std::move(temp);
|
||||
}
|
||||
|
||||
|
||||
void SwapColumns(int col1, int col2);
|
||||
|
||||
/// Swaps two rows.
|
||||
void SwapRows(int row1, int row2);
|
||||
/// Swapsthe xyz-parts of two rows element-by-element
|
||||
void SwapRows3(int row1, int row2);
|
||||
|
||||
void ScaleRow(int row, float scalar);
|
||||
void ScaleRow3(int row, float scalar);
|
||||
void ScaleColumn(int col, float scalar);
|
||||
void ScaleColumn3(int col, float scalar);
|
||||
/// Algorithm from Eric Lengyel's Mathematics for 3D Game Programming & Computer Graphics, 2nd Ed.
|
||||
void Pivot();
|
||||
|
||||
/// Tests if this matrix does not contain any NaNs or infs.
|
||||
/** @return Returns true if the entries of this float4x4 are all finite, and do not contain NaN or infs. */
|
||||
bool IsFinite() const;
|
||||
@@ -97,23 +158,52 @@ namespace LinearAlgebra {
|
||||
bool IsInvertible(float epsilon = 1e-3f) const;
|
||||
|
||||
Vector4 Diagonal() const;
|
||||
Vector4 WorldX() const;
|
||||
Vector4 WorldY() const;
|
||||
Vector4 WorldZ() const;
|
||||
Vector3 Diagonal3() const;
|
||||
/// Returns the local +X 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;
|
||||
|
||||
/// Accesses this structure as a float array.
|
||||
/// @return A pointer to the upper-left element. The data is contiguous in memory.
|
||||
/// ptr[0] gives the element [0][0], ptr[1] is [0][1], ptr[2] is [0][2].
|
||||
/// ptr[4] == [1][0], ptr[5] == [1][1], ..., and finally, ptr[15] == [3][3].
|
||||
float *ptr() { return &elems[0][0]; }
|
||||
const float *ptr() const { return &elems[0][0]; }
|
||||
|
||||
float Determinant3x3() const;
|
||||
/// Computes the determinant of this matrix.
|
||||
// If the determinant is nonzero, this matrix is invertible.
|
||||
float Determinant() const;
|
||||
|
||||
#define SKIPNUM(val, skip) (val >= skip ? (val+1) : val)
|
||||
|
||||
float Minor(int i, int j) const;
|
||||
|
||||
Matrix4x4 Inverse() const;
|
||||
|
||||
Matrix4x4 Transpose() const;
|
||||
|
||||
Vector2 Transform(float tx, float ty) const;
|
||||
Vector2 Transform(const Vector2& rhs) const;
|
||||
|
||||
|
||||
Vector3 Transform(float tx, float ty, float tz) const;
|
||||
Vector3 Transform(const Vector3& rhs) const;
|
||||
|
||||
Vector4 Transform(float tx, float ty, float tz, float tw) const;
|
||||
Vector4 Transform(const Vector4& rhs) const;
|
||||
|
||||
|
||||
Matrix4x4 Translate(const Vector3& rhs) const;
|
||||
static Matrix4x4 FromTranslation(const Vector3& rhs);
|
||||
|
||||
|
||||
static Matrix4x4 D3DOrthoProjLH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
||||
static Matrix4x4 D3DOrthoProjRH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
||||
static Matrix4x4 D3DPerspProjLH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
||||
@@ -124,12 +214,6 @@ namespace LinearAlgebra {
|
||||
static Matrix4x4 OpenGLPerspProjLH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
||||
static Matrix4x4 OpenGLPerspProjRH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
||||
|
||||
Vector3 GetTranslationComponent() const;
|
||||
Matrix3x3 GetRotationComponent() const;
|
||||
|
||||
Vector4 GetRow() const;
|
||||
Vector4 GetColumn() const;
|
||||
|
||||
Vector4 operator[](int row);
|
||||
|
||||
Matrix4x4 operator-() const;
|
||||
@@ -139,9 +223,11 @@ namespace LinearAlgebra {
|
||||
Matrix4x4 operator *(float scalar) const;
|
||||
Matrix4x4 operator /(float scalar) const;
|
||||
|
||||
Vector2 operator * (const Vector2& rhs) const { return this->Transform(rhs);}
|
||||
Vector3 operator * (const Vector3& rhs) const { return this->Transform(rhs);}
|
||||
Vector4 operator * (const Vector4& rhs) const { return this->Transform(rhs);}
|
||||
|
||||
|
||||
Vector2 operator * (const Vector2& rhs) const;
|
||||
Vector3 operator * (const Vector3& rhs) const;
|
||||
Vector4 operator * (const Vector4& rhs) const;
|
||||
|
||||
Matrix4x4 operator * (const Matrix3x3 &rhs) const;
|
||||
|
||||
@@ -149,23 +235,13 @@ namespace LinearAlgebra {
|
||||
|
||||
Matrix4x4 operator * (const Matrix4x4& rhs) const;
|
||||
|
||||
Matrix4x4 &operator = (const Matrix3x3& rhs)
|
||||
{
|
||||
SetRotatePart(rhs);
|
||||
SetTranslatePart(0,0,0);
|
||||
SetRow(3, 0, 0, 0, 1);
|
||||
return *this;
|
||||
}
|
||||
Matrix4x4 &operator = (const Quaternion& rhs)
|
||||
{
|
||||
*this = rhs.ToMatrix4x4();
|
||||
return *this;
|
||||
}
|
||||
Matrix4x4 &operator = (const Matrix3x3& rhs);
|
||||
Matrix4x4 &operator = (const Quaternion& rhs);
|
||||
Matrix4x4 &operator = (const Matrix4x4& rhs) = default;
|
||||
|
||||
protected:
|
||||
float elems[4][4];
|
||||
|
||||
void SetMatrixRotatePart(Matrix4x4 &m, const Quaternion &q);
|
||||
|
||||
};
|
||||
}
|
@@ -6,7 +6,7 @@
|
||||
#include <J3ML/LinearAlgebra/AxisAngle.h>
|
||||
#include <J3ML/LinearAlgebra/Matrix3x3.h>
|
||||
|
||||
namespace LinearAlgebra
|
||||
namespace J3ML::LinearAlgebra
|
||||
{
|
||||
class Quaternion : public Vector4 {
|
||||
public:
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include <J3ML/LinearAlgebra.h>
|
||||
#include <J3ML/LinearAlgebra/Matrix3x3.h>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
class Transform2D {
|
||||
protected:
|
||||
Matrix3x3 transformation;
|
||||
|
@@ -3,10 +3,9 @@
|
||||
#include <J3ML/LinearAlgebra.h>
|
||||
#include <cstddef>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
using namespace J3ML;
|
||||
|
||||
|
||||
/// A 2D (x, y) ordered pair.
|
||||
class Vector2 {
|
||||
public:
|
||||
@@ -14,6 +13,7 @@ namespace LinearAlgebra {
|
||||
Vector2();
|
||||
/// Constructs a new Vector2 with the value (X, Y)
|
||||
Vector2(float X, float Y);
|
||||
Vector2(float* xyPtr);
|
||||
Vector2(const Vector2& rhs); // Copy Constructor
|
||||
//Vector2(Vector2&&) = default; // Move Constructor
|
||||
|
||||
@@ -29,13 +29,21 @@ namespace LinearAlgebra {
|
||||
void SetX(float newX);
|
||||
void SetY(float newY);
|
||||
|
||||
float* ptr()
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
Vector2 Abs() const;
|
||||
|
||||
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 IsPerpendicular(const Vector2& other, float epsilonSq=1e-5f) const;
|
||||
|
||||
float operator[](std::size_t index);
|
||||
float operator[](std::size_t index) const;
|
||||
float &operator[](std::size_t index);
|
||||
bool operator == (const Vector2& rhs) const;
|
||||
bool operator != (const Vector2& rhs) const;
|
||||
|
||||
@@ -70,10 +78,6 @@ namespace LinearAlgebra {
|
||||
static float Magnitude(const Vector2& of);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool IsFinite() const;
|
||||
static bool IsFinite(const Vector2& v);
|
||||
|
||||
@@ -121,6 +125,10 @@ namespace LinearAlgebra {
|
||||
/// Multiplies this vector by a vector, element-wise
|
||||
/// @note Mathematically, the multiplication of two vectors is not defined in linear space structures,
|
||||
/// but this function is provided here for syntactical convenience.
|
||||
Vector2 operator *(const Vector2& rhs) const
|
||||
{
|
||||
|
||||
}
|
||||
Vector2 Mul(const Vector2& v) const;
|
||||
|
||||
/// Divides this vector by a scalar.
|
||||
@@ -147,4 +155,9 @@ namespace LinearAlgebra {
|
||||
float y = 0;
|
||||
|
||||
};
|
||||
|
||||
static Vector2 operator*(float lhs, const Vector2 &rhs)
|
||||
{
|
||||
return rhs * lhs;
|
||||
}
|
||||
}
|
@@ -6,7 +6,7 @@
|
||||
#include <J3ML/LinearAlgebra/Angle2D.h>
|
||||
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
|
||||
// A 3D (x, y, z) ordered pair.
|
||||
class Vector3 {
|
||||
@@ -29,6 +29,13 @@ public:
|
||||
static const Vector3 Forward;
|
||||
static const Vector3 Backward;
|
||||
static const Vector3 NaN;
|
||||
static const Vector3 Infinity;
|
||||
static const Vector3 NegativeInfinity;
|
||||
|
||||
float* ptr()
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
static void Orthonormalize(Vector3& a, Vector3& b)
|
||||
{
|
||||
@@ -37,8 +44,10 @@ public:
|
||||
b = b.Normalize();
|
||||
}
|
||||
|
||||
Vector3 Abs() const;
|
||||
|
||||
//Returns the DirectionVector for a given angle.
|
||||
|
||||
/// Returns the DirectionVector for a given angle.
|
||||
static Vector3 Direction(const Vector3 &rhs) ;
|
||||
|
||||
|
||||
@@ -75,9 +84,15 @@ public:
|
||||
bool IsPerpendicular(const Vector3& other, float epsilonSq=1e-5f) const;
|
||||
|
||||
float operator[](std::size_t index) const;
|
||||
float &operator[](std::size_t index);
|
||||
bool operator == (const Vector3& rhs) const;
|
||||
bool operator != (const Vector3& rhs) const;
|
||||
|
||||
bool IsFinite() const
|
||||
{
|
||||
return std::isfinite(x) && std::isfinite(y) && std::isfinite(z);
|
||||
}
|
||||
|
||||
Vector3 Min(const Vector3& min) const;
|
||||
static Vector3 Min(const Vector3& lhs, const Vector3& rhs);
|
||||
|
||||
@@ -87,7 +102,7 @@ public:
|
||||
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.
|
||||
/// Returns the magnitude between the two vectors.
|
||||
float Distance(const Vector3& to) const;
|
||||
static float Distance(const Vector3& from, const Vector3& to);
|
||||
|
||||
@@ -97,33 +112,33 @@ public:
|
||||
float LengthSquared() const;
|
||||
static float LengthSquared(const Vector3& of);
|
||||
|
||||
// Returns the length of the vector, which is sqrt(x^2 + y^2 + z^2)
|
||||
/// 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.
|
||||
/// 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)
|
||||
/// 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.
|
||||
/// 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"
|
||||
/// 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).
|
||||
/// 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);
|
||||
|
||||
@@ -136,28 +151,47 @@ public:
|
||||
Vector3 Add(const Vector3& rhs) const;
|
||||
static Vector3 Add(const Vector3& lhs, const Vector3& rhs);
|
||||
|
||||
// Subtracts two vectors
|
||||
/// 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
|
||||
/// 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
|
||||
/// Multiplies this vector by a vector, element-wise
|
||||
/// @note Mathematically, the multiplication of two vectors is not defined in linear space structures,
|
||||
/// but this function is provided here for syntactical convenience.
|
||||
Vector3 Mul(const Vector3& rhs) const
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
||||
/// Divides this vector by a vector, element-wise
|
||||
/// @note Mathematically, the multiplication of two vectors is not defined in linear space structures,
|
||||
/// but this function is provided here for syntactical convenience
|
||||
Vector2 Div(const Vector2& v) const;
|
||||
|
||||
/// Unary + operator
|
||||
Vector3 operator+() const; // TODO: Implement
|
||||
// Unary - operator (Negation)
|
||||
/// Unary - operator (Negation)
|
||||
Vector3 operator-() const;
|
||||
public:
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float z = 0;
|
||||
};
|
||||
|
||||
static Vector3 operator*(float lhs, const Vector3& rhs)
|
||||
{
|
||||
return rhs * lhs;
|
||||
}
|
||||
}
|
@@ -2,8 +2,7 @@
|
||||
|
||||
#include <J3ML/LinearAlgebra.h>
|
||||
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
class Vector4 {
|
||||
public:
|
||||
// Default Constructor
|
||||
@@ -16,6 +15,11 @@ namespace LinearAlgebra {
|
||||
Vector4(Vector4&& move) = default;
|
||||
Vector4& operator=(const Vector4& rhs);
|
||||
|
||||
float* ptr()
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
float GetX() const;
|
||||
float GetY() const;
|
||||
float GetZ() const;
|
||||
@@ -81,6 +85,8 @@ namespace LinearAlgebra {
|
||||
|
||||
Vector4 operator+() const; // Unary + Operator
|
||||
Vector4 operator-() const; // Unary - Operator (Negation)
|
||||
|
||||
|
||||
public:
|
||||
#if MUTABLE
|
||||
float x;
|
||||
|
154
src/J3ML/Algorithm/RNG.cpp
Normal file
154
src/J3ML/Algorithm/RNG.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
#include <J3ML/Algorithm/RNG.h>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace J3ML::Algorithm {
|
||||
void RNG::Seed(J3ML::u32 seed, J3ML::u32 multiplier, J3ML::u32 increment, J3ML::u32 modulus) {
|
||||
// If we have a pure multiplicative RNG, then can't have 0 starting seed, since that would generate a stream of all zeroes
|
||||
if (seed == 0 && increment == 0) seed = 1;
|
||||
|
||||
if (increment == 0 && (multiplier % modulus == 0 || modulus % multiplier == 0 ))
|
||||
throw std::runtime_error("Multiplier %u and modulus %u are not compatible since one is a multiple of the other and the increment == 0!");
|
||||
|
||||
// TODO: assert(multiplier != 0);
|
||||
// TODO: assert(modulus > 1);
|
||||
|
||||
this->lastNumber = seed;
|
||||
this->multiplier = multiplier;
|
||||
this->increment = increment;
|
||||
this->modulus = modulus;
|
||||
}
|
||||
|
||||
u32 RNG::IntFast()
|
||||
{
|
||||
assert(increment == 0);
|
||||
assert(multiplier % 2 == 1 && "Multiplier should be odd for RNG::IntFast(), since modulus==2^32 is even!");
|
||||
// The configurable modulus and increment are not used by this function.
|
||||
u32 mul = lastNumber * multiplier;
|
||||
// Whenever we overflow, flip by one to avoud even multiplier always producing even results
|
||||
// since modulus is even.
|
||||
lastNumber = mul + (mul <= lastNumber?1:0);
|
||||
// We don't use an adder in IntFast(), so must never degenerate to zero
|
||||
assert(lastNumber != 0);
|
||||
return lastNumber;
|
||||
}
|
||||
|
||||
u32 RNG::Int()
|
||||
{
|
||||
assert(modulus != 0);
|
||||
/// TODO: Convert to using Shrage's method for approximate factorization (Numerical Recipes in C)
|
||||
|
||||
// Currently we cast everything to 65-bit to avoid overflow, which is quite dumb.
|
||||
|
||||
// Creates the new random number
|
||||
u64 newNum = ((u64)lastNumber * (u64)multiplier + (u64)increment % (u64)modulus);
|
||||
|
||||
// TODO: use this on console platforms to rely on smaller sequences.
|
||||
// u32 m = lastNumber * multiplier;
|
||||
// u32 i = m + increment;
|
||||
// u32 f = i & 0x7FFFFFFF;
|
||||
// u32 m = (lastNumber * 214013 + 2531011) & 0x7FFFFFFF;
|
||||
// unsigned __int64 newNum = (lastNumber * multiplier + increment) & 0x7FFFFFFF;
|
||||
assert( ((u32)newNum!=0 || increment != 0) && "RNG degenerated to producing a stream of zeroes!");
|
||||
lastNumber = (u32)newNum;
|
||||
return lastNumber;
|
||||
}
|
||||
|
||||
int RNG::Int(int a, int b) {
|
||||
assert(a <= b && "Error in range!");
|
||||
|
||||
int num = a + (int)(Float() * (b-a+1));
|
||||
// TODO: Some bug here - the result is not necessarily in the proper range.
|
||||
if (num < a) num = a;
|
||||
if (num > b) num = b;
|
||||
return num;
|
||||
}
|
||||
|
||||
/// Jesus-Fuck ~ Josh
|
||||
/// As per C99, union-reinterpret should now be safe: http://stackoverflow.com/questions/8511676/portable-data-reinterpretation
|
||||
union FloatIntReinterpret
|
||||
{
|
||||
float f;
|
||||
u32 i;
|
||||
};
|
||||
|
||||
template <typename To, typename From>
|
||||
union ReinterpretOp {
|
||||
To to;
|
||||
From from;
|
||||
};
|
||||
|
||||
template <typename To, typename From>
|
||||
To ReinterpretAs(From input)
|
||||
{
|
||||
ReinterpretOp<To, From> fi {};
|
||||
fi.to = input;
|
||||
return fi.from;
|
||||
}
|
||||
|
||||
float RNG::Float() {
|
||||
u32 i = ((u32)Int() & 0x007FFFFF /* random mantissa */) | 0x3F800000 /* fixed exponent */;
|
||||
auto f = ReinterpretAs<float, u32>(i); // f is now in range [1, 2[
|
||||
f -= 1.f; // Map to range [0, 1[
|
||||
assert(f >= 0.f);
|
||||
assert(f < 1.f);
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
float RNG::Float01Incl() {
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
u32 val = (u32)Int() & 0x00FFFFFF;
|
||||
if (val > 0x800000)
|
||||
continue;
|
||||
else if (val = 0x800000)
|
||||
return 1.f;
|
||||
else {
|
||||
val |= 0x3F800000;
|
||||
float f = ReinterpretAs<float, u32>(val) - 1.f;
|
||||
assert(f >= 0.f);
|
||||
assert(f <= 1.f);
|
||||
return f;
|
||||
}
|
||||
}
|
||||
return Float();
|
||||
}
|
||||
|
||||
float RNG::FloatNeg1_1() {
|
||||
u32 i = (u32) Int();
|
||||
u32 one = ((i & 0x00800000) << 8) /* random sign bit */ | 0x3F800000; /* fixed exponent */
|
||||
i = one | (i & 0x007FFFFF); // Random mantissa
|
||||
float f = ReinterpretAs<float, u32>(i); // f is now in range ]-2, -1[ union [1, 2].
|
||||
float fone = ReinterpretAs<float, u32>(one); // +/- 1, of same sign as f.
|
||||
f -= fone;
|
||||
assert(f > -1.f);
|
||||
assert(f < 1.f);
|
||||
return f;
|
||||
}
|
||||
|
||||
float RNG::Float(float a, float b) {
|
||||
assert(a <= b && "");
|
||||
if (a == b)
|
||||
return a;
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
float f = a + Float() * (b - a);
|
||||
if (f != b) {
|
||||
assert(a <= f);
|
||||
assert(f < b || a == b);
|
||||
return f;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
float RNG::FloatIncl(float a, float b) {
|
||||
assert(a <= b && "RNG::Float(a, b): Error in range: b < a!");
|
||||
float f = a + Float() * (b - a);
|
||||
assert( a <= f);
|
||||
assert(f <= b);
|
||||
return f;
|
||||
}
|
||||
}
|
@@ -1,5 +1,237 @@
|
||||
#include <J3ML/Geometry/AABB.h>
|
||||
#include <cassert>
|
||||
|
||||
namespace Geometry {
|
||||
namespace J3ML::Geometry {
|
||||
|
||||
}
|
||||
AABB AABB::FromCenterAndSize(const J3ML::Geometry::Vector3 ¢er, const J3ML::Geometry::Vector3 &size) {
|
||||
Vector3 halfSize = size * 0.5f;
|
||||
return {center - halfSize, center + halfSize};
|
||||
}
|
||||
|
||||
float AABB::MinX() const { return minPoint.x; }
|
||||
|
||||
float AABB::MinY() const { return minPoint.y; }
|
||||
|
||||
float AABB::MinZ() const { return minPoint.z; }
|
||||
|
||||
float AABB::MaxX() const { return maxPoint.x; }
|
||||
|
||||
float AABB::MaxY() const { return maxPoint.y; }
|
||||
|
||||
float AABB::MaxZ() const { return maxPoint.z; }
|
||||
|
||||
Sphere AABB::MinimalEnclosingSphere() const {
|
||||
return Sphere(Centroid(), Size().Length()*0.5f);
|
||||
}
|
||||
|
||||
Vector3 AABB::HalfSize() const {
|
||||
return this->Size()/2.f;
|
||||
}
|
||||
|
||||
Sphere AABB::MaximalContainedSphere() const {
|
||||
Vector3 halfSize = HalfSize();
|
||||
return Sphere(Centroid(), std::min(halfSize.x, std::min(halfSize.y, halfSize.z)));
|
||||
}
|
||||
|
||||
bool AABB::IsFinite() const {
|
||||
return minPoint.IsFinite() && maxPoint.IsFinite();
|
||||
}
|
||||
|
||||
Vector3 AABB::Centroid() const {
|
||||
return (minPoint+maxPoint) * 0.5f;
|
||||
}
|
||||
|
||||
Vector3 AABB::Size() const {
|
||||
return this->maxPoint - this->minPoint;
|
||||
}
|
||||
|
||||
Vector3 AABB::PointInside(float x, float y, float z) const {
|
||||
Vector3 d = maxPoint - minPoint;
|
||||
return minPoint + d.Mul({x, y, z});
|
||||
}
|
||||
|
||||
LineSegment AABB::Edge(int edgeIndex) const {
|
||||
switch(edgeIndex)
|
||||
{
|
||||
default:
|
||||
case 0: return LineSegment(minPoint, {minPoint.x, minPoint.y, maxPoint.z});
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 AABB::CornerPoint(int cornerIndex) const {
|
||||
// TODO: assert(0 <= cornerIndex && cornerIndex <= 7)
|
||||
switch(cornerIndex)
|
||||
{
|
||||
default:
|
||||
case 0: return minPoint;
|
||||
case 1: return {minPoint.x, minPoint.y, maxPoint.z};
|
||||
case 2: return {minPoint.x, maxPoint.y, minPoint.z};
|
||||
case 3: return {minPoint.x, maxPoint.y, maxPoint.z};
|
||||
case 4: return {maxPoint.x, minPoint.y, minPoint.z};
|
||||
case 5: return {maxPoint.x, minPoint.y, maxPoint.z};
|
||||
case 6: return {maxPoint.x, maxPoint.y, minPoint.z};
|
||||
case 7: return maxPoint;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 AABB::ExtremePoint(const Vector3 &direction) const {
|
||||
return {direction.x >= 0.f ? maxPoint.x : minPoint.x,
|
||||
direction.y >= 0.f ? maxPoint.y : minPoint.y,
|
||||
direction.z >= 0.f ? maxPoint.z : minPoint.z};
|
||||
}
|
||||
|
||||
Vector3 AABB::ExtremePoint(const Vector3 &direction, float &projectionDistance) {
|
||||
auto extremePt = ExtremePoint(direction);
|
||||
projectionDistance = extremePt.Dot(direction);
|
||||
return extremePt;
|
||||
}
|
||||
|
||||
Vector3 AABB::PointOnEdge(int edgeIndex, float u) const {
|
||||
// TODO: assert(0 <= edgeIndex && edgeIndex <= 11);
|
||||
// TODO: assert(0 <= u && u < 1.f);
|
||||
|
||||
auto d = maxPoint - minPoint;
|
||||
switch(edgeIndex) {
|
||||
default:
|
||||
case 0: return {minPoint.x, minPoint.y, minPoint.z + u * d.z};
|
||||
case 1: return {minPoint.x, maxPoint.y, minPoint.z + u * d.z};
|
||||
case 2: return {maxPoint.x, minPoint.y, minPoint.z + u * d.z};
|
||||
case 3: return {maxPoint.x, maxPoint.y, minPoint.z + u * d.z};
|
||||
|
||||
case 4: return {minPoint.x, minPoint.y + u * d.y, minPoint.z};
|
||||
case 5: return {maxPoint.x, minPoint.y + u * d.y, minPoint.z};
|
||||
case 6: return {minPoint.x, minPoint.y + u * d.y, maxPoint.z};
|
||||
case 7: return {maxPoint.x, minPoint.y + u * d.y, maxPoint.z};
|
||||
|
||||
case 8: return {minPoint.x + u * d.x, minPoint.y, minPoint.z};
|
||||
case 9: return {minPoint.x + u * d.x, minPoint.y, maxPoint.z};
|
||||
case 10:return {minPoint.x + u * d.x, maxPoint.y, minPoint.z};
|
||||
case 11:return {minPoint.x + u * d.x, maxPoint.y, maxPoint.z};
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 AABB::FaceCenterPoint(int faceIndex) const {
|
||||
// TODO: assert(0 <= faceIndex && faceIndex <= 5)
|
||||
auto center = (minPoint + maxPoint) * 0.5f;
|
||||
switch (faceIndex) {
|
||||
default:
|
||||
case 0: return {minPoint.x, center.y, center.z};
|
||||
case 1: return {maxPoint.x, center.y, center.z};
|
||||
case 2: return {center.x, minPoint.y, center.z};
|
||||
case 3: return {center.x, maxPoint.y, center.z};
|
||||
case 4: return {center.x, center.y, minPoint.z};
|
||||
case 5: return {center.x, center.y, maxPoint.z};
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 AABB::FacePoint(int faceIndex, float u, float v) const {
|
||||
// TODO: assert(0 <= faceIndex && faceIndex <= 5);
|
||||
// TODO: assert(0 <= u && u <= 1.f);
|
||||
// TODO: assert(0 <= v && v <= 1.f);
|
||||
|
||||
auto d = maxPoint - minPoint;
|
||||
switch(faceIndex)
|
||||
{
|
||||
default: // For release builds where assume() is disabled, return always the first option if out-of-bounds.
|
||||
case 0: return {minPoint.x, minPoint.y + u * d.y, minPoint.z + v * d.z};
|
||||
case 1: return {maxPoint.x, minPoint.y + u * d.y, minPoint.z + v * d.z};
|
||||
case 2: return {minPoint.x + u * d.x, minPoint.y, minPoint.z + v * d.z};
|
||||
case 3: return {minPoint.x + u * d.x, maxPoint.y, minPoint.z + v * d.z};
|
||||
case 4: return {minPoint.x + u * d.x, minPoint.y + v * d.y, minPoint.z};
|
||||
case 5: return {minPoint.x + u * d.x, minPoint.y + v * d.y, maxPoint.z};
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 AABB::FaceNormal(int faceIndex) const {
|
||||
// TODO: assert(0 <= faceIndex && faceIndex <= 5);
|
||||
switch(faceIndex) {
|
||||
default:
|
||||
case 0: return {-1, 0, 0};
|
||||
case 1: return { 1, 0, 0};
|
||||
case 2: return { 0, -1, 0};
|
||||
case 3: return { 0, 1, 0};
|
||||
case 4: return { 0, 0, -1};
|
||||
case 5: return { 0, 0, 1};
|
||||
}
|
||||
}
|
||||
|
||||
Plane AABB::FacePlane(int faceIndex) const {
|
||||
// TODO: assert(0 <= faceIndex && faceIndex <= 5);
|
||||
return Plane(FaceCenterPoint(faceIndex), FaceNormal(faceIndex));
|
||||
}
|
||||
|
||||
AABB AABB::MinimalEnclosingAABB(const Vector3 *pointArray, int numPoints) {
|
||||
AABB aabb;
|
||||
aabb.SetFrom(pointArray, numPoints);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
float AABB::GetVolume() const {
|
||||
Vector3 sz = Size();
|
||||
return sz.x * sz.y * sz.z;
|
||||
}
|
||||
|
||||
float AABB::GetSurfaceArea() const {
|
||||
Vector3 size = Size();
|
||||
return 2.f * (size.x*size.y + size.x*size.z + size.y*size.z);
|
||||
}
|
||||
|
||||
void AABB::SetFromCenterAndSize(const Vector3& center, const Vector3& size)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void AABB::SetFrom(const OBB& obb)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void AABB::SetFrom(const Sphere& s)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void AABB::SetFrom(const Vector3 *pointArray, int numPoints) {
|
||||
assert(pointArray || numPoints == 0);
|
||||
SetNegativeInfinity();
|
||||
if (!pointArray)
|
||||
return;
|
||||
for (int i = 0; i < numPoints; ++i)
|
||||
Enclose(pointArray[i]);
|
||||
}
|
||||
|
||||
Vector3 AABB::GetRandomPointInside() const {
|
||||
|
||||
}
|
||||
|
||||
void AABB::SetNegativeInfinity() {
|
||||
minPoint = Vector3::Infinity;
|
||||
maxPoint = Vector3::NegativeInfinity;
|
||||
}
|
||||
|
||||
void AABB::Enclose(const Vector3& point) {
|
||||
minPoint = Vector3::Min(minPoint, point);
|
||||
maxPoint = Vector3::Max(maxPoint, point);
|
||||
}
|
||||
|
||||
void AABB::Enclose(const Vector3& aabbMinPt, const Vector3& aabbMaxPt)
|
||||
{
|
||||
minPoint = Vector3::Min(minPoint, aabbMinPt);
|
||||
maxPoint = Vector3::Max(maxPoint, aabbMaxPt);
|
||||
}
|
||||
|
||||
void AABB::Enclose(const LineSegment& lineSegment)
|
||||
{
|
||||
Enclose(Vector3::Min(lineSegment.A, lineSegment.B), Vector3::Max(lineSegment.A, lineSegment.B));
|
||||
}
|
||||
|
||||
void AABB::Enclose(const OBB& obb)
|
||||
{
|
||||
Vector3 absAxis0 = obb.axis[0].Abs();
|
||||
Vector3 absAxis1 = obb.axis[1].Abs();
|
||||
Vector3 absAxis2 = obb.axis[2].Abs();
|
||||
Vector3 d = obb.r.x * absAxis0 + obb.r.y * absAxis1 + obb.r.z * absAxis2;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#include <J3ML/Geometry/Capsule.h>
|
||||
|
||||
namespace Geometry
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
|
||||
Capsule::Capsule() : l() {}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
#include <J3ML/Geometry/Frustum.h>
|
||||
|
||||
namespace Geometry
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
Frustum Frustum::CreateFrustumFromCamera(const CoordinateFrame &cam, float aspect, float fovY, float zNear, float zFar) {
|
||||
Frustum frustum;
|
||||
|
@@ -1,5 +1,11 @@
|
||||
#include <J3ML/Geometry/LineSegment.h>
|
||||
|
||||
namespace Geometry {
|
||||
namespace J3ML::Geometry {
|
||||
|
||||
LineSegment::LineSegment(const Vector3 &a, const Vector3 &b) : A(a), B(b)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LineSegment::LineSegment() {}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
#include <J3ML/LinearAlgebra/AxisAngle.h>
|
||||
#include <J3ML/LinearAlgebra/Quaternion.h>
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
|
||||
AxisAngle::AxisAngle() : axis(Vector3::Zero) {}
|
||||
|
||||
|
@@ -3,50 +3,49 @@
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
#pragma region EulerAngle
|
||||
namespace LinearAlgebra {
|
||||
EulerAngle::EulerAngle(float pitch, float yaw, float roll): pitch(pitch), yaw(yaw), roll(roll)
|
||||
{}
|
||||
namespace J3ML::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::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::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); }
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
EulerAngle::EulerAngle() : pitch(0), yaw(0), roll(0) {}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
#include <J3ML/LinearAlgebra/Matrix2x2.h>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
|
||||
Vector2 Matrix2x2::GetRow(int index) const {
|
||||
float x = this->elems[index][0];
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#include <J3ML/LinearAlgebra/Matrix3x3.h>
|
||||
#include <cmath>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::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);
|
||||
@@ -296,5 +296,71 @@ namespace LinearAlgebra {
|
||||
};
|
||||
}
|
||||
|
||||
float &Matrix3x3::At(int row, int col) {
|
||||
return elems[row][col];
|
||||
}
|
||||
|
||||
Vector3 Matrix3x3::WorldZ() const {
|
||||
return GetColumn(2);
|
||||
}
|
||||
|
||||
Vector3 Matrix3x3::WorldY() const {
|
||||
return GetColumn(1);
|
||||
}
|
||||
|
||||
Vector3 Matrix3x3::WorldX() const {
|
||||
return GetColumn(0);
|
||||
}
|
||||
|
||||
Matrix3x3 Matrix3x3::FromRS(const Quaternion &rotate, const Vector3 &scale) {
|
||||
return Matrix3x3(rotate) * Matrix3x3::FromScale(scale);
|
||||
}
|
||||
|
||||
Matrix3x3 Matrix3x3::FromRS(const Matrix3x3 &rotate, const Vector3 &scale) {
|
||||
return rotate * Matrix3x3::FromScale(scale);
|
||||
}
|
||||
|
||||
Matrix3x3 Matrix3x3::FromQuat(const Quaternion &orientation) {
|
||||
return Matrix3x3(orientation);
|
||||
}
|
||||
|
||||
Matrix3x3 Matrix3x3::ScaleBy(const Vector3 &rhs) {
|
||||
return *this * FromScale(rhs);
|
||||
}
|
||||
|
||||
Vector3 Matrix3x3::GetScale() const {
|
||||
return Vector3(GetColumn(0).Length(), GetColumn(1).Length(), GetColumn(2).Length());
|
||||
}
|
||||
|
||||
Vector3 Matrix3x3::operator[](int row) const {
|
||||
return Vector3{elems[row][0], elems[row][1], elems[row][2]};
|
||||
}
|
||||
|
||||
Matrix3x3 Matrix3x3::FromScale(const Vector3 &scale) {
|
||||
Matrix3x3 m;
|
||||
m.At(0,0) = scale.x;
|
||||
m.At(1,1) = scale.y;
|
||||
m.At(2,2) = scale.z;
|
||||
return m;
|
||||
}
|
||||
|
||||
Matrix3x3 Matrix3x3::FromScale(float sx, float sy, float sz) {
|
||||
Matrix3x3 m;
|
||||
m.At(0,0) = sx;
|
||||
m.At(1,1) = sy;
|
||||
m.At(2,2) = sz;
|
||||
return m;
|
||||
}
|
||||
|
||||
void Matrix3x3::Orthonormalize(int c0, int c1, int c2) {
|
||||
Vector3 v0 = GetColumn(c0);
|
||||
Vector3 v1 = GetColumn(c1);
|
||||
Vector3 v2 = GetColumn(c2);
|
||||
Vector3::Orthonormalize(v0, v1, v2);
|
||||
SetColumn(c0, v0);
|
||||
SetColumn(c1, v1);
|
||||
SetColumn(c2, v2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#include <J3ML/LinearAlgebra/Matrix4x4.h>
|
||||
#include <J3ML/LinearAlgebra/Vector4.h>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
const Matrix4x4 Matrix4x4::Zero = Matrix4x4(0);
|
||||
const Matrix4x4 Matrix4x4::Identity = Matrix4x4({1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0,0,1});
|
||||
const Matrix4x4 Matrix4x4::NaN = Matrix4x4(NAN);
|
||||
@@ -90,11 +90,8 @@ namespace LinearAlgebra {
|
||||
elems[2][3] = offset.z;
|
||||
}
|
||||
|
||||
void Matrix4x4::SetRotatePart(const Quaternion &q) {
|
||||
SetMatrixRotatePart(*this, q);
|
||||
}
|
||||
|
||||
void Matrix4x4::SetMatrixRotatePart(Matrix4x4 &m, const Quaternion& q)
|
||||
void Matrix4x4::SetRotatePart(const Quaternion& q)
|
||||
{
|
||||
// See e.g. http://www.geometrictools.com/Documentation/LinearAlgebraicQuaternions.pdf .
|
||||
const float x = q.x;
|
||||
@@ -106,6 +103,15 @@ namespace LinearAlgebra {
|
||||
elems[2][0] = 2*(x*z - y*w); elems[2][1] = 2*(y*z + x*w); elems[2][2] = 1 - 2*(x*x + y*y);
|
||||
}
|
||||
|
||||
void Matrix4x4::Set3x3Part(const Matrix3x3& r)
|
||||
{
|
||||
At(0, 0) = r[0][0]; At(0, 1) = r[0][1]; At(0, 2) = r[0][2];
|
||||
At(1, 0) = r[1][0]; At(1, 1) = r[1][1]; At(1, 2) = r[1][2];
|
||||
At(2, 0) = r[2][0]; At(2, 1) = r[2][1]; At(2, 2) = r[2][2];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Matrix4x4::SetRow(int row, const Vector3 &rowVector, float m_r3) {
|
||||
SetRow(row, rowVector.x, rowVector.y, rowVector.z, m_r3);
|
||||
}
|
||||
@@ -224,4 +230,288 @@ namespace LinearAlgebra {
|
||||
}
|
||||
|
||||
Matrix4x4 Matrix4x4::operator+() const { return *this; }
|
||||
|
||||
Matrix4x4 Matrix4x4::FromTranslation(const Vector3 &rhs) {
|
||||
return Matrix4x4(1.f, 0, 0, rhs.x,
|
||||
0, 1.f, 0, rhs.y,
|
||||
0, 0, 1.f, rhs.z,
|
||||
0, 0, 0, 1.f);
|
||||
}
|
||||
|
||||
Matrix4x4 Matrix4x4::Translate(const Vector3 &rhs) const {
|
||||
return *this * FromTranslation(rhs);
|
||||
}
|
||||
|
||||
Vector3 Matrix4x4::Transform(const Vector3 &rhs) const {
|
||||
return Transform(rhs.x, rhs.y, rhs.z);
|
||||
}
|
||||
|
||||
Vector3 Matrix4x4::Transform(float tx, float ty, float tz) const {
|
||||
return Vector3(At(0, 0) * tx + At(0, 1) * ty + At(0, 2) * tz + At(0, 3),
|
||||
At(1, 0) * tx + At(1, 1) * ty + At(1, 2) * tz + At(1, 3),
|
||||
At(2, 0) * tx + At(2, 1) * ty + At(2, 2) * tz + At(2, 3));
|
||||
}
|
||||
|
||||
Vector2 Matrix4x4::Transform(float tx, float ty) const {
|
||||
return Vector2(At(0, 0) * tx + At(0, 1) * ty + At(0, 2) + At(0, 3),
|
||||
At(1, 0) * tx + At(1, 1) * ty + At(1, 2) + At(1, 3));
|
||||
}
|
||||
|
||||
Vector2 Matrix4x4::Transform(const Vector2 &rhs) const {
|
||||
return Transform(rhs.x, rhs.y);
|
||||
}
|
||||
|
||||
Matrix4x4 &Matrix4x4::operator=(const Matrix3x3 &rhs) {
|
||||
Set3x3Part(rhs);
|
||||
SetTranslatePart(0,0,0);
|
||||
SetRow(3, 0, 0, 0, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Matrix4x4 &Matrix4x4::operator=(const Quaternion &rhs) {
|
||||
*this = rhs.ToMatrix4x4();
|
||||
return *this;
|
||||
}
|
||||
|
||||
float &Matrix4x4::At(int row, int col) {
|
||||
return elems[row][col];
|
||||
}
|
||||
|
||||
Matrix4x4 Matrix4x4::Inverse() const {
|
||||
// Compute the inverse directly using Cramer's rule
|
||||
// Warning: This method is numerically very unstable!
|
||||
float d = Determinant();
|
||||
|
||||
d = 1.f / d;
|
||||
|
||||
float a11 = At(0, 0);float a12 = At(0, 1);float a13 = At(0, 2);float a14 = At(0, 3);
|
||||
float a21 = At(1, 0);float a22 = At(1, 1);float a23 = At(1, 2);float a24 = At(1, 3);
|
||||
float a31 = At(2, 0);float a32 = At(2, 1);float a33 = At(2, 2);float a34 = At(2, 3);
|
||||
float a41 = At(3, 0);float a42 = At(3, 1);float a43 = At(3, 2);float a44 = At(3, 3);
|
||||
|
||||
Matrix4x4 i = {
|
||||
d * (a22*a33*a44 + a23*a34*a42 + a24*a32*a43 - a22*a34*a43 - a23*a32*a44 - a24*a33*a42),
|
||||
d * (a12*a34*a43 + a13*a32*a44 + a14*a33*a42 - a12*a33*a44 - a13*a34*a42 - a14*a32*a43),
|
||||
d * (a12*a23*a44 + a13*a24*a42 + a14*a22*a43 - a12*a24*a43 - a13*a22*a44 - a14*a23*a42),
|
||||
d * (a12*a24*a33 + a13*a22*a34 + a14*a23*a32 - a12*a23*a34 - a13*a24*a32 - a14*a22*a33),
|
||||
d * (a21*a34*a43 + a23*a31*a44 + a24*a33*a41 - a21*a33*a44 - a23*a34*a41 - a24*a31*a43),
|
||||
d * (a11*a33*a44 + a13*a34*a41 + a14*a31*a43 - a11*a34*a43 - a13*a31*a44 - a14*a33*a41),
|
||||
d * (a11*a24*a43 + a13*a21*a44 + a14*a23*a41 - a11*a23*a44 - a13*a24*a41 - a14*a21*a43),
|
||||
d * (a11*a23*a34 + a13*a24*a31 + a14*a21*a33 - a11*a24*a33 - a13*a21*a34 - a14*a23*a31),
|
||||
d * (a21*a32*a44 + a22*a34*a41 + a24*a31*a42 - a21*a34*a42 - a22*a31*a44 - a24*a32*a41),
|
||||
d * (a11*a34*a42 + a12*a31*a44 + a14*a32*a41 - a11*a32*a44 - a12*a34*a41 - a14*a31*a42),
|
||||
d * (a11*a22*a44 + a12*a24*a41 + a14*a21*a42 - a11*a24*a42 - a12*a21*a44 - a14*a22*a41),
|
||||
d * (a11*a24*a32 + a12*a21*a34 + a14*a22*a31 - a11*a22*a34 - a12*a24*a31 - a14*a21*a32),
|
||||
d * (a21*a33*a42 + a22*a31*a43 + a23*a32*a41 - a21*a32*a43 - a22*a33*a41 - a23*a31*a42),
|
||||
d * (a11*a32*a43 + a12*a33*a41 + a13*a31*a42 - a11*a33*a42 - a12*a31*a43 - a13*a32*a41),
|
||||
d * (a11*a23*a42 + a12*a21*a43 + a13*a22*a41 - a11*a22*a43 - a12*a23*a41 - a13*a21*a42),
|
||||
d * (a11*a22*a33 + a12*a23*a31 + a13*a21*a32 - a11*a23*a32 - a12*a21*a33 - a13*a22*a31)
|
||||
};
|
||||
return i;
|
||||
}
|
||||
|
||||
float Matrix4x4::Minor(int i, int j) const {
|
||||
int r0 = SKIPNUM(0, i);
|
||||
int r1 = SKIPNUM(1, i);
|
||||
int r2 = SKIPNUM(2, i);
|
||||
int c0 = SKIPNUM(0, j);
|
||||
int c1 = SKIPNUM(1, j);
|
||||
int c2 = SKIPNUM(2, j);
|
||||
|
||||
float a = At(r0, c0);
|
||||
float b = At(r0, c1);
|
||||
float c = At(r0, c2);
|
||||
float d = At(r1, c0);
|
||||
float e = At(r1, c1);
|
||||
float f = At(r1, c2);
|
||||
float g = At(r2, c0);
|
||||
float h = At(r2, c1);
|
||||
float k = At(r2, c2);
|
||||
|
||||
return a*e*k + b*f*g + c*d*h - a*f*h - b*d*k - c*e*g;
|
||||
}
|
||||
|
||||
float Matrix4x4::Determinant() const {
|
||||
return At(0, 0) * Minor(0,0) - At(0, 1) * Minor(0,1) + At(0, 2) * Minor(0,2) - At(0, 3) * Minor(0,3);
|
||||
}
|
||||
|
||||
float Matrix4x4::Determinant3x3() const {
|
||||
|
||||
const float a = elems[0][0];
|
||||
const float b = elems[0][1];
|
||||
const float c = elems[0][2];
|
||||
const float d = elems[1][0];
|
||||
const float e = elems[1][1];
|
||||
const float f = elems[1][2];
|
||||
const float g = elems[2][0];
|
||||
const float h = elems[2][1];
|
||||
const float i = elems[2][2];
|
||||
|
||||
return a*e*i + b*f*g + c*d*h - a*f*h - b*d*i - c*e*g;
|
||||
}
|
||||
|
||||
Matrix3x3 Matrix4x4::GetRotatePart() const {
|
||||
return Matrix3x3 {
|
||||
At(0, 0), At(0, 1), At(0, 2),
|
||||
At(1, 0), At(1, 1), At(1, 2),
|
||||
At(2, 0), At(2, 1), At(2, 2)
|
||||
};
|
||||
}
|
||||
|
||||
Matrix4x4 Matrix4x4::Transpose() const {
|
||||
Matrix4x4 copy;
|
||||
copy.elems[0][0] = elems[0][0]; copy.elems[0][1] = elems[1][0]; copy.elems[0][2] = elems[2][0]; copy.elems[0][3] = elems[3][0];
|
||||
copy.elems[1][0] = elems[0][1]; copy.elems[1][1] = elems[1][1]; copy.elems[1][2] = elems[2][1]; copy.elems[1][3] = elems[3][1];
|
||||
copy.elems[2][0] = elems[0][2]; copy.elems[2][1] = elems[1][2]; copy.elems[2][2] = elems[2][2]; copy.elems[2][3] = elems[3][2];
|
||||
copy.elems[3][0] = elems[0][3]; copy.elems[3][1] = elems[1][3]; copy.elems[3][2] = elems[2][3]; copy.elems[3][3] = elems[3][3];
|
||||
return copy;
|
||||
}
|
||||
|
||||
Vector4 Matrix4x4::Diagonal() const {
|
||||
return Vector4{At(0, 0), At(1,1), At(2,2), At(3,3)};
|
||||
}
|
||||
|
||||
Vector3 Matrix4x4::Diagonal3() const {
|
||||
return Vector3 { At(0, 0), At(1,1), At(2,2) };
|
||||
}
|
||||
|
||||
Vector3 Matrix4x4::WorldX() const {
|
||||
return GetColumn3(0);
|
||||
}
|
||||
|
||||
Vector3 Matrix4x4::WorldY() const {
|
||||
return GetColumn3(1);
|
||||
}
|
||||
|
||||
Vector3 Matrix4x4::WorldZ() const {
|
||||
return GetColumn3(2);
|
||||
}
|
||||
|
||||
bool Matrix4x4::IsFinite() const {
|
||||
for(int iy = 0; iy < Rows; ++iy)
|
||||
for(int ix = 0; ix < Cols; ++ix)
|
||||
if (!std::isfinite(elems[iy][ix]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Vector3 Matrix4x4::GetColumn3(int index) const {
|
||||
return Vector3{At(0, index), At(1, index), At(2, index)};
|
||||
}
|
||||
|
||||
Vector2 Matrix4x4::operator*(const Vector2 &rhs) const { return this->Transform(rhs);}
|
||||
|
||||
Vector3 Matrix4x4::operator*(const Vector3 &rhs) const { return this->Transform(rhs);}
|
||||
|
||||
Vector4 Matrix4x4::operator*(const Vector4 &rhs) const { return this->Transform(rhs);}
|
||||
|
||||
Vector4 Matrix4x4::Transform(float tx, float ty, float tz, float tw) const {
|
||||
return Transform({tx, ty, tz, tw});
|
||||
}
|
||||
|
||||
Vector4 Matrix4x4::Transform(const Vector4 &rhs) const {
|
||||
return Vector4(At(0, 0) * rhs.x + At(0, 1) * rhs.y + At(0, 2) * rhs.z + At(0, 3) * rhs.w,
|
||||
At(1, 0) * rhs.x + At(1, 1) * rhs.y + At(1, 2) * rhs.z + At(1, 3) * rhs.w,
|
||||
At(2, 0) * rhs.x + At(2, 1) * rhs.y + At(2, 2) * rhs.z + At(2, 3) * rhs.w,
|
||||
At(3, 0) * rhs.x + At(3, 1) * rhs.y + At(3, 2) * rhs.z + At(3, 3) * rhs.w);
|
||||
}
|
||||
|
||||
Vector3 Matrix4x4::GetTranslatePart() const {
|
||||
return GetColumn3(3);
|
||||
}
|
||||
|
||||
Matrix4x4
|
||||
Matrix4x4::LookAt(const Vector3 &localFwd, const Vector3 &targetDir, const Vector3 &localUp, const Vector3 &worldUp) {
|
||||
Matrix4x4 m;
|
||||
m.Set3x3Part(Matrix3x3::LookAt(localFwd, targetDir, localUp, worldUp));
|
||||
m.SetTranslatePart(0,0,0);
|
||||
m.SetRow(3, 0,0,0,1);
|
||||
return m;
|
||||
}
|
||||
|
||||
Vector4 Matrix4x4::GetRow(int index) const {
|
||||
return { At(index, 0), At(index, 1), At(index, 2), At(index, 3)};
|
||||
}
|
||||
|
||||
Vector4 Matrix4x4::GetColumn(int index) const {
|
||||
return { At(0, index), At(1, index), At(2, index), At(3, index)};
|
||||
}
|
||||
|
||||
Vector3 Matrix4x4::GetRow3(int index) const {
|
||||
return Vector3{ At(index, 0), At(index, 1), At(index, 2)};
|
||||
}
|
||||
|
||||
void Matrix4x4::SwapColumns(int col1, int col2) {
|
||||
Swap(At(0, col1), At(0, col2));
|
||||
Swap(At(1, col1), At(1, col2));
|
||||
Swap(At(2, col1), At(2, col2));
|
||||
Swap(At(3, col1), At(3, col2));
|
||||
}
|
||||
|
||||
void Matrix4x4::SwapRows(int row1, int row2) {
|
||||
Swap(At(row1, 0), At(row2, 0));
|
||||
Swap(At(row1, 1), At(row2, 1));
|
||||
Swap(At(row1, 2), At(row2, 2));
|
||||
Swap(At(row1, 3), At(row2, 3));
|
||||
}
|
||||
|
||||
void Matrix4x4::SwapRows3(int row1, int row2) {
|
||||
Swap(At(row1, 0), At(row2, 0));
|
||||
Swap(At(row1, 1), At(row2, 1));
|
||||
Swap(At(row1, 2), At(row2, 2));
|
||||
}
|
||||
|
||||
void Matrix4x4::Pivot() {
|
||||
int rowIndex = 0;
|
||||
|
||||
for(int col = 0; col < Cols; ++col)
|
||||
{
|
||||
int greatest = rowIndex;
|
||||
|
||||
// find the rowIndex k with k >= 1 for which Mkj has the largest absolute value.
|
||||
for(int i = rowIndex; i < Rows; ++i)
|
||||
if (std::abs(At(i, col)) > std::abs(At(greatest, col)))
|
||||
greatest = i;
|
||||
|
||||
if (std::abs(At(greatest, col)) != 0)
|
||||
{
|
||||
if (rowIndex != greatest)
|
||||
SwapRows(rowIndex, greatest); // the greatest now in rowIndex
|
||||
|
||||
ScaleRow(rowIndex, 1.f/At(rowIndex, col));
|
||||
|
||||
for(int r = 0; r < Rows; ++r)
|
||||
if (r != rowIndex)
|
||||
SetRow(r, GetRow(r) - GetRow(rowIndex) * At(r, col));
|
||||
|
||||
++rowIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Matrix4x4::ScaleColumn3(int col, float scalar) {
|
||||
At(0, col) *= scalar;
|
||||
At(1, col) *= scalar;
|
||||
At(2, col) *= scalar;
|
||||
}
|
||||
|
||||
void Matrix4x4::ScaleColumn(int col, float scalar) {
|
||||
At(0, col) *= scalar;
|
||||
At(1, col) *= scalar;
|
||||
At(2, col) *= scalar;
|
||||
At(3, col) *= scalar;
|
||||
}
|
||||
|
||||
void Matrix4x4::ScaleRow3(int row, float scalar) {
|
||||
At(row, 0) *= scalar;
|
||||
At(row, 1) *= scalar;
|
||||
At(row, 2) *= scalar;
|
||||
}
|
||||
|
||||
void Matrix4x4::ScaleRow(int row, float scalar) {
|
||||
At(row, 0) *= scalar;
|
||||
At(row, 1) *= scalar;
|
||||
At(row, 2) *= scalar;
|
||||
At(row, 3) *= scalar;
|
||||
}
|
||||
}
|
@@ -4,7 +4,7 @@
|
||||
#include <J3ML/LinearAlgebra/Matrix4x4.h>
|
||||
#include <J3ML/LinearAlgebra/Quaternion.h>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
Quaternion Quaternion::operator-() const
|
||||
{
|
||||
return {-x, -y, -z, -w};
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#include <J3ML/LinearAlgebra/Transform2D.h>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
|
||||
const Transform2D Transform2D::Identity = Transform2D({0, 0}, {1, 1}, {0,0}, {0,0}, 0);
|
||||
const Transform2D Transform2D::FlipX = Transform2D({0, 0}, {-1, 1}, {0,0}, {0,0}, 0);
|
||||
|
@@ -4,7 +4,7 @@
|
||||
#include <valarray>
|
||||
#include <iostream>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
|
||||
Vector2::Vector2(): x(0), y(0)
|
||||
{}
|
||||
@@ -15,13 +15,21 @@ namespace LinearAlgebra {
|
||||
Vector2::Vector2(const Vector2& rhs): x(rhs.x), y(rhs.y)
|
||||
{}
|
||||
|
||||
float Vector2::operator[](std::size_t index)
|
||||
float Vector2::operator[](std::size_t index) const
|
||||
{
|
||||
assert(index < 2);
|
||||
if (index == 0) return x;
|
||||
if (index == 1) return y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
float &Vector2::operator[](std::size_t index)
|
||||
{
|
||||
assert(index < 2);
|
||||
if (index == 0) return x;
|
||||
if (index == 1) return y;
|
||||
}
|
||||
|
||||
bool Vector2::IsWithinMarginOfError(const Vector2& rhs, float margin) const
|
||||
{
|
||||
return this->Distance(rhs) <= margin;
|
||||
@@ -253,4 +261,6 @@ namespace LinearAlgebra {
|
||||
Vector2 Vector2::Div(const Vector2 &v) const {
|
||||
return {this->x/v.x, this->y/v.y};
|
||||
}
|
||||
|
||||
Vector2 Vector2::Abs() const { return {std::abs(x), std::abs(y)};}
|
||||
}
|
@@ -3,9 +3,9 @@
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
|
||||
|
||||
#pragma region vector3
|
||||
|
||||
const Vector3 Vector3::Zero = {0,0,0};
|
||||
const Vector3 Vector3::Up = {0, -1, 0};
|
||||
@@ -15,6 +15,8 @@ namespace LinearAlgebra {
|
||||
const Vector3 Vector3::Forward = {0, 0, -1};
|
||||
const Vector3 Vector3::Backward = {0, 0, 1};
|
||||
const Vector3 Vector3::NaN = {NAN, NAN, NAN};
|
||||
const Vector3 Vector3::Infinity = {INFINITY, INFINITY, INFINITY};
|
||||
const Vector3 Vector3::NegativeInfinity = {-INFINITY, -INFINITY, -INFINITY};
|
||||
|
||||
Vector3 Vector3::operator+(const Vector3& rhs) const
|
||||
{
|
||||
@@ -80,6 +82,14 @@ namespace LinearAlgebra {
|
||||
return 0;
|
||||
}
|
||||
|
||||
float &Vector3::operator[](std::size_t index)
|
||||
{
|
||||
assert(index < 3);
|
||||
if (index == 0) return x;
|
||||
if (index == 1) return y;
|
||||
if (index == 2) return z;
|
||||
}
|
||||
|
||||
bool Vector3::IsWithinMarginOfError(const Vector3& rhs, float margin) const
|
||||
{
|
||||
return this->Distance(rhs) <= margin;
|
||||
@@ -308,5 +318,9 @@ namespace LinearAlgebra {
|
||||
return {x, y, z};
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
Vector3 Vector3::Abs() const {
|
||||
return {std::abs(x), std::abs(y), std::abs(z)};
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -7,7 +7,7 @@
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
namespace LinearAlgebra {
|
||||
namespace J3ML::LinearAlgebra {
|
||||
|
||||
const Vector4 Vector4::Zero = {0,0,0,0};
|
||||
const Vector4 Vector4::NaN = {NAN, NAN, NAN, NAN};
|
||||
@@ -141,6 +141,15 @@ Vector4 Vector4::operator-(const Vector4& rhs) const
|
||||
|
||||
}
|
||||
|
||||
Vector4 &Vector4::operator=(const Vector4 &rhs) {
|
||||
x = rhs.x;
|
||||
y = rhs.y;
|
||||
z = rhs.z;
|
||||
w = rhs.w;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#pragma endregion
|
@@ -1,7 +1,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <J3ML/LinearAlgebra/Vector2.h>
|
||||
|
||||
using Vector2 = LinearAlgebra::Vector2;
|
||||
using J3ML::LinearAlgebra::Vector2;
|
||||
|
||||
TEST(Vector2Test, V2_Constructor_Default)
|
||||
{
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <J3ML/LinearAlgebra/Vector3.h>
|
||||
|
||||
using Vector3 = LinearAlgebra::Vector3;
|
||||
using J3ML::LinearAlgebra::Vector3;
|
||||
|
||||
void EXPECT_V3_EQ(const Vector3& lhs, const Vector3& rhs)
|
||||
{
|
||||
@@ -185,11 +185,12 @@ TEST(Vector3Test, V3_Lerp)
|
||||
EXPECT_V3_EQ(Start.Lerp(Finish, Percent), ExpectedResult);
|
||||
}
|
||||
TEST(Vector3Test, V3_AngleBetween) {
|
||||
using J3ML::LinearAlgebra::Angle2D;
|
||||
Vector3 A{ .5f, .5f, .5f};
|
||||
Vector3 B {.25f, .75f, .25f};
|
||||
A = A.Normalize();
|
||||
B = B.Normalize();
|
||||
LinearAlgebra::Angle2D ExpectedResult {-0.69791365, -2.3561945};
|
||||
Angle2D ExpectedResult {-0.69791365, -2.3561945};
|
||||
std::cout << A.AngleBetween(B).x << ", " << A.AngleBetween(B).y << "";
|
||||
auto angle = A.AngleBetween(B);
|
||||
EXPECT_FLOAT_EQ(angle.x, ExpectedResult.x);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <J3ML/LinearAlgebra/Vector4.h>
|
||||
|
||||
using Vector4 = LinearAlgebra::Vector4;
|
||||
using Vector4 = J3ML::LinearAlgebra::Vector4;
|
||||
|
||||
|
||||
void EXPECT_V4_EQ(const Vector4& lhs, const Vector4& rhs)
|
||||
|
Reference in New Issue
Block a user