diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index aca0f53..7ed13c7 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -9,6 +9,7 @@ add_library(${PROJECT_NAME} src/gba/sin_lut.s src/gba/tonc_bios.s src/gba_engine.cpp + src/math.cpp src/sound_control.cpp src/scene.cpp src/timer.cpp src/gbavector.cpp src/mesh.cpp) target_include_directories(${PROJECT_NAME} PUBLIC diff --git a/engine/include/libgba-sprite-engine/GBAMatrix.h b/engine/include/libgba-sprite-engine/GBAMatrix.h index c928dc0..81298c5 100644 --- a/engine/include/libgba-sprite-engine/GBAMatrix.h +++ b/engine/include/libgba-sprite-engine/GBAMatrix.h @@ -6,6 +6,7 @@ #define GBA_BITMAP_ENGINE_PROJECT_GBAMATRIX_H #define MATRIX_DIMENSION 16 +#include #ifdef CODE_COMPILED_AS_PART_OF_TEST #include @@ -13,20 +14,11 @@ #include #endif -FIXED HALF = float2fx(0.5); -FIXED ONE = int2fx(1); - class GBAMatrix { private: FIXED m[MATRIX_DIMENSION]; public: - inline static FIXED tan(FIXED angle) { - FIXED sin = lu_sin(angle) >> 4; - FIXED cos = lu_cos(angle) >> 4; - - return fxdiv(sin, cos); - } inline static GBAMatrix zero() { return GBAMatrix(); } inline FIXED mAt(int index) const { @@ -57,7 +49,7 @@ public: inline static GBAMatrix perspectiveFovLH(FIXED fov, FIXED aspect, FIXED znear, FIXED zfar) { auto matrix = GBAMatrix::zero(); - FIXED tanResult = fxdiv(ONE, tan(fxmul(fov, HALF))); + 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; diff --git a/engine/include/libgba-sprite-engine/math.h b/engine/include/libgba-sprite-engine/math.h new file mode 100644 index 0000000..227354f --- /dev/null +++ b/engine/include/libgba-sprite-engine/math.h @@ -0,0 +1,68 @@ +// +// Created by Wouter Groeneveld on 08/07/20. +// + +#ifndef GBA_BITMAP_ENGINE_PROJECT_MATH_H +#define GBA_BITMAP_ENGINE_PROJECT_MATH_H + +#include +#ifdef CODE_COMPILED_AS_PART_OF_TEST + #include + #else + #include +#endif + +// fixed point math things that were missing from TONC + +extern FIXED HALF; +extern FIXED ONE; + +// ----- +INLINE float gr2rad(uint grad); +INLINE FIXED gr2lut(uint grad); +INLINE FIXED rad2lut(float rad); +INLINE FIXED fxrad2lut(FIXED rad); +INLINE float fx12ToFloat(FIXED fx); +INLINE FIXED fx12Tofx8(FIXED fx12); +INLINE FIXED fxtan(FIXED fxrad); +INLINE float rnd(float val); + +// ---- impl +INLINE float rnd(float val) { + return (float) ((std::floor(val * 100) + .5) / 100); +} + +INLINE float gr2rad(uint grad) { + return grad*M_PI/180; +} + +INLINE FIXED gr2lut(uint grad) { + return 65535 / (360 / grad); +} + +INLINE FIXED rad2lut(float rad) { + return gr2lut(rad * 180 / M_PI); +} + +INLINE FIXED fxrad2lut(FIXED rad) { + // TODO NOT good; too much divisions, but hey, fuck it + return rad2lut(fx2float(rad)); +} + +INLINE float fx12ToFloat(FIXED fx) { + return fx / (float) (1<<12); +} + +INLINE FIXED fx12Tofx8(FIXED fx12) { + return fx12 >> 4; +} + +INLINE FIXED fxtan(FIXED fxrad) { + FIXED theta = fxrad2lut(fxrad); + FIXED sin = fx12Tofx8(lu_sin(theta)); + FIXED cos = fx12Tofx8(lu_cos(theta)); + + return fxdiv(sin, cos); +} + +#endif //GBA_BITMAP_ENGINE_PROJECT_MATH_H diff --git a/engine/src/math.cpp b/engine/src/math.cpp new file mode 100644 index 0000000..c5416b4 --- /dev/null +++ b/engine/src/math.cpp @@ -0,0 +1,8 @@ +// +// Created by Wouter Groeneveld on 08/07/20. +// + +#include + +FIXED HALF = float2fx(0.5); +FIXED ONE = int2fx(1); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0a107d6..3d668b6 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -33,6 +33,7 @@ add_executable(unittest ../engine/src/palette/palette_manager.cpp ../engine/src/palette/combined_palette.cpp ../engine/src/timer.cpp + ../engine/src/math.cpp ../engine/src/gbavector.cpp timertest.cpp gbavectortest.cpp gbamatrixtest.cpp fixedpoinmathtest.cpp) diff --git a/test/fixedpoinmathtest.cpp b/test/fixedpoinmathtest.cpp index e876f48..5c4f038 100644 --- a/test/fixedpoinmathtest.cpp +++ b/test/fixedpoinmathtest.cpp @@ -6,6 +6,7 @@ #include #include #include +#include class FpSuite : public ::testing::Test { protected: @@ -16,30 +17,6 @@ protected: } }; -float rnd(float val) { - return (float) ((std::floor(val * 100) + .5) / 100); -} - -float gr2rad(uint grad) { - return grad*M_PI/180; -} - -FIXED gr2lut(uint grad) { - return 65535 / (360 / grad); -} - -FIXED rad2lut(float rad) { - return gr2lut(rad * 180 / M_PI); -} - -float fx12ToFloat(FIXED fx) { - return fx / (float) (1<<12); -} - -FIXED fx12Tofx8(FIXED fx12) { - return fx12 >> 4; -} - // from LUT doxygen: //! Look-up a cosine value (2π = 0x10000) @@ -63,6 +40,25 @@ TEST_F(FpSuite, LUTValueTests) { ASSERT_EQ(rnd(sinLutConv8), 0.995f); } +TEST_F(FpSuite, TanFromFixedPointRadian) { + // 20 degrees is 0.34906577777777775 rad + // will be stored as .8f as input val + FIXED angle = float2fx(0.34906577777777775f); + + float result = fx2float(fxtan(angle)); + ASSERT_EQ(rnd(result), 0.355f); +} + + +TEST_F(FpSuite, SinFromFixedPointRadInput) { + // 20 degrees is 0.34906577777777775 rad + FIXED angle = float2fx(0.34906577777777775f); + + FIXED lusin = lu_sin(fxrad2lut(angle)); + float result = fx12ToFloat(lusin); + ASSERT_EQ(rnd(result), 0.335f); +} + TEST_F(FpSuite, TanUtilityTests) { // 20 degrees is 0.34906577777777775 rad // Math.sin(0.3...) / Math.cos(0.3...) = 0.3420 / 0.9396 = 0.3639... @@ -75,7 +71,7 @@ TEST_F(FpSuite, TanUtilityTests) { FIXED lutalpha = rad2lut(rad); FIXED lusin = lu_sin(lutalpha), lucos = lu_cos(lutalpha); - std::cout << "sin(14) is " << fx12ToFloat(lusin) << " and cos(14) is " << fx12ToFloat(lucos) << std::endl; + std::cout << "sin(20) is " << fx12ToFloat(lusin) << " and cos(20) is " << fx12ToFloat(lucos) << std::endl; auto tanFakeLookupTables = fx2float(fxdiv(fx12Tofx8(lu_sin(lutalpha)), fx12Tofx8(lu_cos(lutalpha)))); ASSERT_EQ(rnd(tanFakeLookupTables), 0.355f); diff --git a/test/gbamatrixtest.cpp b/test/gbamatrixtest.cpp index daeb1b6..7b909d0 100644 --- a/test/gbamatrixtest.cpp +++ b/test/gbamatrixtest.cpp @@ -5,6 +5,7 @@ #include #include #include +#include class GBAMatrixSuite : public ::testing::Test { protected: @@ -15,19 +16,6 @@ protected: } }; -TEST_F(GBAMatrixSuite, TanUtilityTests) { - // Math.sin(14) / Math.cos(14) = 0.99 / 0.13 = 7.2446 - auto tanRef = sin(14) / cos(14); - auto realTan = tan(14); - ASSERT_EQ((std::floor(tanRef * 100) + .5) / 100, 7.245); - ASSERT_EQ((std::floor(realTan * 100) + .5) / 100, 7.245); - - auto tanFakeLookupTables = ((lu_sin(14)) / (lu_cos(14))) << 4; - ASSERT_EQ((std::floor(tanFakeLookupTables * 100) + .5) / 100, 7.245); - - auto result = fx2float(GBAMatrix::tan(int2fx(14))); - ASSERT_EQ(result, 7.2446); -} TEST_F(GBAMatrixSuite, PerspectiveFovLH_TestData) { /* IN: @@ -51,5 +39,12 @@ TEST_F(GBAMatrixSuite, PerspectiveFovLH_TestData) { 15: 0 */ auto result = GBAMatrix::perspectiveFovLH(float2fx(0.78), float2fx(1.6), float2fx(0.01), float2fx(1)); - ASSERT_EQ(fx2float(result.mAt(0)), 1.52); + + // 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); }