parent
c6374b6e59
commit
a38f1eeddd
@ -1,66 +0,0 @@
|
||||
//
|
||||
// Created by Wouter Groeneveld on 08/07/20.
|
||||
//
|
||||
|
||||
#ifndef GBA_BITMAP_ENGINE_PROJECT_GBAMATRIX_H
|
||||
#define GBA_BITMAP_ENGINE_PROJECT_GBAMATRIX_H
|
||||
|
||||
#define MATRIX_DIMENSION 16
|
||||
#include <libgba-sprite-engine/math.h>
|
||||
|
||||
#ifdef CODE_COMPILED_AS_PART_OF_TEST
|
||||
#include <libgba-sprite-engine/gba/tonc_math_stub.h>
|
||||
#else
|
||||
#include <libgba-sprite-engine/gba/tonc_math.h>
|
||||
#endif
|
||||
|
||||
class GBAMatrix {
|
||||
private:
|
||||
FIXED m[MATRIX_DIMENSION];
|
||||
|
||||
public:
|
||||
|
||||
inline static GBAMatrix zero() { return GBAMatrix(); }
|
||||
inline FIXED mAt(int index) const {
|
||||
return m[index];
|
||||
}
|
||||
GBAMatrix() {}
|
||||
GBAMatrix(FIXED m11, FIXED m12, FIXED m13, FIXED m14, FIXED m21, FIXED m22, FIXED m23, FIXED m24, FIXED m31, FIXED m32, FIXED m33, FIXED m34, FIXED m41, FIXED m42, FIXED m43, FIXED m44) {
|
||||
m[0] = m11;
|
||||
m[1] = m12;
|
||||
m[2] = m13;
|
||||
m[3] = m14;
|
||||
|
||||
m[4] = m21;
|
||||
m[5] = m22;
|
||||
m[6] = m23;
|
||||
m[7] = m24;
|
||||
|
||||
m[8] = m31;
|
||||
m[9] = m32;
|
||||
m[10] = m33;
|
||||
m[11] = m34;
|
||||
|
||||
m[12] = m41;
|
||||
m[13] = m42;
|
||||
m[14] = m43;
|
||||
m[15] = m44;
|
||||
}
|
||||
|
||||
inline static GBAMatrix perspectiveFovLH(FIXED fov, FIXED aspect, FIXED znear, FIXED zfar) {
|
||||
auto matrix = GBAMatrix::zero();
|
||||
FIXED tanResult = fxdiv(ONE, fxtan(fxmul(fov, HALF)));
|
||||
matrix.m[0] = fxdiv(tanResult, aspect);
|
||||
matrix.m[1] = matrix.m[2] = matrix.m[3] = 0;
|
||||
matrix.m[5] = tanResult;
|
||||
matrix.m[4] = matrix.m[6] = matrix.m[7] = 0;
|
||||
matrix.m[8] = matrix.m[9] = 0;
|
||||
matrix.m[10] = fxdiv(-zfar, (znear - zfar));
|
||||
matrix.m[11] = ONE;
|
||||
matrix.m[12] = matrix.m[13] = matrix.m[15] = 0;
|
||||
matrix.m[14] = fxdiv(fxmul(znear, zfar), (znear - zfar));
|
||||
return matrix;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //GBA_BITMAP_ENGINE_PROJECT_GBAMATRIX_H
|
@ -0,0 +1,30 @@
|
||||
//
|
||||
// Created by Wouter Groeneveld on 09/07/20.
|
||||
//
|
||||
|
||||
#ifndef GBA_BITMAP_ENGINE_PROJECT_CAMERA_H
|
||||
#define GBA_BITMAP_ENGINE_PROJECT_CAMERA_H
|
||||
|
||||
#include <libgba-sprite-engine/vectorfx.h>
|
||||
|
||||
class Camera {
|
||||
private:
|
||||
VectorFx position;
|
||||
VectorFx target;
|
||||
|
||||
public:
|
||||
Camera() : position(VectorFx()), target(VectorFx()) {}
|
||||
Camera(VectorFx pos, VectorFx targ) : position(pos), target(targ) {}
|
||||
|
||||
VectorFx getPosition() { return position; }
|
||||
VectorFx getTarget() { return target; }
|
||||
void setPosition(VectorFx pos) {
|
||||
position = pos;
|
||||
}
|
||||
void setTarget(VectorFx tar) {
|
||||
target = tar;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //GBA_BITMAP_ENGINE_PROJECT_CAMERA_H
|
@ -1,97 +0,0 @@
|
||||
//
|
||||
// Created by Wouter Groeneveld on 14/12/18.
|
||||
// This is a FIXED-POINT VECTOR REPRESENTATION!
|
||||
// Wrapper around Tonc's VECTOR for convenience and readability.
|
||||
//
|
||||
|
||||
#ifndef GBA_VECTOR_H_
|
||||
#define GBA_VECTOR_H_
|
||||
|
||||
#include <string>
|
||||
#include <deque>
|
||||
#include <libgba-sprite-engine/gba/tonc_bios.h>
|
||||
|
||||
#ifdef CODE_COMPILED_AS_PART_OF_TEST
|
||||
#include <libgba-sprite-engine/gba/tonc_math_stub.h>
|
||||
#else
|
||||
#include <libgba-sprite-engine/gba/tonc_math.h>
|
||||
#endif
|
||||
|
||||
|
||||
class GBAVector {
|
||||
private:
|
||||
VECTOR v;
|
||||
public:
|
||||
GBAVector() : v({}) {}
|
||||
GBAVector(const GBAVector& other) : v(other.v) {}
|
||||
GBAVector(VECTOR v) : v(v) {}
|
||||
GBAVector(FIXED x, FIXED y, FIXED z) : v({ x, y, z}) {}
|
||||
|
||||
static GBAVector fromInt(int x, int y, int z) {
|
||||
return GBAVector(int2fx(x), int2fx(y), int2fx(z));
|
||||
}
|
||||
|
||||
inline GBAVector toInt() {
|
||||
return GBAVector(fx2int(v.x), fx2int(v.y), fx2int(v.z));
|
||||
}
|
||||
|
||||
std::deque<VECTOR> bresenhamLineTo(VECTOR dest);
|
||||
GBAVector rotateAsCenter(GBAVector point, FIXED angle);
|
||||
|
||||
// WHY all these inlines? performance reasons.
|
||||
inline static GBAVector up() { return GBAVector(0, int2fx(1), 0); }
|
||||
inline static FIXED dot(const GBAVector &left, const GBAVector &right) {
|
||||
return (fxmul(left.v.x, right.v.x) + fxmul(left.v.y, right.v.y) + fxmul(left.v.z, right.v.z));
|
||||
}
|
||||
inline static GBAVector cross(const GBAVector &left, const GBAVector &right) {
|
||||
FIXED x = fxmul(left.v.y, right.v.z) - fxmul(left.v.z, right.v.y);
|
||||
FIXED y = fxmul(left.v.z, right.v.x) - fxmul(left.v.x, right.v.z);
|
||||
FIXED z = fxmul(left.v.x, right.v.y) - fxmul(left.v.y, right.v.x);
|
||||
return GBAVector(x, y, z);
|
||||
}
|
||||
|
||||
inline friend GBAVector operator+(const GBAVector &one, const GBAVector &two) {
|
||||
return GBAVector(one.v.x + two.v.x, one.v.y + two.v.y, one.v.z + two.v.z);
|
||||
}
|
||||
inline friend GBAVector operator-(const GBAVector &one, const GBAVector &two) {
|
||||
return GBAVector(one.v.x - two.v.x, one.v.y - two.v.y, one.v.z - two.v.z);
|
||||
}
|
||||
inline friend GBAVector operator*(const GBAVector &one, const GBAVector &two) {
|
||||
return GBAVector(fxmul(one.v.x, two.v.x), fxmul(one.v.y, two.v.y), fxmul(one.v.z, two.v.z));
|
||||
}
|
||||
inline friend GBAVector operator/(const GBAVector &one, const GBAVector &two) {
|
||||
return GBAVector(fxdiv(one.v.x, two.v.x), fxdiv(one.v.y, two.v.y), fxdiv(one.v.z, two.v.z));
|
||||
}
|
||||
inline FIXED length() {
|
||||
FIXED toRoot = fxmul(v.x, v.x) + fxmul(v.y, v.y) + fxmul(v.z, v.z);
|
||||
return Sqrt(toRoot);
|
||||
}
|
||||
inline GBAVector negate() {
|
||||
return GBAVector(-v.x, -v.y, -v.z);
|
||||
}
|
||||
inline GBAVector scale(int scale) {
|
||||
FIXED fac = int2fx(scale);
|
||||
return GBAVector(fxmul(v.x, fac), fxmul(v.y, fac), fxmul(v.z, fac));
|
||||
}
|
||||
inline void normalize() {
|
||||
auto len = length();
|
||||
if(len == 0) return;
|
||||
FIXED num = fxdiv(int2fx(1), len);
|
||||
v.x = fxmul(v.x, num);
|
||||
v.y = fxmul(v.y, num);
|
||||
v.z = fxmul(v.z, num);
|
||||
}
|
||||
|
||||
inline FIXED x() const { return v.x; }
|
||||
inline float floatX() const { return fx2float(v.x); }
|
||||
inline FIXED y() const { return v.y; }
|
||||
inline float floatY() const { return fx2float(v.y); }
|
||||
inline FIXED z() const { return v.z; }
|
||||
inline float floatZ() const { return fx2float(v.z); }
|
||||
|
||||
std::string to_string() {
|
||||
return "(" + std::to_string(v.x) + "," + std::to_string(v.y) + ")";
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,210 @@
|
||||
//
|
||||
// Created by Wouter Groeneveld on 08/07/20.
|
||||
//
|
||||
|
||||
#ifndef GBA_BITMAP_ENGINE_PROJECT_GBAMATRIX_H
|
||||
#define GBA_BITMAP_ENGINE_PROJECT_GBAMATRIX_H
|
||||
|
||||
#define MATRIX_DIMENSION 16
|
||||
#include <libgba-sprite-engine/math.h>
|
||||
#include <libgba-sprite-engine/vectorfx.h>
|
||||
|
||||
#ifdef CODE_COMPILED_AS_PART_OF_TEST
|
||||
#include <libgba-sprite-engine/gba/tonc_math_stub.h>
|
||||
#else
|
||||
#include <libgba-sprite-engine/gba/tonc_math.h>
|
||||
#endif
|
||||
|
||||
class MatrixFx {
|
||||
private:
|
||||
FIXED m[MATRIX_DIMENSION];
|
||||
|
||||
public:
|
||||
|
||||
inline static MatrixFx zero() { return MatrixFx(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); }
|
||||
inline static MatrixFx identity() { return MatrixFx(ONE, 0, 0, 0, 0, ONE, 0, 0, 0, 0, ONE, 0, 0, 0, 0, ONE); }
|
||||
inline FIXED mAt(int index) const {
|
||||
return m[index];
|
||||
}
|
||||
MatrixFx() {}
|
||||
|
||||
inline static MatrixFx fromFloat(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24, float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44) {
|
||||
return MatrixFx(
|
||||
float2fx(m11),
|
||||
float2fx(m12),
|
||||
float2fx(m13),
|
||||
float2fx(m14),
|
||||
|
||||
float2fx(m21),
|
||||
float2fx(m22),
|
||||
float2fx(m23),
|
||||
float2fx(m24),
|
||||
|
||||
float2fx(m31),
|
||||
float2fx(m32),
|
||||
float2fx(m33),
|
||||
float2fx(m34),
|
||||
|
||||
float2fx(m41),
|
||||
float2fx(m42),
|
||||
float2fx(m43),
|
||||
float2fx(m44)
|
||||
);
|
||||
}
|
||||
|
||||
inline static MatrixFx fromInt(int m11, int m12, int m13, int m14, int m21, int m22, int m23, int m24, int m31, int m32, int m33, int m34, int m41, int m42, int m43, int m44) {
|
||||
return MatrixFx(
|
||||
int2fx(m11),
|
||||
int2fx(m12),
|
||||
int2fx(m13),
|
||||
int2fx(m14),
|
||||
|
||||
int2fx(m21),
|
||||
int2fx(m22),
|
||||
int2fx(m23),
|
||||
int2fx(m24),
|
||||
|
||||
int2fx(m31),
|
||||
int2fx(m32),
|
||||
int2fx(m33),
|
||||
int2fx(m34),
|
||||
|
||||
int2fx(m41),
|
||||
int2fx(m42),
|
||||
int2fx(m43),
|
||||
int2fx(m44)
|
||||
);
|
||||
}
|
||||
MatrixFx(FIXED m11, FIXED m12, FIXED m13, FIXED m14, FIXED m21, FIXED m22, FIXED m23, FIXED m24, FIXED m31, FIXED m32, FIXED m33, FIXED m34, FIXED m41, FIXED m42, FIXED m43, FIXED m44) {
|
||||
m[0] = m11;
|
||||
m[1] = m12;
|
||||
m[2] = m13;
|
||||
m[3] = m14;
|
||||
|
||||
m[4] = m21;
|
||||
m[5] = m22;
|
||||
m[6] = m23;
|
||||
m[7] = m24;
|
||||
|
||||
m[8] = m31;
|
||||
m[9] = m32;
|
||||
m[10] = m33;
|
||||
m[11] = m34;
|
||||
|
||||
m[12] = m41;
|
||||
m[13] = m42;
|
||||
m[14] = m43;
|
||||
m[15] = m44;
|
||||
}
|
||||
|
||||
inline static VectorFx transformCoordinates(VectorFx vector, MatrixFx transformation) {
|
||||
FIXED x = fxmul(vector.x(), transformation.mAt(0)) + fxmul(vector.y(), transformation.mAt(4)) + fxmul(vector.z(), transformation.mAt(8) + transformation.mAt(12));
|
||||
FIXED y = fxmul(vector.x(), transformation.mAt(1)) + fxmul(vector.y(), transformation.mAt(5)) + fxmul(vector.z(), transformation.mAt(9) + transformation.mAt(13));
|
||||
FIXED z = fxmul(vector.x(), transformation.mAt(2)) + fxmul(vector.y(), transformation.mAt(6)) + fxmul(vector.z(), transformation.mAt(10) + transformation.mAt(14));
|
||||
FIXED w = fxmul(vector.x(), transformation.mAt(3)) + fxmul(vector.y(), transformation.mAt(7)) + fxmul(vector.z(), transformation.mAt(11) + transformation.mAt(15));
|
||||
return VectorFx(fxdiv(x, w), fxdiv(y, w), fxdiv(z, w));
|
||||
}
|
||||
|
||||
inline friend MatrixFx operator*(const MatrixFx &thiz, const MatrixFx &other) {
|
||||
auto result = MatrixFx();
|
||||
result.m[0] = fxmul(thiz.m[0], other.m[0]) + fxmul(thiz.m[1], other.m[4]) + fxmul(thiz.m[2], other.m[8]) + fxmul(thiz.m[3], other.m[12]);
|
||||
result.m[1] = fxmul(thiz.m[0], other.m[1]) + fxmul(thiz.m[1], other.m[5]) + fxmul(thiz.m[2], other.m[9]) + fxmul(thiz.m[3], other.m[13]);
|
||||
result.m[2] = fxmul(thiz.m[0], other.m[2]) + fxmul(thiz.m[1], other.m[6]) + fxmul(thiz.m[2], other.m[10]) + fxmul(thiz.m[3], other.m[14]);
|
||||
result.m[3] = fxmul(thiz.m[0], other.m[3]) + fxmul(thiz.m[1], other.m[7]) + fxmul(thiz.m[2], other.m[11]) + fxmul(thiz.m[3], other.m[15]);
|
||||
result.m[4] = fxmul(thiz.m[4], other.m[0]) + fxmul(thiz.m[5], other.m[4]) + fxmul(thiz.m[6], other.m[8]) + fxmul(thiz.m[7], other.m[12]);
|
||||
result.m[5] = fxmul(thiz.m[4], other.m[1]) + fxmul(thiz.m[5], other.m[5]) + fxmul(thiz.m[6], other.m[9]) + fxmul(thiz.m[7], other.m[13]);
|
||||
result.m[6] = fxmul(thiz.m[4], other.m[2]) + fxmul(thiz.m[5], other.m[6]) + fxmul(thiz.m[6], other.m[10]) + fxmul(thiz.m[7], other.m[14]);
|
||||
result.m[7] = fxmul(thiz.m[4], other.m[3]) + fxmul(thiz.m[5], other.m[7]) + fxmul(thiz.m[6], other.m[11]) + fxmul(thiz.m[7], other.m[15]);
|
||||
result.m[8] = fxmul(thiz.m[8], other.m[0]) + fxmul(thiz.m[9], other.m[4]) + fxmul(thiz.m[10], other.m[8]) + fxmul(thiz.m[11], other.m[12]);
|
||||
result.m[9] = fxmul(thiz.m[8], other.m[1]) + fxmul(thiz.m[9], other.m[5]) + fxmul(thiz.m[10], other.m[9]) + fxmul(thiz.m[11], other.m[13]);
|
||||
result.m[10] = fxmul(thiz.m[8], other.m[2]) + fxmul(thiz.m[9], other.m[6]) + fxmul(thiz.m[10], other.m[10]) + fxmul(thiz.m[11], other.m[14]);
|
||||
result.m[11] = fxmul(thiz.m[8], other.m[3]) + fxmul(thiz.m[9], other.m[7]) + fxmul(thiz.m[10], other.m[11]) + fxmul(thiz.m[11], other.m[15]);
|
||||
result.m[12] = fxmul(thiz.m[12], other.m[0]) + fxmul(thiz.m[13], other.m[4]) + fxmul(thiz.m[14], other.m[8]) + fxmul(thiz.m[15], other.m[12]);
|
||||
result.m[13] = fxmul(thiz.m[12], other.m[1]) + fxmul(thiz.m[13], other.m[5]) + fxmul(thiz.m[14], other.m[9]) + fxmul(thiz.m[15], other.m[13]);
|
||||
result.m[14] = fxmul(thiz.m[12], other.m[2]) + fxmul(thiz.m[13], other.m[6]) + fxmul(thiz.m[14], other.m[10]) + fxmul(thiz.m[15], other.m[14]);
|
||||
result.m[15] = fxmul(thiz.m[12], other.m[3]) + fxmul(thiz.m[13], other.m[7]) + fxmul(thiz.m[14], other.m[11]) + fxmul(thiz.m[15], other.m[15]);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline static MatrixFx lookAtLH(VectorFx eye, VectorFx target, VectorFx up) {
|
||||
auto zAxis = target - eye;
|
||||
zAxis.normalize();
|
||||
auto xAxis = VectorFx::cross(up, zAxis);
|
||||
xAxis.normalize();
|
||||
auto yAxis = VectorFx::cross(zAxis, xAxis);
|
||||
yAxis.normalize();
|
||||
auto ex = -VectorFx::dot(xAxis, eye);
|
||||
auto ey = -VectorFx::dot(yAxis, eye);
|
||||
auto ez = -VectorFx::dot(zAxis, eye);
|
||||
|
||||
return MatrixFx(xAxis.x(), yAxis.x(), zAxis.x(), 0, xAxis.y(), yAxis.y(), zAxis.y(), 0, xAxis.z(), yAxis.z(), zAxis.z(), 0, ex, ey, ez, ONE);
|
||||
}
|
||||
|
||||
inline static MatrixFx rotationX(FIXED angle) {
|
||||
auto result = MatrixFx::zero();
|
||||
auto s = fxsin(angle);
|
||||
auto c = fxcos(angle);
|
||||
result.m[0] = 1.0;
|
||||
result.m[15] = 1.0;
|
||||
result.m[5] = c;
|
||||
result.m[10] = c;
|
||||
result.m[9] = -s;
|
||||
result.m[6] = s;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline static MatrixFx rotationY(FIXED angle) {
|
||||
auto result = MatrixFx::zero();
|
||||
auto s = fxsin(angle);
|
||||
auto c = fxcos(angle);
|
||||
result.m[5] = 1.0;
|
||||
result.m[15] = 1.0;
|
||||
result.m[0] = c;
|
||||
result.m[2] = -s;
|
||||
result.m[8] = s;
|
||||
result.m[10] = c;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline static MatrixFx rotationZ(FIXED angle) {
|
||||
auto result = MatrixFx::zero();
|
||||
auto s = fxsin(angle);
|
||||
auto c = fxcos(angle);
|
||||
result.m[10] = 1.0;
|
||||
result.m[15] = 1.0;
|
||||
result.m[0] = c;
|
||||
result.m[1] = s;
|
||||
result.m[4] = -s;
|
||||
result.m[5] = c;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline static MatrixFx translation(VectorFx vec) {
|
||||
auto result = MatrixFx::identity();
|
||||
result.m[12] = vec.x();
|
||||
result.m[13] = vec.y();
|
||||
result.m[14] = vec.z();
|
||||
return result;
|
||||
}
|
||||
|
||||
inline static MatrixFx rotationYawPitchRoll(FIXED yaw, FIXED pitch, FIXED roll) {
|
||||
return MatrixFx::rotationZ(roll) * MatrixFx::rotationX(pitch) * MatrixFx::rotationY(yaw);
|
||||
}
|
||||
|
||||
inline static MatrixFx perspectiveFovLH(FIXED fov, FIXED aspect, FIXED znear, FIXED zfar) {
|
||||
auto matrix = MatrixFx::zero();
|
||||
FIXED tanResult = fxdiv(ONE, fxtan(fxmul(fov, HALF)));
|
||||
matrix.m[0] = fxdiv(tanResult, aspect);
|
||||
matrix.m[1] = matrix.m[2] = matrix.m[3] = 0;
|
||||
matrix.m[5] = tanResult;
|
||||
matrix.m[4] = matrix.m[6] = matrix.m[7] = 0;
|
||||
matrix.m[8] = matrix.m[9] = 0;
|
||||
matrix.m[10] = fxdiv(-zfar, (znear - zfar));
|
||||
matrix.m[11] = ONE;
|
||||
matrix.m[12] = matrix.m[13] = matrix.m[15] = 0;
|
||||
matrix.m[14] = fxdiv(fxmul(znear, zfar), (znear - zfar));
|
||||
return matrix;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //GBA_BITMAP_ENGINE_PROJECT_GBAMATRIX_H
|
@ -0,0 +1,106 @@
|
||||
//
|
||||
// Created by Wouter Groeneveld on 14/12/18.
|
||||
// This is a FIXED-POINT VECTOR REPRESENTATION!
|
||||
// Wrapper around Tonc's VECTOR for convenience and readability.
|
||||
//
|
||||
|
||||
#ifndef GBA_VECTOR_H_
|
||||
#define GBA_VECTOR_H_
|
||||
|
||||
#include <string>
|
||||
#include <deque>
|
||||
#include <libgba-sprite-engine/gba/tonc_bios.h>
|
||||
|
||||
#ifdef CODE_COMPILED_AS_PART_OF_TEST
|
||||
#include <libgba-sprite-engine/gba/tonc_math_stub.h>
|
||||
#else
|
||||
#include <libgba-sprite-engine/gba/tonc_math.h>
|
||||
#endif
|
||||
|
||||
|
||||
class VectorFx {
|
||||
private:
|
||||
VECTOR v;
|
||||
public:
|
||||
VectorFx() : v({}) {}
|
||||
VectorFx(const VectorFx& other) : v(other.v) {}
|
||||
VectorFx(VECTOR v) : v(v) {}
|
||||
VectorFx(FIXED x, FIXED y, FIXED z) : v({ x, y, z}) {}
|
||||
|
||||
static VectorFx fromInt(int x, int y, int z) {
|
||||
return VectorFx(int2fx(x), int2fx(y), int2fx(z));
|
||||
}
|
||||
|
||||
inline VectorFx toInt() {
|
||||
return VectorFx(fx2int(v.x), fx2int(v.y), fx2int(v.z));
|
||||
}
|
||||
|
||||
std::deque<VECTOR> bresenhamLineTo(VECTOR dest);
|
||||
VectorFx rotateAsCenter(VectorFx point, FIXED angle);
|
||||
|
||||
// WHY all these inlines? performance reasons.
|
||||
inline static VectorFx up() { return VectorFx::fromInt(0, 1, 0); }
|
||||
inline static FIXED dot(const VectorFx &left, const VectorFx &right) {
|
||||
return (fxmul(left.v.x, right.v.x) + fxmul(left.v.y, right.v.y) + fxmul(left.v.z, right.v.z));
|
||||
}
|
||||
inline static VectorFx cross(const VectorFx &left, const VectorFx &right) {
|
||||
FIXED x = fxmul(left.v.y, right.v.z) - fxmul(left.v.z, right.v.y);
|
||||
FIXED y = fxmul(left.v.z, right.v.x) - fxmul(left.v.x, right.v.z);
|
||||
FIXED z = fxmul(left.v.x, right.v.y) - fxmul(left.v.y, right.v.x);
|
||||
return VectorFx(x, y, z);
|
||||
}
|
||||
|
||||
inline friend VectorFx operator+(const VectorFx &one, const VectorFx &two) {
|
||||
return VectorFx(one.v.x + two.v.x, one.v.y + two.v.y, one.v.z + two.v.z);
|
||||
}
|
||||
inline friend VectorFx operator-(const VectorFx &one, const VectorFx &two) {
|
||||
return VectorFx(one.v.x - two.v.x, one.v.y - two.v.y, one.v.z - two.v.z);
|
||||
}
|
||||
inline friend VectorFx operator*(const VectorFx &one, const VectorFx &two) {
|
||||
return VectorFx(fxmul(one.v.x, two.v.x), fxmul(one.v.y, two.v.y), fxmul(one.v.z, two.v.z));
|
||||
}
|
||||
inline friend VectorFx operator/(const VectorFx &one, const VectorFx &two) {
|
||||
return VectorFx(fxdiv(one.v.x, two.v.x), fxdiv(one.v.y, two.v.y), fxdiv(one.v.z, two.v.z));
|
||||
}
|
||||
inline FIXED length() {
|
||||
FIXED toRoot = fxmul(v.x, v.x) + fxmul(v.y, v.y) + fxmul(v.z, v.z);
|
||||
// tonc's fx() methods are .8fx, and BIOS needs .16 (results are .8??)
|
||||
return Sqrt(toRoot << 8);
|
||||
}
|
||||
inline VectorFx negate() {
|
||||
return VectorFx(-v.x, -v.y, -v.z);
|
||||
}
|
||||
inline VectorFx scale(int scale) {
|
||||
FIXED fac = int2fx(scale);
|
||||
return VectorFx(fxmul(v.x, fac), fxmul(v.y, fac), fxmul(v.z, fac));
|
||||
}
|
||||
inline void normalize() {
|
||||
auto len = length();
|
||||
if(len == 0) return;
|
||||
FIXED num = fxdiv(int2fx(1), len);
|
||||
v.x = fxmul(v.x, num);
|
||||
v.y = fxmul(v.y, num);
|
||||
v.z = fxmul(v.z, num);
|
||||
}
|
||||
|
||||
inline FIXED x() const { return v.x; }
|
||||
inline float floatX() const { return fx2float(v.x); }
|
||||
inline void setX(FIXED x) { v.x = x; }
|
||||
|
||||
inline FIXED y() const { return v.y; }
|
||||
inline float floatY() const { return fx2float(v.y); }
|
||||
inline void setY(FIXED y) { v.y = y; }
|
||||
|
||||
inline FIXED z() const { return v.z; }
|
||||
inline float floatZ() const { return fx2float(v.z); }
|
||||
inline void setZ(FIXED z) { v.z = z; }
|
||||
|
||||
std::string to_string() {
|
||||
return "(" + std::to_string(v.x) + "," + std::to_string(v.y) + "," + std::to_string(v.z) + ")";
|
||||
}
|
||||
std::string to_stringfl() {
|
||||
return "(" + std::to_string(fx2float(v.x)) + "," + std::to_string(fx2float(v.y)) + "," + std::to_string(fx2float(v.z)) + ")";
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
@ -1,50 +0,0 @@
|
||||
//
|
||||
// Created by Wouter Groeneveld on 08/07/20.
|
||||
//
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <math.h>
|
||||
#include <libgba-sprite-engine/gbamatrix.h>
|
||||
#include <libgba-sprite-engine/math.h>
|
||||
|
||||
class GBAMatrixSuite : public ::testing::Test {
|
||||
protected:
|
||||
virtual void TearDown() {
|
||||
}
|
||||
|
||||
virtual void SetUp() {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST_F(GBAMatrixSuite, PerspectiveFovLH_TestData) {
|
||||
/* IN:
|
||||
* fov 0.78, aspect 1.6, znear 0.01, zfar 1
|
||||
* OUT:
|
||||
0: 1.520478108791285
|
||||
1: 0
|
||||
2: 0
|
||||
3: 0
|
||||
4: 0
|
||||
5: 2.4327649740660564
|
||||
6: 0
|
||||
7: 0
|
||||
8: 0
|
||||
9: 0
|
||||
10: 1.0101010101010102
|
||||
11: 1
|
||||
12: 0
|
||||
13: 0
|
||||
14: -0.010101010101010102
|
||||
15: 0
|
||||
*/
|
||||
auto result = GBAMatrix::perspectiveFovLH(float2fx(0.78), float2fx(1.6), float2fx(0.01), float2fx(1));
|
||||
|
||||
// hmm... is this correct? rounding issues aside?
|
||||
ASSERT_EQ(rnd(fx2float(result.mAt(0))), 1.565f);
|
||||
ASSERT_EQ(fx2float(result.mAt(1)), 0);
|
||||
ASSERT_EQ(rnd(fx2float(result.mAt(5))), 2.505f);
|
||||
ASSERT_EQ(rnd(fx2float(result.mAt(10))), 1.005f);
|
||||
ASSERT_EQ(rnd(fx2float(result.mAt(14))), -0.005f);
|
||||
ASSERT_EQ(fx2float(result.mAt(15)), 0);
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
//
|
||||
// Created by Wouter Groeneveld on 08/07/20.
|
||||
//
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <math.h>
|
||||
#include <libgba-sprite-engine/matrixfx.h>
|
||||
#include <libgba-sprite-engine/math.h>
|
||||
|
||||
class MatrixFxSuite : public ::testing::Test {
|
||||
protected:
|
||||
virtual void TearDown() {
|
||||
}
|
||||
|
||||
virtual void SetUp() {
|
||||
}
|
||||
};
|
||||
|
||||
INLINE float rnd2(float val) {
|
||||
return (float) ((std::floor(val * 10) + .5) / 10);
|
||||
}
|
||||
|
||||
|
||||
void assertMatrix(MatrixFx expected, MatrixFx actual) {
|
||||
for(int i = 0; i < MATRIX_DIMENSION; i++) {
|
||||
auto expect = expected.mAt(i);
|
||||
auto act = actual.mAt(i);
|
||||
|
||||
// WHY check the rounded floats instead of fixed numbers? conversion issues. -256 and -257 should be 'equal'
|
||||
float expectFl = rnd2(fx2float(expect));
|
||||
float actFl = rnd2(fx2float(act));
|
||||
|
||||
ASSERT_EQ(expectFl, actFl) << "M[" << i << "] does not match: (exp, act) " << expect << ", " << act << " - floats: " << expectFl << ", " << actFl;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(MatrixFxSuite, lookAtLH_TestData) {
|
||||
/*
|
||||
* IN:
|
||||
* eye 0, 0, 10
|
||||
* taget: 0, 0, 0
|
||||
* up: 0, 1, 0
|
||||
* OUT:
|
||||
0: -1
|
||||
1: 0
|
||||
2: 0
|
||||
3: 0
|
||||
4: 0
|
||||
5: 1
|
||||
6: 0
|
||||
7: 0
|
||||
8: 0
|
||||
9: 0
|
||||
10: -1
|
||||
11: 0
|
||||
12: -0
|
||||
13: -0
|
||||
14: 10
|
||||
15: 1
|
||||
*/
|
||||
auto eye = VectorFx::fromInt(0, 0, 10);
|
||||
auto target = VectorFx::fromInt(0, 0, 0);
|
||||
auto up = VectorFx::up();
|
||||
auto result = MatrixFx::lookAtLH(eye, target, up);
|
||||
auto expected = MatrixFx(-257, 0, 0, 0, 0, 256, 0, 0, 0, 0, -250, 0, 0, 0, 2500, 256);
|
||||
|
||||
assertMatrix(expected, result);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(MatrixFxSuite, PerspectiveFovLH_TestData) {
|
||||
/* IN:
|
||||
* fov 0.78, aspect 1.6, znear 0.01, zfar 1
|
||||
* OUT:
|
||||
0: 1.520478108791285
|
||||
1: 0
|
||||
2: 0
|
||||
3: 0
|
||||
4: 0
|
||||
5: 2.4327649740660564
|
||||
6: 0
|
||||
7: 0
|
||||
8: 0
|
||||
9: 0
|
||||
10: 1.0101010101010102
|
||||
11: 1
|
||||
12: 0
|
||||
13: 0
|
||||
14: -0.010101010101010102
|
||||
15: 0
|
||||
*/
|
||||
auto result = MatrixFx::perspectiveFovLH(float2fx(0.78), float2fx(1.6), float2fx(0.01), float2fx(1));
|
||||
auto expected = MatrixFx::fromFloat(1.565f, 0, 0, 0, 0, 2.505f, 0, 0, 0, 0, 1.005f, 1, 0, 0, -0.005f, 0);
|
||||
|
||||
assertMatrix(expected, result);
|
||||
}
|