@@ -225,13 +225,13 @@ quat Camera::GetRotation() const | |||||
// Calculate the frustum height at a given distance from the camera. | // Calculate the frustum height at a given distance from the camera. | ||||
float Camera::GetFrustumHeightAtDistance(float distance, float fov) const | float Camera::GetFrustumHeightAtDistance(float distance, float fov) const | ||||
{ | { | ||||
return 2.f * distance * lol::tan(fov * .5f * (F_PI / 180.f)); | return 2.f * distance * lol::tan(radians(fov * .5f)); | ||||
} | } | ||||
// Calculate the FOV needed to get a given frustum height at a given distance. | // Calculate the FOV needed to get a given frustum height at a given distance. | ||||
float Camera::GetFOVForHeightAndDistance(float distance, float height) const | float Camera::GetFOVForHeightAndDistance(float distance, float height) const | ||||
{ | { | ||||
return 2.f * lol::atan(height * .5f / distance) * (180.f / F_PI); | return 2.f * radians(lol::atan(height * .5f / distance)); | ||||
} | } | ||||
void Camera::TickGame(float seconds) | void Camera::TickGame(float seconds) | ||||
@@ -1450,7 +1450,7 @@ void EasyMesh::AppendCapsule(int ndivisions, float h, float d) | |||||
/* Fill in the icosahedron vertices, rotating them so that there | /* Fill in the icosahedron vertices, rotating them so that there | ||||
* is a vertex at [0 1 0] and [0 -1 0] after normalisation. */ | * is a vertex at [0 1 0] and [0 -1 0] after normalisation. */ | ||||
float phi = 0.5f + 0.5f * sqrt(5.f); | float phi = 0.5f + 0.5f * sqrt(5.f); | ||||
mat3 mat = mat3::rotate(asin(1.f / sqrt(2.f + phi)) * (180.f / F_PI), | mat3 mat = mat3::rotate(degrees(asin(1.f / sqrt(2.f + phi))), | ||||
vec3(0.f, 0.f, 1.f)); | vec3(0.f, 0.f, 1.f)); | ||||
for (int i = 0; i < 4; i++) | for (int i = 0; i < 4; i++) | ||||
{ | { | ||||
@@ -84,6 +84,55 @@ static inline void sincos(float const &x, float *s, float *c) | |||||
*c = std::cos(x); | *c = std::cos(x); | ||||
} | } | ||||
/* Inherited from GLSL */ | |||||
static inline float degrees(float radians) | |||||
{ | |||||
return radians * (180.0f / F_PI); | |||||
} | |||||
static inline double degrees(double radians) | |||||
{ | |||||
return radians * (180.0 / D_PI); | |||||
} | |||||
static inline ldouble degrees(ldouble radians) | |||||
{ | |||||
return radians * (180.0L / LD_PI); | |||||
} | |||||
static inline int8_t degrees(int8_t x) { return degrees((float)x); } | |||||
static inline uint8_t degrees(uint8_t x) { return degrees((float)x); } | |||||
static inline int16_t degrees(int16_t x) { return degrees((float)x); } | |||||
static inline uint16_t degrees(uint16_t x) { return degrees((float)x); } | |||||
static inline int32_t degrees(int32_t x) { return degrees((double)x); } | |||||
static inline uint32_t degrees(uint32_t x) { return degrees((double)x); } | |||||
static inline int64_t degrees(int64_t x) { return degrees((ldouble)x); } | |||||
static inline uint64_t degrees(uint64_t x) { return degrees((ldouble)x); } | |||||
static inline float radians(float degrees) | |||||
{ | |||||
return degrees * (F_PI / 180.0f); | |||||
} | |||||
static inline double radians(double degrees) | |||||
{ | |||||
return degrees * (D_PI / 180.0); | |||||
} | |||||
static inline ldouble radians(ldouble degrees) | |||||
{ | |||||
return degrees * (LD_PI / 180.0L); | |||||
} | |||||
static inline int8_t radians(int8_t x) { return radians((float)x); } | |||||
static inline uint8_t radians(uint8_t x) { return radians((float)x); } | |||||
static inline int16_t radians(int16_t x) { return radians((float)x); } | |||||
static inline uint16_t radians(uint16_t x) { return radians((float)x); } | |||||
static inline int32_t radians(int32_t x) { return radians((double)x); } | |||||
static inline uint32_t radians(uint32_t x) { return radians((double)x); } | |||||
static inline int64_t radians(int64_t x) { return radians((ldouble)x); } | |||||
static inline uint64_t radians(uint64_t x) { return radians((ldouble)x); } | |||||
static inline float lerp(float const &a, float const &b, float const &x) | static inline float lerp(float const &a, float const &b, float const &x) | ||||
{ | { | ||||
return a + (b - a) * x; | return a + (b - a) * x; | ||||
@@ -124,6 +124,8 @@ static inline float fmod(half a, half b) | |||||
return fmod((float)a, (float)b); | return fmod((float)a, (float)b); | ||||
} | } | ||||
static inline float fract(half a) { return fract((float)a); } | static inline float fract(half a) { return fract((float)a); } | ||||
static inline float degrees(half a) { return degrees((float)a); } | |||||
static inline float radians(half a) { return radians((float)a); } | |||||
static inline half abs(half a) { return half::makebits(a.bits & 0x7fffu); } | static inline half abs(half a) { return half::makebits(a.bits & 0x7fffu); } | ||||
static inline half clamp(half x, half a, half b) | static inline half clamp(half x, half a, half b) | ||||
@@ -125,6 +125,8 @@ public: | |||||
/* Functions inherited from GLSL */ | /* Functions inherited from GLSL */ | ||||
template<int K> friend Real<K> abs(Real<K> const &x); | template<int K> friend Real<K> abs(Real<K> const &x); | ||||
template<int K> friend Real<K> fract(Real<K> const &x); | template<int K> friend Real<K> fract(Real<K> const &x); | ||||
template<int K> friend Real<K> degrees(Real<K> const &x); | |||||
template<int K> friend Real<K> radians(Real<K> const &x); | |||||
void hexprint() const; | void hexprint() const; | ||||
void print(int ndigits = 150) const; | void print(int ndigits = 150) const; | ||||
@@ -276,6 +278,8 @@ template<int K> Real<K> round(Real<K> const &x); | |||||
template<int K> Real<K> fmod(Real<K> const &x, Real<K> const &y); | template<int K> Real<K> fmod(Real<K> const &x, Real<K> const &y); | ||||
template<int K> Real<K> abs(Real<K> const &x); | template<int K> Real<K> abs(Real<K> const &x); | ||||
template<int K> Real<K> fract(Real<K> const &x); | template<int K> Real<K> fract(Real<K> const &x); | ||||
template<int K> Real<K> degrees(Real<K> const &x); | |||||
template<int K> Real<K> radians(Real<K> const &x); | |||||
template<> real min(real const &a, real const &b); | template<> real min(real const &a, real const &b); | ||||
template<> real max(real const &a, real const &b); | template<> real max(real const &a, real const &b); | ||||
@@ -314,6 +318,8 @@ template<> real round(real const &x); | |||||
template<> real fmod(real const &x, real const &y); | template<> real fmod(real const &x, real const &y); | ||||
template<> real abs(real const &x); | template<> real abs(real const &x); | ||||
template<> real fract(real const &x); | template<> real fract(real const &x); | ||||
template<> real degrees(real const &x); | |||||
template<> real radians(real const &x); | |||||
template<> void real::hexprint() const; | template<> void real::hexprint() const; | ||||
template<> void real::print(int ndigits) const; | template<> void real::print(int ndigits) const; | ||||
@@ -1399,6 +1399,24 @@ extern Quat<T> slerp(Quat<T> const &qa, Quat<T> const &qb, T f); | |||||
for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \ | for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \ | ||||
ret[n] = lol::abs(a[n]); \ | ret[n] = lol::abs(a[n]); \ | ||||
return ret; \ | return ret; \ | ||||
} \ | |||||
\ | |||||
tprefix \ | |||||
inline tname<type> degrees(tname<type> const &a) \ | |||||
{ \ | |||||
tname<type> ret; \ | |||||
for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \ | |||||
ret[n] = lol::degrees(a[n]); \ | |||||
return ret; \ | |||||
} \ | |||||
\ | |||||
tprefix \ | |||||
inline tname<type> radians(tname<type> const &a) \ | |||||
{ \ | |||||
tname<type> ret; \ | |||||
for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \ | |||||
ret[n] = lol::radians(a[n]); \ | |||||
return ret; \ | |||||
} | } | ||||
#define LOL_BINARY_NONVECTOR_FUNS(tname, tprefix, type) \ | #define LOL_BINARY_NONVECTOR_FUNS(tname, tprefix, type) \ | ||||
@@ -820,6 +820,20 @@ template<> real fract(real const &x) | |||||
return x - floor(x); | return x - floor(x); | ||||
} | } | ||||
template<> real degrees(real const &x) | |||||
{ | |||||
static real mul = real(180) * real::R_1_PI(); | |||||
return x * mul; | |||||
} | |||||
template<> real radians(real const &x) | |||||
{ | |||||
static real mul = real::R_PI() / real(180); | |||||
return x * mul; | |||||
} | |||||
static real fast_log(real const &x) | static real fast_log(real const &x) | ||||
{ | { | ||||
/* This fast log method is tuned to work on the [1..2] range and | /* This fast log method is tuned to work on the [1..2] range and | ||||
@@ -352,10 +352,8 @@ template<> mat4 mat4::translate(vec3 v) | |||||
template<> mat2 mat2::rotate(float degrees) | template<> mat2 mat2::rotate(float degrees) | ||||
{ | { | ||||
degrees *= (F_PI / 180.0f); | float st = sin(radians(degrees)); | ||||
float ct = cos(radians(degrees)); | |||||
float st = sin(degrees); | |||||
float ct = cos(degrees); | |||||
mat2 ret; | mat2 ret; | ||||
@@ -370,10 +368,8 @@ template<> mat2 mat2::rotate(float degrees) | |||||
template<> mat3 mat3::rotate(float degrees, float x, float y, float z) | template<> mat3 mat3::rotate(float degrees, float x, float y, float z) | ||||
{ | { | ||||
degrees *= (F_PI / 180.0f); | float st = sin(radians(degrees)); | ||||
float ct = cos(radians(degrees)); | |||||
float st = sin(degrees); | |||||
float ct = cos(degrees); | |||||
float len = std::sqrt(x * x + y * y + z * z); | float len = std::sqrt(x * x + y * y + z * z); | ||||
float invlen = len ? 1.0f / len : 0.0f; | float invlen = len ? 1.0f / len : 0.0f; | ||||
@@ -489,11 +485,11 @@ template<> quat::Quat(mat4 const &m) | |||||
template<> quat quat::rotate(float degrees, vec3 const &v) | template<> quat quat::rotate(float degrees, vec3 const &v) | ||||
{ | { | ||||
degrees *= (F_PI / 360.0f); | float half_angle = radians(degrees) * 0.5f; | ||||
vec3 tmp = normalize(v) * sin(degrees); | vec3 tmp = normalize(v) * sin(half_angle); | ||||
return quat(cos(degrees), tmp.x, tmp.y, tmp.z); | return quat(cos(half_angle), tmp.x, tmp.y, tmp.z); | ||||
} | } | ||||
template<> quat quat::rotate(float degrees, float x, float y, float z) | template<> quat quat::rotate(float degrees, float x, float y, float z) | ||||
@@ -563,17 +559,17 @@ static inline vec3 quat_toeuler_generic(quat const &q, int i, int j, int k) | |||||
1.f - 2.f * (sq(q[1 + k]) + sq(q[1 + j]))); | 1.f - 2.f * (sq(q[1 + k]) + sq(q[1 + j]))); | ||||
} | } | ||||
return (180.0f / F_PI / n) * ret; | return degrees(ret / n); | ||||
} | } | ||||
static inline mat3 mat3_fromeuler_generic(vec3 const &v, int i, int j, int k) | static inline mat3 mat3_fromeuler_generic(vec3 const &v, int i, int j, int k) | ||||
{ | { | ||||
mat3 ret; | mat3 ret; | ||||
vec3 const radians = (F_PI / 180.0f) * v; | vec3 const w = radians(v); | ||||
float const s0 = sin(radians[0]), c0 = cos(radians[0]); | float const s0 = sin(w[0]), c0 = cos(w[0]); | ||||
float const s1 = sin(radians[1]), c1 = cos(radians[1]); | float const s1 = sin(w[1]), c1 = cos(w[1]); | ||||
float const s2 = sin(radians[2]), c2 = cos(radians[2]); | float const s2 = sin(w[2]), c2 = cos(w[2]); | ||||
/* (2 + i - j) % 3 means x-y-z direct order; otherwise indirect */ | /* (2 + i - j) % 3 means x-y-z direct order; otherwise indirect */ | ||||
float const sign = ((2 + i - j) % 3) ? 1.f : -1.f; | float const sign = ((2 + i - j) % 3) ? 1.f : -1.f; | ||||
@@ -616,7 +612,7 @@ static inline mat3 mat3_fromeuler_generic(vec3 const &v, int i, int j, int k) | |||||
static inline quat quat_fromeuler_generic(vec3 const &v, int i, int j, int k) | static inline quat quat_fromeuler_generic(vec3 const &v, int i, int j, int k) | ||||
{ | { | ||||
vec3 const half_angles = (F_PI / 360.0f) * v; | vec3 const half_angles = radians(v * 0.5f); | ||||
float const s0 = sin(half_angles[0]), c0 = cos(half_angles[0]); | float const s0 = sin(half_angles[0]), c0 = cos(half_angles[0]); | ||||
float const s1 = sin(half_angles[1]), c1 = cos(half_angles[1]); | float const s1 = sin(half_angles[1]), c1 = cos(half_angles[1]); | ||||
float const s2 = sin(half_angles[2]), c2 = cos(half_angles[2]); | float const s2 = sin(half_angles[2]), c2 = cos(half_angles[2]); | ||||
@@ -771,9 +767,7 @@ template<> mat4 mat4::frustum(float left, float right, float bottom, | |||||
template<> mat4 mat4::perspective(float fov_y, float width, | template<> mat4 mat4::perspective(float fov_y, float width, | ||||
float height, float near, float far) | float height, float near, float far) | ||||
{ | { | ||||
fov_y *= (F_PI / 180.0f); | float t2 = lol::tan(radians(fov_y) * 0.5f); | ||||
float t2 = lol::tan(fov_y * 0.5f); | |||||
float t1 = t2 * width / height; | float t1 = t2 * width / height; | ||||
return frustum(-near * t1, near * t1, -near * t2, near * t2, near, far); | return frustum(-near * t1, near * t1, -near * t2, near * t2, near, far); | ||||
@@ -783,8 +777,7 @@ template<> mat4 mat4::perspective(float fov_y, float width, | |||||
template<> mat4 mat4::shifted_perspective(float fov_y, float screen_size, | template<> mat4 mat4::shifted_perspective(float fov_y, float screen_size, | ||||
float screen_ratio_yx, float near, float far) | float screen_ratio_yx, float near, float far) | ||||
{ | { | ||||
float new_fov_y = fov_y * (F_PI / 180.0f); | float tan_y = tanf(radians(fov_y) * .5f); | ||||
float tan_y = tanf(new_fov_y * .5f); | |||||
ASSERT(tan_y > 0.000001f); | ASSERT(tan_y > 0.000001f); | ||||
float dist_scr = (screen_size * screen_ratio_yx * .5f) / tan_y; | float dist_scr = (screen_size * screen_ratio_yx * .5f) / tan_y; | ||||
@@ -22,6 +22,21 @@ namespace lol | |||||
LOLUNIT_FIXTURE(TrigTest) | LOLUNIT_FIXTURE(TrigTest) | ||||
{ | { | ||||
LOLUNIT_TEST(AngleConversions) | |||||
{ | |||||
LOLUNIT_ASSERT_DOUBLES_EQUAL(D_PI, radians(180.0), 1e-5); | |||||
LOLUNIT_ASSERT_DOUBLES_EQUAL(D_PI_2, radians(90.0), 1e-5); | |||||
LOLUNIT_ASSERT_DOUBLES_EQUAL(F_PI, radians(180.0f), 1e-5f); | |||||
LOLUNIT_ASSERT_DOUBLES_EQUAL(F_PI_2, radians(90.0f), 1e-5f); | |||||
LOLUNIT_ASSERT_DOUBLES_EQUAL(180.0, degrees(D_PI), 1e-5); | |||||
LOLUNIT_ASSERT_DOUBLES_EQUAL(90.0, degrees(D_PI_2), 1e-5); | |||||
LOLUNIT_ASSERT_DOUBLES_EQUAL(180.0f, degrees(F_PI), 1e-5f); | |||||
LOLUNIT_ASSERT_DOUBLES_EQUAL(90.0f, degrees(F_PI_2), 1e-5f); | |||||
} | |||||
LOLUNIT_TEST(Sin) | LOLUNIT_TEST(Sin) | ||||
{ | { | ||||
using std::fabs; | using std::fabs; | ||||