@@ -225,13 +225,13 @@ quat Camera::GetRotation() const | |||
// Calculate the frustum height at a given distance from the camera. | |||
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. | |||
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) | |||
@@ -1450,7 +1450,7 @@ void EasyMesh::AppendCapsule(int ndivisions, float h, float d) | |||
/* Fill in the icosahedron vertices, rotating them so that there | |||
* is a vertex at [0 1 0] and [0 -1 0] after normalisation. */ | |||
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)); | |||
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); | |||
} | |||
/* 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) | |||
{ | |||
return a + (b - a) * x; | |||
@@ -124,6 +124,8 @@ static inline float fmod(half a, half b) | |||
return fmod((float)a, (float)b); | |||
} | |||
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 clamp(half x, half a, half b) | |||
@@ -125,6 +125,8 @@ public: | |||
/* Functions inherited from GLSL */ | |||
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> degrees(Real<K> const &x); | |||
template<int K> friend Real<K> radians(Real<K> const &x); | |||
void hexprint() 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> abs(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 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 abs(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::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++) \ | |||
ret[n] = lol::abs(a[n]); \ | |||
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) \ | |||
@@ -820,6 +820,20 @@ template<> real fract(real const &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) | |||
{ | |||
/* 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) | |||
{ | |||
degrees *= (F_PI / 180.0f); | |||
float st = sin(degrees); | |||
float ct = cos(degrees); | |||
float st = sin(radians(degrees)); | |||
float ct = cos(radians(degrees)); | |||
mat2 ret; | |||
@@ -370,10 +368,8 @@ template<> mat2 mat2::rotate(float degrees) | |||
template<> mat3 mat3::rotate(float degrees, float x, float y, float z) | |||
{ | |||
degrees *= (F_PI / 180.0f); | |||
float st = sin(degrees); | |||
float ct = cos(degrees); | |||
float st = sin(radians(degrees)); | |||
float ct = cos(radians(degrees)); | |||
float len = std::sqrt(x * x + y * y + z * z); | |||
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) | |||
{ | |||
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) | |||
@@ -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]))); | |||
} | |||
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) | |||
{ | |||
mat3 ret; | |||
vec3 const radians = (F_PI / 180.0f) * v; | |||
float const s0 = sin(radians[0]), c0 = cos(radians[0]); | |||
float const s1 = sin(radians[1]), c1 = cos(radians[1]); | |||
float const s2 = sin(radians[2]), c2 = cos(radians[2]); | |||
vec3 const w = radians(v); | |||
float const s0 = sin(w[0]), c0 = cos(w[0]); | |||
float const s1 = sin(w[1]), c1 = cos(w[1]); | |||
float const s2 = sin(w[2]), c2 = cos(w[2]); | |||
/* (2 + i - j) % 3 means x-y-z direct order; otherwise indirect */ | |||
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) | |||
{ | |||
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 s1 = sin(half_angles[1]), c1 = cos(half_angles[1]); | |||
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, | |||
float height, float near, float far) | |||
{ | |||
fov_y *= (F_PI / 180.0f); | |||
float t2 = lol::tan(fov_y * 0.5f); | |||
float t2 = lol::tan(radians(fov_y) * 0.5f); | |||
float t1 = t2 * width / height; | |||
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, | |||
float screen_ratio_yx, float near, float far) | |||
{ | |||
float new_fov_y = fov_y * (F_PI / 180.0f); | |||
float tan_y = tanf(new_fov_y * .5f); | |||
float tan_y = tanf(radians(fov_y) * .5f); | |||
ASSERT(tan_y > 0.000001f); | |||
float dist_scr = (screen_size * screen_ratio_yx * .5f) / tan_y; | |||
@@ -22,6 +22,21 @@ namespace lol | |||
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) | |||
{ | |||
using std::fabs; | |||