| @@ -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; | |||