Make everything use radians (#107)

* Make everything use radians (and provide an escape hatch)

* Fix tests

* Add tests for forcing degrees

* Add degrees tests for windows

* Remove coverage macro; just always use radians

* Update forward declarations and clean up tests

* Tell the user that angles are in radians
This commit is contained in:
Ben Visness
2020-04-06 09:56:43 -05:00
committed by GitHub
parent a9b08b9147
commit 68d2af495c
5 changed files with 39 additions and 18 deletions

View File

@@ -4,6 +4,8 @@
This is a single header file with a bunch of useful functions for game and
graphics math operations.
All angles are in radians.
=============================================================================
You MUST
@@ -544,6 +546,16 @@ HMM_INLINE float HMM_PowerF(float Base, float Exponent)
* Utility functions
*/
COVERAGE(HMM_ToDegrees, 1)
HMM_INLINE float HMM_ToDegrees(float Radians)
{
ASSERT_COVERED(HMM_ToDegrees);
float Result = Radians * (180.0f / HMM_PI32);
return (Result);
}
COVERAGE(HMM_ToRadians, 1)
HMM_INLINE float HMM_ToRadians(float Degrees)
{
@@ -1404,7 +1416,7 @@ HMM_INLINE hmm_mat4 HMM_Orthographic(float Left, float Right, float Bottom, floa
}
COVERAGE(HMM_Perspective, 1)
HMM_INLINE hmm_mat4 HMM_Perspective(float FOV, float AspectRatio, float Near, float Far)
HMM_INLINE hmm_mat4 HMM_Perspective(float FOVRadians, float AspectRatio, float Near, float Far)
{
ASSERT_COVERED(HMM_Perspective);
@@ -1412,7 +1424,7 @@ HMM_INLINE hmm_mat4 HMM_Perspective(float FOV, float AspectRatio, float Near, fl
// See https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml
float Cotangent = 1.0f / HMM_TanF(FOV * (HMM_PI32 / 360.0f));
float Cotangent = 1.0f / HMM_TanF(FOVRadians / 2.0f);
Result.Elements[0][0] = Cotangent / AspectRatio;
Result.Elements[1][1] = Cotangent;
@@ -1438,7 +1450,7 @@ HMM_INLINE hmm_mat4 HMM_Translate(hmm_vec3 Translation)
return (Result);
}
HMM_EXTERN hmm_mat4 HMM_Rotate(float Angle, hmm_vec3 Axis);
HMM_EXTERN hmm_mat4 HMM_Rotate(float AngleRadians, hmm_vec3 Axis);
COVERAGE(HMM_Scale, 1)
HMM_INLINE hmm_mat4 HMM_Scale(hmm_vec3 Scale)
@@ -1675,7 +1687,7 @@ HMM_INLINE hmm_quaternion HMM_NLerp(hmm_quaternion Left, float Time, hmm_quatern
HMM_EXTERN hmm_quaternion HMM_Slerp(hmm_quaternion Left, float Time, hmm_quaternion Right);
HMM_EXTERN hmm_mat4 HMM_QuaternionToMat4(hmm_quaternion Left);
HMM_EXTERN hmm_quaternion HMM_Mat4ToQuaternion(hmm_mat4 Left);
HMM_EXTERN hmm_quaternion HMM_QuaternionFromAxisAngle(hmm_vec3 Axis, float AngleOfRotation);
HMM_EXTERN hmm_quaternion HMM_QuaternionFromAxisAngle(hmm_vec3 Axis, float AngleOfRotationRadians);
#ifdef __cplusplus
}
@@ -2978,7 +2990,7 @@ hmm_mat4 HMM_DivideMat4f(hmm_mat4 Matrix, float Scalar)
#endif
COVERAGE(HMM_Rotate, 1)
hmm_mat4 HMM_Rotate(float Angle, hmm_vec3 Axis)
hmm_mat4 HMM_Rotate(float AngleRadians, hmm_vec3 Axis)
{
ASSERT_COVERED(HMM_Rotate);
@@ -2986,8 +2998,8 @@ hmm_mat4 HMM_Rotate(float Angle, hmm_vec3 Axis)
Axis = HMM_NormalizeVec3(Axis);
float SinTheta = HMM_SinF(HMM_ToRadians(Angle));
float CosTheta = HMM_CosF(HMM_ToRadians(Angle));
float SinTheta = HMM_SinF(AngleRadians);
float CosTheta = HMM_CosF(AngleRadians);
float CosValue = 1.0f - CosTheta;
Result.Elements[0][0] = (Axis.X * Axis.X * CosValue) + CosTheta;
@@ -3205,17 +3217,17 @@ hmm_quaternion HMM_Mat4ToQuaternion(hmm_mat4 M)
}
COVERAGE(HMM_QuaternionFromAxisAngle, 1)
hmm_quaternion HMM_QuaternionFromAxisAngle(hmm_vec3 Axis, float AngleOfRotation)
hmm_quaternion HMM_QuaternionFromAxisAngle(hmm_vec3 Axis, float AngleOfRotationRadians)
{
ASSERT_COVERED(HMM_QuaternionFromAxisAngle);
hmm_quaternion Result;
hmm_vec3 AxisNormalized = HMM_NormalizeVec3(Axis);
float SineOfRotation = HMM_SinF(AngleOfRotation / 2.0f);
float SineOfRotation = HMM_SinF(AngleOfRotationRadians / 2.0f);
Result.XYZ = HMM_MultiplyVec3f(AxisNormalized, SineOfRotation);
Result.W = HMM_CosF(AngleOfRotation / 2.0f);
Result.W = HMM_CosF(AngleOfRotationRadians / 2.0f);
return (Result);
}

View File

@@ -15,7 +15,7 @@ TEST(Projection, Orthographic)
TEST(Projection, Perspective)
{
hmm_mat4 projection = HMM_Perspective(90.0f, 2.0f, 5.0f, 15.0f);
hmm_mat4 projection = HMM_Perspective(HMM_ToRadians(90.0f), 2.0f, 5.0f, 15.0f);
{
hmm_vec3 original = HMM_Vec3(5.0f, 5.0f, -15.0f);

View File

@@ -111,7 +111,7 @@ TEST(QuaternionOps, Mat4ToQuat)
// Rotate 90 degrees on the X axis
{
hmm_mat4 m = HMM_Rotate(90, HMM_Vec3(1, 0, 0));
hmm_mat4 m = HMM_Rotate(HMM_ToRadians(90.0f), HMM_Vec3(1, 0, 0));
hmm_quaternion result = HMM_Mat4ToQuaternion(m);
float cosf = 0.707107f; // cos(90/2 degrees)
@@ -125,7 +125,7 @@ TEST(QuaternionOps, Mat4ToQuat)
// Rotate 90 degrees on the Y axis (axis not normalized, just for fun)
{
hmm_mat4 m = HMM_Rotate(90, HMM_Vec3(0, 2, 0));
hmm_mat4 m = HMM_Rotate(HMM_ToRadians(90.0f), HMM_Vec3(0, 2, 0));
hmm_quaternion result = HMM_Mat4ToQuaternion(m);
float cosf = 0.707107f; // cos(90/2 degrees)
@@ -139,7 +139,7 @@ TEST(QuaternionOps, Mat4ToQuat)
// Rotate 90 degrees on the Z axis
{
hmm_mat4 m = HMM_Rotate(90, HMM_Vec3(0, 0, 1));
hmm_mat4 m = HMM_Rotate(HMM_ToRadians(90.0f), HMM_Vec3(0, 0, 1));
hmm_quaternion result = HMM_Mat4ToQuaternion(m);
float cosf = 0.707107f; // cos(90/2 degrees)
@@ -153,7 +153,7 @@ TEST(QuaternionOps, Mat4ToQuat)
// Rotate 45 degrees on the X axis (this hits case 4)
{
hmm_mat4 m = HMM_Rotate(45, HMM_Vec3(1, 0, 0));
hmm_mat4 m = HMM_Rotate(HMM_ToRadians(45.0f), HMM_Vec3(1, 0, 0));
hmm_quaternion result = HMM_Mat4ToQuaternion(m);
float cosf = 0.9238795325f; // cos(90/2 degrees)

View File

@@ -36,6 +36,13 @@ TEST(ScalarMath, Trigonometry)
// checking that things work by default.
}
TEST(ScalarMath, ToDegrees)
{
EXPECT_FLOAT_EQ(HMM_ToDegrees(0.0f), 0.0f);
EXPECT_FLOAT_EQ(HMM_ToDegrees(HMM_PI32), 180.0f);
EXPECT_FLOAT_EQ(HMM_ToDegrees(-HMM_PI32), -180.0f);
}
TEST(ScalarMath, ToRadians)
{
EXPECT_FLOAT_EQ(HMM_ToRadians(0.0f), 0.0f);

View File

@@ -17,21 +17,23 @@ TEST(Transformations, Rotate)
{
hmm_vec3 original = HMM_Vec3(1.0f, 1.0f, 1.0f);
hmm_mat4 rotateX = HMM_Rotate(90, HMM_Vec3(1, 0, 0));
float angle = HMM_ToRadians(90.0f);
hmm_mat4 rotateX = HMM_Rotate(angle, HMM_Vec3(1, 0, 0));
hmm_vec4 rotatedX = HMM_MultiplyMat4ByVec4(rotateX, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(rotatedX.X, 1.0f);
EXPECT_FLOAT_EQ(rotatedX.Y, -1.0f);
EXPECT_FLOAT_EQ(rotatedX.Z, 1.0f);
EXPECT_FLOAT_EQ(rotatedX.W, 1.0f);
hmm_mat4 rotateY = HMM_Rotate(90, HMM_Vec3(0, 1, 0));
hmm_mat4 rotateY = HMM_Rotate(angle, HMM_Vec3(0, 1, 0));
hmm_vec4 rotatedY = HMM_MultiplyMat4ByVec4(rotateY, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(rotatedY.X, 1.0f);
EXPECT_FLOAT_EQ(rotatedY.Y, 1.0f);
EXPECT_FLOAT_EQ(rotatedY.Z, -1.0f);
EXPECT_FLOAT_EQ(rotatedY.W, 1.0f);
hmm_mat4 rotateZ = HMM_Rotate(90, HMM_Vec3(0, 0, 1));
hmm_mat4 rotateZ = HMM_Rotate(angle, HMM_Vec3(0, 0, 1));
hmm_vec4 rotatedZ = HMM_MultiplyMat4ByVec4(rotateZ, HMM_Vec4v(original, 1));
EXPECT_FLOAT_EQ(rotatedZ.X, -1.0f);
EXPECT_FLOAT_EQ(rotatedZ.Y, 1.0f);