PerspectiveFovLH with fx2lut impl
This commit is contained in:
parent
aedb3cdfcb
commit
c6374b6e59
|
@ -9,6 +9,7 @@ add_library(${PROJECT_NAME}
|
||||||
src/gba/sin_lut.s
|
src/gba/sin_lut.s
|
||||||
src/gba/tonc_bios.s
|
src/gba/tonc_bios.s
|
||||||
src/gba_engine.cpp
|
src/gba_engine.cpp
|
||||||
|
src/math.cpp
|
||||||
src/sound_control.cpp src/scene.cpp src/timer.cpp src/gbavector.cpp src/mesh.cpp)
|
src/sound_control.cpp src/scene.cpp src/timer.cpp src/gbavector.cpp src/mesh.cpp)
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#define GBA_BITMAP_ENGINE_PROJECT_GBAMATRIX_H
|
#define GBA_BITMAP_ENGINE_PROJECT_GBAMATRIX_H
|
||||||
|
|
||||||
#define MATRIX_DIMENSION 16
|
#define MATRIX_DIMENSION 16
|
||||||
|
#include <libgba-sprite-engine/math.h>
|
||||||
|
|
||||||
#ifdef CODE_COMPILED_AS_PART_OF_TEST
|
#ifdef CODE_COMPILED_AS_PART_OF_TEST
|
||||||
#include <libgba-sprite-engine/gba/tonc_math_stub.h>
|
#include <libgba-sprite-engine/gba/tonc_math_stub.h>
|
||||||
|
@ -13,20 +14,11 @@
|
||||||
#include <libgba-sprite-engine/gba/tonc_math.h>
|
#include <libgba-sprite-engine/gba/tonc_math.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FIXED HALF = float2fx(0.5);
|
|
||||||
FIXED ONE = int2fx(1);
|
|
||||||
|
|
||||||
class GBAMatrix {
|
class GBAMatrix {
|
||||||
private:
|
private:
|
||||||
FIXED m[MATRIX_DIMENSION];
|
FIXED m[MATRIX_DIMENSION];
|
||||||
|
|
||||||
public:
|
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 static GBAMatrix zero() { return GBAMatrix(); }
|
||||||
inline FIXED mAt(int index) const {
|
inline FIXED mAt(int index) const {
|
||||||
|
@ -57,7 +49,7 @@ public:
|
||||||
|
|
||||||
inline static GBAMatrix perspectiveFovLH(FIXED fov, FIXED aspect, FIXED znear, FIXED zfar) {
|
inline static GBAMatrix perspectiveFovLH(FIXED fov, FIXED aspect, FIXED znear, FIXED zfar) {
|
||||||
auto matrix = GBAMatrix::zero();
|
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[0] = fxdiv(tanResult, aspect);
|
||||||
matrix.m[1] = matrix.m[2] = matrix.m[3] = 0;
|
matrix.m[1] = matrix.m[2] = matrix.m[3] = 0;
|
||||||
matrix.m[5] = tanResult;
|
matrix.m[5] = tanResult;
|
||||||
|
|
|
@ -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 <libgba-sprite-engine/gba/tonc_types.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
|
||||||
|
|
||||||
|
// 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
|
|
@ -0,0 +1,8 @@
|
||||||
|
//
|
||||||
|
// Created by Wouter Groeneveld on 08/07/20.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <libgba-sprite-engine/math.h>
|
||||||
|
|
||||||
|
FIXED HALF = float2fx(0.5);
|
||||||
|
FIXED ONE = int2fx(1);
|
|
@ -33,6 +33,7 @@ add_executable(unittest
|
||||||
../engine/src/palette/palette_manager.cpp
|
../engine/src/palette/palette_manager.cpp
|
||||||
../engine/src/palette/combined_palette.cpp
|
../engine/src/palette/combined_palette.cpp
|
||||||
../engine/src/timer.cpp
|
../engine/src/timer.cpp
|
||||||
|
../engine/src/math.cpp
|
||||||
../engine/src/gbavector.cpp
|
../engine/src/gbavector.cpp
|
||||||
timertest.cpp gbavectortest.cpp gbamatrixtest.cpp fixedpoinmathtest.cpp)
|
timertest.cpp gbavectortest.cpp gbamatrixtest.cpp fixedpoinmathtest.cpp)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <libgba-sprite-engine/gba/tonc_math_stub.h>
|
#include <libgba-sprite-engine/gba/tonc_math_stub.h>
|
||||||
|
#include <libgba-sprite-engine/math.h>
|
||||||
|
|
||||||
class FpSuite : public ::testing::Test {
|
class FpSuite : public ::testing::Test {
|
||||||
protected:
|
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:
|
// from LUT doxygen:
|
||||||
//! Look-up a cosine value (2π = 0x10000)
|
//! Look-up a cosine value (2π = 0x10000)
|
||||||
|
@ -63,6 +40,25 @@ TEST_F(FpSuite, LUTValueTests) {
|
||||||
ASSERT_EQ(rnd(sinLutConv8), 0.995f);
|
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) {
|
TEST_F(FpSuite, TanUtilityTests) {
|
||||||
// 20 degrees is 0.34906577777777775 rad
|
// 20 degrees is 0.34906577777777775 rad
|
||||||
// Math.sin(0.3...) / Math.cos(0.3...) = 0.3420 / 0.9396 = 0.3639...
|
// 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 lutalpha = rad2lut(rad);
|
||||||
FIXED lusin = lu_sin(lutalpha), lucos = lu_cos(lutalpha);
|
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))));
|
auto tanFakeLookupTables = fx2float(fxdiv(fx12Tofx8(lu_sin(lutalpha)), fx12Tofx8(lu_cos(lutalpha))));
|
||||||
ASSERT_EQ(rnd(tanFakeLookupTables), 0.355f);
|
ASSERT_EQ(rnd(tanFakeLookupTables), 0.355f);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <libgba-sprite-engine/gbamatrix.h>
|
#include <libgba-sprite-engine/gbamatrix.h>
|
||||||
|
#include <libgba-sprite-engine/math.h>
|
||||||
|
|
||||||
class GBAMatrixSuite : public ::testing::Test {
|
class GBAMatrixSuite : public ::testing::Test {
|
||||||
protected:
|
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) {
|
TEST_F(GBAMatrixSuite, PerspectiveFovLH_TestData) {
|
||||||
/* IN:
|
/* IN:
|
||||||
|
@ -51,5 +39,12 @@ TEST_F(GBAMatrixSuite, PerspectiveFovLH_TestData) {
|
||||||
15: 0
|
15: 0
|
||||||
*/
|
*/
|
||||||
auto result = GBAMatrix::perspectiveFovLH(float2fx(0.78), float2fx(1.6), float2fx(0.01), float2fx(1));
|
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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue