Compare commits

..

9 Commits

Author SHA1 Message Date
Ben Visness
ea1b8c3fdf Add models 2020-04-26 15:15:07 -05:00
Ben Visness
066df8dc02 Get a matrix in there 2020-04-25 11:33:49 -05:00
Ben Visness
cee57ba573 Start of new example stuff 2020-04-25 11:33:49 -05:00
Ben Visness
c66971850a Update version and release notes 2020-04-25 11:33:48 -05:00
Ben Visness
43b5686636 Add ability to customize HMM_ prefix (#114)
* Add prefix macro and use it everywhere

* Add lightweight test for prefix

* Add a little doc blurb
2020-04-25 11:33:48 -05:00
Ben Visness
49f274249f Suppress float equality warnings (#113)
* Add a macro to help with deprecations

* Suppress warnings about float equality
2020-04-25 11:33:47 -05:00
Zak Strange
f1297e7f31 Removed use of stdint.h (#110) 2020-04-25 11:33:47 -05:00
Ben Visness
d3d09f8352 Make all functions static inline (#117)
* Make all functions static inline

* Updated email in credits

Co-authored-by: Zakary Strange <ZakaryStrange@gmail.com>
2020-04-11 18:41:26 -05:00
Ben Visness
68d2af495c 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
2020-04-06 09:56:43 -05:00
23 changed files with 18898 additions and 231 deletions

3
.gitignore vendored
View File

@@ -31,4 +31,7 @@
*.exe
*.out
*.app
test/build
example/build
example/lib/flextgl/*

9
.gitmodules vendored
View File

@@ -0,0 +1,9 @@
[submodule "example/lib/glfw"]
path = example/lib/glfw
url = git@github.com:glfw/glfw.git
[submodule "example/lib/flextgl-gen"]
path = example/lib/flextgl-gen
url = git@github.com:mosra/flextgl.git
[submodule "example/lib/EGL-Registry"]
path = example/lib/EGL-Registry
url = git@github.com:KhronosGroup/EGL-Registry.git

View File

@@ -1,8 +1,6 @@
# Understanding the structure of Handmade Math
Most of the functions in Handmade Math are very short, and are the kind of functions you want to have inlined. Because of this, most functions in Handmade Math are defined with `HINLINE`, which is defined as `static inline`.
The exceptions are functions like `HMM_Rotate`, which are long enough that it doesn't make sense to inline them. These functions are defined with an `HEXTERN` prototype, and implemented in the `#ifdef HANDMADE_MATH_IMPLEMENTATION` block.
Most of the functions in Handmade Math are very short, and all are the kind of functions you want to be easily inlined for performance. Because of this, all functions in Handmade Math are defined with `HMM_INLINE`, which is defined as `static inline`.
# Quick style guide
@@ -14,7 +12,7 @@ The exceptions are functions like `HMM_Rotate`, which are long enough that it do
0.5f;
1.0f;
3.14159f;
// Bad
1.f
.0f

View File

@@ -1,17 +1,18 @@
/*
HandmadeMath.h v1.13.0
HandmadeMath.h v1.11.0
This is a single header file with a bunch of useful functions for game and
graphics math operations.
All angles are in radians.
=============================================================================
To disable SSE intrinsics, you MUST
#define HANDMADE_MATH_NO_SSE
in EXACTLY one C or C++ file that includes this header, BEFORE the
include, like this:
BEFORE the include, like this:
#define HANDMADE_MATH_NO_SSE
#include "HandmadeMath.h"
@@ -41,8 +42,7 @@
#define HMM_ATAN2F MYATan2F
Provide your own implementations of SinF, CosF, TanF, ACosF, ATanF, ATan2F,
ExpF, and LogF in EXACTLY one C or C++ file that includes this header,
BEFORE the include, like this:
ExpF, and LogF BEFORE the include, like this:
#define HMM_SINF MySinF
#define HMM_COSF MyCosF
@@ -68,14 +68,15 @@
CREDITS
Written by Zakary Strange (strangezak@protonmail.com && @strangezak)
Written by:
Zakary Strange (zakarystrange@gmail.com && @strangezak)
Ben Visness (ben@bvisness.me && @its_bvisness)
Functionality:
Matt Mascarenhas (@miblo_)
Aleph
FieryDrake (@fierydrake)
Gingerbill (@TheGingerBill)
Ben Visness (@bvisness)
Trinton Bullard (@Peliex_Dev)
@AntonDan
@@ -127,12 +128,11 @@
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#if (defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) || defined(__clang__)
#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
#pragma GCC diagnostic ignored "-Wmissing-braces"
#endif
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wgnu-anonymous-struct"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
#endif
@@ -196,10 +196,10 @@ extern "C"
#define HMM_PI32 3.14159265359f
#define HMM_PI 3.14159265358979323846
#define HMM_MIN(a, b) ((a) > (b) ? (b) : (a))
#define HMM_MAX(a, b) ((a) < (b) ? (b) : (a))
#define HMM_MIN(a, b) (a) > (b) ? (b) : (a)
#define HMM_MAX(a, b) (a) < (b) ? (b) : (a)
#define HMM_ABS(a) ((a) > 0 ? (a) : -(a))
#define HMM_MOD(a, m) (((a) % (m)) >= 0 ? ((a) % (m)) : (((a) % (m)) + (m)))
#define HMM_MOD(a, m) ((a) % (m)) >= 0 ? ((a) % (m)) : (((a) % (m)) + (m))
#define HMM_SQUARE(x) ((x) * (x))
#ifndef HMM_PREFIX
@@ -367,16 +367,15 @@ typedef union hmm_mat4
#ifdef __cplusplus
inline hmm_vec4 operator[](const int &Index)
{
hmm_vec4 Result;
float* Column = Elements[Index];
float* col = Elements[Index];
Result.Elements[0] = Column[0];
Result.Elements[1] = Column[1];
Result.Elements[2] = Column[2];
Result.Elements[3] = Column[3];
hmm_vec4 result;
result.Elements[0] = col[0];
result.Elements[1] = col[1];
result.Elements[2] = col[2];
result.Elements[3] = col[3];
return Result;
return result;
}
#endif
} hmm_mat4;
@@ -533,7 +532,7 @@ HMM_INLINE float HMM_PREFIX(RSquareRootF)(float Float)
}
COVERAGE(HMM_Power, 2)
HMM_INLINE float HMM_PREFIX(Power)(float Base, int Exponent)
HMM_INLINE float HMM_Power(float Base, int Exponent)
{
ASSERT_COVERED(HMM_Power);
@@ -571,6 +570,16 @@ HMM_INLINE float HMM_PREFIX(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_PREFIX(ToRadians)(float Degrees)
{
@@ -602,8 +611,7 @@ HMM_INLINE float HMM_PREFIX(Clamp)(float Min, float Value, float Max)
{
Result = Min;
}
if(Result > Max)
else if(Result > Max)
{
Result = Max;
}
@@ -1314,11 +1322,15 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix)
{
ASSERT_COVERED(HMM_Transpose);
#ifdef HANDMADE_MATH__USE_SSE
hmm_mat4 Result = Matrix;
#ifdef HANDMADE_MATH__USE_SSE
_MM_TRANSPOSE4_PS(Result.Columns[0], Result.Columns[1], Result.Columns[2], Result.Columns[3]);
return (Result);
#else
hmm_mat4 Result;
int Columns;
for(Columns = 0; Columns < 4; ++Columns)
{
@@ -1328,10 +1340,9 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(Transpose)(hmm_mat4 Matrix)
Result.Elements[Rows][Columns] = Matrix.Elements[Columns][Rows];
}
}
#endif
return (Result);
#endif
}
COVERAGE(HMM_AddMat4, 1)
@@ -1339,15 +1350,19 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right)
{
ASSERT_COVERED(HMM_AddMat4);
#ifdef HANDMADE_MATH__USE_SSE
hmm_mat4 Result;
#ifdef HANDMADE_MATH__USE_SSE
Result.Columns[0] = _mm_add_ps(Left.Columns[0], Right.Columns[0]);
Result.Columns[1] = _mm_add_ps(Left.Columns[1], Right.Columns[1]);
Result.Columns[2] = _mm_add_ps(Left.Columns[2], Right.Columns[2]);
Result.Columns[3] = _mm_add_ps(Left.Columns[3], Right.Columns[3]);
return (Result);
#else
int Columns;
hmm_mat4 Result;
int Columns;
for(Columns = 0; Columns < 4; ++Columns)
{
int Rows;
@@ -1356,10 +1371,9 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(AddMat4)(hmm_mat4 Left, hmm_mat4 Right)
Result.Elements[Columns][Rows] = Left.Elements[Columns][Rows] + Right.Elements[Columns][Rows];
}
}
#endif
return (Result);
#endif
}
COVERAGE(HMM_SubtractMat4, 1)
@@ -1367,14 +1381,18 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right)
{
ASSERT_COVERED(HMM_SubtractMat4);
#ifdef HANDMADE_MATH__USE_SSE
hmm_mat4 Result;
#ifdef HANDMADE_MATH__USE_SSE
Result.Columns[0] = _mm_sub_ps(Left.Columns[0], Right.Columns[0]);
Result.Columns[1] = _mm_sub_ps(Left.Columns[1], Right.Columns[1]);
Result.Columns[2] = _mm_sub_ps(Left.Columns[2], Right.Columns[2]);
Result.Columns[3] = _mm_sub_ps(Left.Columns[3], Right.Columns[3]);
return (Result);
#else
hmm_mat4 Result;
int Columns;
for(Columns = 0; Columns < 4; ++Columns)
{
@@ -1384,23 +1402,23 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(SubtractMat4)(hmm_mat4 Left, hmm_mat4 Right)
Result.Elements[Columns][Rows] = Left.Elements[Columns][Rows] - Right.Elements[Columns][Rows];
}
}
#endif
return (Result);
#endif
}
COVERAGE(HMM_MultiplyMat4, 1)
HMM_INLINE hmm_mat4 HMM_PREFIX(MultiplyMat4)(hmm_mat4 Left, hmm_mat4 Right)
HMM_INLINE hmm_mat4 HMM_MultiplyMat4(hmm_mat4 Left, hmm_mat4 Right)
{
ASSERT_COVERED(HMM_MultiplyMat4);
hmm_mat4 Result;
#ifdef HANDMADE_MATH__USE_SSE
Result.Columns[0] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[0], Left);
Result.Columns[1] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[1], Left);
Result.Columns[2] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[2], Left);
Result.Columns[3] = HMM_PREFIX(LinearCombineSSE)(Right.Columns[3], Left);
Result.Columns[0] = HMM_LinearCombineSSE(Right.Columns[0], Left);
Result.Columns[1] = HMM_LinearCombineSSE(Right.Columns[1], Left);
Result.Columns[2] = HMM_LinearCombineSSE(Right.Columns[2], Left);
Result.Columns[3] = HMM_LinearCombineSSE(Right.Columns[3], Left);
#else
int Columns;
for(Columns = 0; Columns < 4; ++Columns)
@@ -1423,21 +1441,24 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(MultiplyMat4)(hmm_mat4 Left, hmm_mat4 Right)
return (Result);
}
COVERAGE(HMM_MultiplyMat4f, 1)
HMM_INLINE hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar)
{
ASSERT_COVERED(HMM_MultiplyMat4f);
#ifdef HANDMADE_MATH__USE_SSE
hmm_mat4 Result;
#ifdef HANDMADE_MATH__USE_SSE
__m128 SSEScalar = _mm_set1_ps(Scalar);
Result.Columns[0] = _mm_mul_ps(Matrix.Columns[0], SSEScalar);
Result.Columns[1] = _mm_mul_ps(Matrix.Columns[1], SSEScalar);
Result.Columns[2] = _mm_mul_ps(Matrix.Columns[2], SSEScalar);
Result.Columns[3] = _mm_mul_ps(Matrix.Columns[3], SSEScalar);
return (Result);
#else
hmm_mat4 Result;
int Columns;
for(Columns = 0; Columns < 4; ++Columns)
{
@@ -1447,20 +1468,20 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(MultiplyMat4f)(hmm_mat4 Matrix, float Scalar)
Result.Elements[Columns][Rows] = Matrix.Elements[Columns][Rows] * Scalar;
}
}
#endif
return (Result);
#endif
}
COVERAGE(HMM_MultiplyMat4ByVec4, 1)
HMM_INLINE hmm_vec4 HMM_PREFIX(MultiplyMat4ByVec4)(hmm_mat4 Matrix, hmm_vec4 Vector)
HMM_INLINE hmm_vec4 HMM_MultiplyMat4ByVec4(hmm_mat4 Matrix, hmm_vec4 Vector)
{
ASSERT_COVERED(HMM_MultiplyMat4ByVec4);
hmm_vec4 Result;
#ifdef HANDMADE_MATH__USE_SSE
Result.InternalElementsSSE = HMM_PREFIX(LinearCombineSSE)(Vector.InternalElementsSSE, Matrix);
Result.InternalElementsSSE = HMM_LinearCombineSSE(Vector.InternalElementsSSE, Matrix);
#else
int Columns, Rows;
for(Rows = 0; Rows < 4; ++Rows)
@@ -1478,21 +1499,24 @@ HMM_INLINE hmm_vec4 HMM_PREFIX(MultiplyMat4ByVec4)(hmm_mat4 Matrix, hmm_vec4 Vec
return (Result);
}
COVERAGE(HMM_DivideMat4f, 1)
HMM_INLINE hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar)
{
ASSERT_COVERED(HMM_DivideMat4f);
#ifdef HANDMADE_MATH__USE_SSE
hmm_mat4 Result;
#ifdef HANDMADE_MATH__USE_SSE
__m128 SSEScalar = _mm_set1_ps(Scalar);
Result.Columns[0] = _mm_div_ps(Matrix.Columns[0], SSEScalar);
Result.Columns[1] = _mm_div_ps(Matrix.Columns[1], SSEScalar);
Result.Columns[2] = _mm_div_ps(Matrix.Columns[2], SSEScalar);
Result.Columns[3] = _mm_div_ps(Matrix.Columns[3], SSEScalar);
return (Result);
#else
hmm_mat4 Result;
int Columns;
for(Columns = 0; Columns < 4; ++Columns)
{
@@ -1502,11 +1526,12 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(DivideMat4f)(hmm_mat4 Matrix, float Scalar)
Result.Elements[Columns][Rows] = Matrix.Elements[Columns][Rows] / Scalar;
}
}
#endif
return (Result);
#endif
}
/*
* Common graphics transformations
*/
@@ -1531,7 +1556,7 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(Orthographic)(float Left, float Right, float Bott
}
COVERAGE(HMM_Perspective, 1)
HMM_INLINE hmm_mat4 HMM_PREFIX(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);
@@ -1539,7 +1564,7 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(Perspective)(float FOV, float AspectRatio, float
// See https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml
float Cotangent = 1.0f / HMM_PREFIX(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;
@@ -1566,16 +1591,16 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(Translate)(hmm_vec3 Translation)
}
COVERAGE(HMM_Rotate, 1)
HMM_INLINE hmm_mat4 HMM_PREFIX(Rotate)(float Angle, hmm_vec3 Axis)
HMM_INLINE hmm_mat4 HMM_Rotate(float AngleRadians, hmm_vec3 Axis)
{
ASSERT_COVERED(HMM_Rotate);
hmm_mat4 Result = HMM_PREFIX(Mat4d)(1.0f);
hmm_mat4 Result = HMM_Mat4d(1.0f);
Axis = HMM_PREFIX(NormalizeVec3)(Axis);
Axis = HMM_NormalizeVec3(Axis);
float SinTheta = HMM_PREFIX(SinF)(HMM_PREFIX(ToRadians)(Angle));
float CosTheta = HMM_PREFIX(CosF)(HMM_PREFIX(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;
@@ -1593,8 +1618,6 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(Rotate)(float Angle, hmm_vec3 Axis)
return (Result);
}
COVERAGE(HMM_Scale, 1)
HMM_INLINE hmm_mat4 HMM_PREFIX(Scale)(hmm_vec3 Scale)
{
@@ -1610,15 +1633,15 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(Scale)(hmm_vec3 Scale)
}
COVERAGE(HMM_LookAt, 1)
HMM_INLINE hmm_mat4 HMM_PREFIX(LookAt)(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up)
HMM_INLINE hmm_mat4 HMM_LookAt(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up)
{
ASSERT_COVERED(HMM_LookAt);
hmm_mat4 Result;
hmm_vec3 F = HMM_PREFIX(NormalizeVec3)(HMM_PREFIX(SubtractVec3)(Center, Eye));
hmm_vec3 S = HMM_PREFIX(NormalizeVec3)(HMM_PREFIX(Cross)(F, Up));
hmm_vec3 U = HMM_PREFIX(Cross)(S, F);
hmm_vec3 F = HMM_NormalizeVec3(HMM_SubtractVec3(Center, Eye));
hmm_vec3 S = HMM_NormalizeVec3(HMM_Cross(F, Up));
hmm_vec3 U = HMM_Cross(S, F);
Result.Elements[0][0] = S.X;
Result.Elements[0][1] = U.X;
@@ -1635,14 +1658,15 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(LookAt)(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 U
Result.Elements[2][2] = -F.Z;
Result.Elements[2][3] = 0.0f;
Result.Elements[3][0] = -HMM_PREFIX(DotVec3)(S, Eye);
Result.Elements[3][1] = -HMM_PREFIX(DotVec3)(U, Eye);
Result.Elements[3][2] = HMM_PREFIX(DotVec3)(F, Eye);
Result.Elements[3][0] = -HMM_DotVec3(S, Eye);
Result.Elements[3][1] = -HMM_DotVec3(U, Eye);
Result.Elements[3][2] = HMM_DotVec3(F, Eye);
Result.Elements[3][3] = 1.0f;
return (Result);
}
/*
* Quaternion operations
*/
@@ -1819,25 +1843,29 @@ HMM_INLINE float HMM_PREFIX(DotQuaternion)(hmm_quaternion Left, hmm_quaternion R
return (Result);
}
COVERAGE(HMM_InverseQuaternion, 1)
HMM_INLINE hmm_quaternion HMM_PREFIX(InverseQuaternion)(hmm_quaternion Left)
HMM_INLINE hmm_quaternion HMM_InverseQuaternion(hmm_quaternion Left)
{
ASSERT_COVERED(HMM_InverseQuaternion);
hmm_quaternion Conjugate;
hmm_quaternion Result;
float Norm = 0;
float NormSquared = 0;
Result.X = -Left.X;
Result.Y = -Left.Y;
Result.Z = -Left.Z;
Result.W = Left.W;
Conjugate.X = -Left.X;
Conjugate.Y = -Left.Y;
Conjugate.Z = -Left.Z;
Conjugate.W = Left.W;
Result = HMM_PREFIX(DivideQuaternionF)(Result, (HMM_PREFIX(DotQuaternion)(Left, Left)));
Norm = HMM_SquareRootF(HMM_DotQuaternion(Left, Left));
NormSquared = Norm * Norm;
Result = HMM_DivideQuaternionF(Conjugate, NormSquared);
return (Result);
}
COVERAGE(HMM_NormalizeQuaternion, 1)
HMM_INLINE hmm_quaternion HMM_PREFIX(NormalizeQuaternion)(hmm_quaternion Left)
{
@@ -1876,7 +1904,7 @@ HMM_INLINE hmm_quaternion HMM_PREFIX(NLerp)(hmm_quaternion Left, float Time, hmm
}
COVERAGE(HMM_Slerp, 1)
HMM_INLINE hmm_quaternion HMM_PREFIX(Slerp)(hmm_quaternion Left, float Time, hmm_quaternion Right)
HMM_INLINE hmm_quaternion HMM_Slerp(hmm_quaternion Left, float Time, hmm_quaternion Right)
{
ASSERT_COVERED(HMM_Slerp);
@@ -1884,30 +1912,30 @@ HMM_INLINE hmm_quaternion HMM_PREFIX(Slerp)(hmm_quaternion Left, float Time, hmm
hmm_quaternion QuaternionLeft;
hmm_quaternion QuaternionRight;
float Cos_Theta = HMM_PREFIX(DotQuaternion)(Left, Right);
float Angle = HMM_PREFIX(ACosF)(Cos_Theta);
float Cos_Theta = HMM_DotQuaternion(Left, Right);
float Angle = HMM_ACosF(Cos_Theta);
float S1 = HMM_PREFIX(SinF)((1.0f - Time) * Angle);
float S2 = HMM_PREFIX(SinF)(Time * Angle);
float Is = 1.0f / HMM_PREFIX(SinF)(Angle);
float S1 = HMM_SinF((1.0f - Time) * Angle);
float S2 = HMM_SinF(Time * Angle);
float Is = 1.0f / HMM_SinF(Angle);
QuaternionLeft = HMM_PREFIX(MultiplyQuaternionF)(Left, S1);
QuaternionRight = HMM_PREFIX(MultiplyQuaternionF)(Right, S2);
QuaternionLeft = HMM_MultiplyQuaternionF(Left, S1);
QuaternionRight = HMM_MultiplyQuaternionF(Right, S2);
Result = HMM_PREFIX(AddQuaternion)(QuaternionLeft, QuaternionRight);
Result = HMM_PREFIX(MultiplyQuaternionF)(Result, Is);
Result = HMM_AddQuaternion(QuaternionLeft, QuaternionRight);
Result = HMM_MultiplyQuaternionF(Result, Is);
return (Result);
}
COVERAGE(HMM_QuaternionToMat4, 1)
HMM_INLINE hmm_mat4 HMM_PREFIX(QuaternionToMat4)(hmm_quaternion Left)
HMM_INLINE hmm_mat4 HMM_QuaternionToMat4(hmm_quaternion Left)
{
ASSERT_COVERED(HMM_QuaternionToMat4);
hmm_mat4 Result;
hmm_quaternion NormalizedQuaternion = HMM_PREFIX(NormalizeQuaternion)(Left);
hmm_quaternion NormalizedQuaternion = HMM_NormalizeQuaternion(Left);
float XX, YY, ZZ,
XY, XZ, YZ,
@@ -1961,7 +1989,7 @@ HMM_INLINE hmm_mat4 HMM_PREFIX(QuaternionToMat4)(hmm_quaternion Left)
// Don't be confused! Or if you must be confused, at least trust this
// comment. :)
COVERAGE(HMM_Mat4ToQuaternion, 4)
HMM_INLINE hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 M)
HMM_INLINE hmm_quaternion HMM_Mat4ToQuaternion(hmm_mat4 M)
{
float T;
hmm_quaternion Q;
@@ -1971,7 +1999,7 @@ HMM_INLINE hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 M)
ASSERT_COVERED(HMM_Mat4ToQuaternion);
T = 1 + M.Elements[0][0] - M.Elements[1][1] - M.Elements[2][2];
Q = HMM_PREFIX(Quaternion)(
Q = HMM_Quaternion(
T,
M.Elements[0][1] + M.Elements[1][0],
M.Elements[2][0] + M.Elements[0][2],
@@ -1981,7 +2009,7 @@ HMM_INLINE hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 M)
ASSERT_COVERED(HMM_Mat4ToQuaternion);
T = 1 - M.Elements[0][0] + M.Elements[1][1] - M.Elements[2][2];
Q = HMM_PREFIX(Quaternion)(
Q = HMM_Quaternion(
M.Elements[0][1] + M.Elements[1][0],
T,
M.Elements[1][2] + M.Elements[2][1],
@@ -1993,7 +2021,7 @@ HMM_INLINE hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 M)
ASSERT_COVERED(HMM_Mat4ToQuaternion);
T = 1 - M.Elements[0][0] - M.Elements[1][1] + M.Elements[2][2];
Q = HMM_PREFIX(Quaternion)(
Q = HMM_Quaternion(
M.Elements[2][0] + M.Elements[0][2],
M.Elements[1][2] + M.Elements[2][1],
T,
@@ -2003,7 +2031,7 @@ HMM_INLINE hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 M)
ASSERT_COVERED(HMM_Mat4ToQuaternion);
T = 1 + M.Elements[0][0] + M.Elements[1][1] + M.Elements[2][2];
Q = HMM_PREFIX(Quaternion)(
Q = HMM_Quaternion(
M.Elements[1][2] - M.Elements[2][1],
M.Elements[2][0] - M.Elements[0][2],
M.Elements[0][1] - M.Elements[1][0],
@@ -2012,23 +2040,23 @@ HMM_INLINE hmm_quaternion HMM_PREFIX(Mat4ToQuaternion)(hmm_mat4 M)
}
}
Q = HMM_PREFIX(MultiplyQuaternionF)(Q, 0.5f / HMM_PREFIX(SquareRootF)(T));
Q = HMM_MultiplyQuaternionF(Q, 0.5f / HMM_SquareRootF(T));
return Q;
}
COVERAGE(HMM_QuaternionFromAxisAngle, 1)
HMM_INLINE hmm_quaternion HMM_PREFIX(QuaternionFromAxisAngle)(hmm_vec3 Axis, float AngleOfRotation)
HMM_INLINE hmm_quaternion HMM_QuaternionFromAxisAngle(hmm_vec3 Axis, float AngleOfRotationRadians)
{
ASSERT_COVERED(HMM_QuaternionFromAxisAngle);
hmm_quaternion Result;
hmm_vec3 AxisNormalized = HMM_PREFIX(NormalizeVec3)(Axis);
float SineOfRotation = HMM_PREFIX(SinF)(AngleOfRotation / 2.0f);
hmm_vec3 AxisNormalized = HMM_NormalizeVec3(Axis);
float SineOfRotation = HMM_SinF(AngleOfRotationRadians / 2.0f);
Result.XYZ = HMM_PREFIX(MultiplyVec3f)(AxisNormalized, SineOfRotation);
Result.W = HMM_PREFIX(CosF)(AngleOfRotation / 2.0f);
Result.XYZ = HMM_MultiplyVec3f(AxisNormalized, SineOfRotation);
Result.W = HMM_CosF(AngleOfRotationRadians / 2.0f);
return (Result);
}
@@ -2045,6 +2073,7 @@ HMM_INLINE float HMM_PREFIX(Length)(hmm_vec2 A)
ASSERT_COVERED(HMM_LengthVec2CPP);
float Result = HMM_PREFIX(LengthVec2)(A);
return (Result);
}
@@ -3124,46 +3153,6 @@ HMM_INLINE hmm_bool operator!=(hmm_vec4 Left, hmm_vec4 Right)
return !HMM_PREFIX(EqualsVec4)(Left, Right);
}
COVERAGE(HMM_UnaryMinusVec2, 1)
HMM_INLINE hmm_vec2 operator-(hmm_vec2 In)
{
ASSERT_COVERED(HMM_UnaryMinusVec2);
hmm_vec2 Result;
Result.X = -In.X;
Result.Y = -In.Y;
return(Result);
}
COVERAGE(HMM_UnaryMinusVec3, 1)
HMM_INLINE hmm_vec3 operator-(hmm_vec3 In)
{
ASSERT_COVERED(HMM_UnaryMinusVec3);
hmm_vec3 Result;
Result.X = -In.X;
Result.Y = -In.Y;
Result.Z = -In.Z;
return(Result);
}
COVERAGE(HMM_UnaryMinusVec4, 1)
HMM_INLINE hmm_vec4 operator-(hmm_vec4 In)
{
ASSERT_COVERED(HMM_UnaryMinusVec4);
hmm_vec4 Result;
#if HANDMADE_MATH__USE_SSE
Result.InternalElementsSSE = _mm_xor_ps(In.InternalElementsSSE, _mm_set1_ps(-0.0f));
#else
Result.X = -In.X;
Result.Y = -In.Y;
Result.Z = -In.Z;
Result.W = -In.W;
#endif
return(Result);
}
#endif /* __cplusplus */
#if defined(__GNUC__) || defined(__clang__)
@@ -3171,6 +3160,3 @@ HMM_INLINE hmm_vec4 operator-(hmm_vec4 In)
#endif
#endif /* HANDMADE_MATH_H */

View File

@@ -10,11 +10,6 @@ To get started, go download [the latest release](https://github.com/HandmadeMath
Version | Changes |
----------------|----------------|
**1.13.0** | Fully inlined HandmadeMath.h. No need for HANDMADE_MATH_IMPLEMENTATION anymore |
**1.12.1** | Added extra parentheses around some macros |
**1.12.0** | Added Unary Minus operator for `HMM_Vec2`, `HMM_Vec3`, and `HMM_Vec4`. |
**1.11.1** | Added HMM_PREFIX macro to a few functions that were missing it. |
**1.11.0** | Added ability to customize or remove the default `HMM_` prefix on function names by defining a macro called `HMM_PREFIX(name)`. |
**1.10.1** | Removed stdint.h, this doesn't exist on some really old compilers and we didn't really use it anyways. |
**1.10.0** | Made HMM_Perspective use vertical FOV instead of horizontal FOV for consistency with other graphics APIs. |
@@ -42,7 +37,7 @@ Version | Changes |
**0.5** | Added scalar operations on vectors and matrices, added += and -= for hmm_mat4, reconciled headers and implementations, tidied up in general |
**0.4** | Added SSE Optimized HMM_SqrtF, HMM_RSqrtF, Removed use of C Runtime |
**0.3** | Added +=,-=, *=, /= for hmm_vec2, hmm_vec3, hmm_vec4 |
**0.2b** | Disabled warning C4201 on MSVC, Added 64bit precision on HMM_PI |
**0.2b** | Disabled warning C4201 on MSVC, Added 64bit percision on HMM_PI |
**0.2a** | Prefixed Macros |
**0.2** | Updated Documentation, Fixed C Compliance, Prefixed all functions, and added better operator overloading |
**0.1** | Initial Version |

34
example/Makefile Normal file
View File

@@ -0,0 +1,34 @@
ifeq ($(OS),Windows_NT)
RM = del /Q /F
RMDIR = rmdir /Q /S
CP = copy /Y
PYTHON = python
PIP = pip
else
RM = rm -rf
RMDIR = rm -rf
CP = cp -f
PYTHON = python3
PIP = pip3
endif
BUILD_DIR=build
all: example
example: lib/flextgl/flextgl.h
$(RMDIR) $(BUILD_DIR)
mkdir $(BUILD_DIR)
cd $(BUILD_DIR) \
&& $(CC) -std=c99 -c -lm \
-I../lib/glfw/include \
-I../lib/flextgl \
-I../lib/EGL-Registry/api \
../src/main.c ../lib/flextgl/flextGL.c \
&& $(CC) -ohmm_example.exe main.o -lm
flextgl-deps:
$(PIP) install --user wheezy.template
lib/flextgl/flextgl.h lib/flextgl/flextgl.c: flextgl-deps
$(PYTHON) lib/flextgl-gen/flextGLgen.py -D lib/flextgl -T glfw3 flextgl-profile.txt

19
example/build.bat Normal file
View File

@@ -0,0 +1,19 @@
@echo off
where /q cl
if ERRORLEVEL 1 (
for /f "delims=" %%a in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -find VC\Auxiliary\Build\vcvarsall.bat') do (%%a x64)
)
python lib\flextgl-gen\flextGLgen.py -D lib\flextgl -T glfw3 flextgl-profile.txt
if not exist "build" mkdir build
pushd build
cl ^
/Feexample.exe /MD ^
/I..\lib\glfw\include /I..\lib\flextgl /I..\lib\EGL-Registry\api ^
..\src\main.c ..\lib\flextgl\flextGL.c ^
/link user32.lib shell32.lib gdi32.lib opengl32.lib ..\lib\glfw\lib-vc2017\glfw3.lib
popd

View File

@@ -0,0 +1 @@
version 3.3 core

3
example/install.bat Normal file
View File

@@ -0,0 +1,3 @@
@echo off
pip install --user wheezy.template

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,525 @@
/*************************************************************************
* GLFW 3.3 - www.glfw.org
* A library for OpenGL, window and input
*------------------------------------------------------------------------
* Copyright (c) 2002-2006 Marcus Geelnard
* Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
*************************************************************************/
#ifndef _glfw3_native_h_
#define _glfw3_native_h_
#ifdef __cplusplus
extern "C" {
#endif
/*************************************************************************
* Doxygen documentation
*************************************************************************/
/*! @file glfw3native.h
* @brief The header of the native access functions.
*
* This is the header file of the native access functions. See @ref native for
* more information.
*/
/*! @defgroup native Native access
* @brief Functions related to accessing native handles.
*
* **By using the native access functions you assert that you know what you're
* doing and how to fix problems caused by using them. If you don't, you
* shouldn't be using them.**
*
* Before the inclusion of @ref glfw3native.h, you may define zero or more
* window system API macro and zero or more context creation API macros.
*
* The chosen backends must match those the library was compiled for. Failure
* to do this will cause a link-time error.
*
* The available window API macros are:
* * `GLFW_EXPOSE_NATIVE_WIN32`
* * `GLFW_EXPOSE_NATIVE_COCOA`
* * `GLFW_EXPOSE_NATIVE_X11`
* * `GLFW_EXPOSE_NATIVE_WAYLAND`
*
* The available context API macros are:
* * `GLFW_EXPOSE_NATIVE_WGL`
* * `GLFW_EXPOSE_NATIVE_NSGL`
* * `GLFW_EXPOSE_NATIVE_GLX`
* * `GLFW_EXPOSE_NATIVE_EGL`
* * `GLFW_EXPOSE_NATIVE_OSMESA`
*
* These macros select which of the native access functions that are declared
* and which platform-specific headers to include. It is then up your (by
* definition platform-specific) code to handle which of these should be
* defined.
*/
/*************************************************************************
* System headers and types
*************************************************************************/
#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL)
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
// example to allow applications to correctly declare a GL_ARB_debug_output
// callback) but windows.h assumes no one will define APIENTRY before it does
#if defined(GLFW_APIENTRY_DEFINED)
#undef APIENTRY
#undef GLFW_APIENTRY_DEFINED
#endif
#include <windows.h>
#elif defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
#if defined(__OBJC__)
#import <Cocoa/Cocoa.h>
#else
#include <ApplicationServices/ApplicationServices.h>
typedef void* id;
#endif
#elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
#include <wayland-client.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_WGL)
/* WGL is declared by windows.h */
#endif
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
/* NSGL is declared by Cocoa.h */
#endif
#if defined(GLFW_EXPOSE_NATIVE_GLX)
#include <GL/glx.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_EGL)
#include <EGL/egl.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
#include <GL/osmesa.h>
#endif
/*************************************************************************
* Functions
*************************************************************************/
#if defined(GLFW_EXPOSE_NATIVE_WIN32)
/*! @brief Returns the adapter device name of the specified monitor.
*
* @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`)
* of the specified monitor, or `NULL` if an [error](@ref error_handling)
* occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.1.
*
* @ingroup native
*/
GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor);
/*! @brief Returns the display device name of the specified monitor.
*
* @return The UTF-8 encoded display device name (for example
* `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.1.
*
* @ingroup native
*/
GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor);
/*! @brief Returns the `HWND` of the specified window.
*
* @return The `HWND` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_WGL)
/*! @brief Returns the `HGLRC` of the specified window.
*
* @return The `HGLRC` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_COCOA)
/*! @brief Returns the `CGDirectDisplayID` of the specified monitor.
*
* @return The `CGDirectDisplayID` of the specified monitor, or
* `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.1.
*
* @ingroup native
*/
GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
/*! @brief Returns the `NSWindow` of the specified window.
*
* @return The `NSWindow` of the specified window, or `nil` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
/*! @brief Returns the `NSOpenGLContext` of the specified window.
*
* @return The `NSOpenGLContext` of the specified window, or `nil` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_X11)
/*! @brief Returns the `Display` used by GLFW.
*
* @return The `Display` used by GLFW, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI Display* glfwGetX11Display(void);
/*! @brief Returns the `RRCrtc` of the specified monitor.
*
* @return The `RRCrtc` of the specified monitor, or `None` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.1.
*
* @ingroup native
*/
GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
/*! @brief Returns the `RROutput` of the specified monitor.
*
* @return The `RROutput` of the specified monitor, or `None` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.1.
*
* @ingroup native
*/
GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
/*! @brief Returns the `Window` of the specified window.
*
* @return The `Window` of the specified window, or `None` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
/*! @brief Sets the current primary selection to the specified string.
*
* @param[in] string A UTF-8 encoded string.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @pointer_lifetime The specified string is copied before this function
* returns.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref clipboard
* @sa glfwGetX11SelectionString
* @sa glfwSetClipboardString
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI void glfwSetX11SelectionString(const char* string);
/*! @brief Returns the contents of the current primary selection as a string.
*
* If the selection is empty or if its contents cannot be converted, `NULL`
* is returned and a @ref GLFW_FORMAT_UNAVAILABLE error is generated.
*
* @return The contents of the selection as a UTF-8 encoded string, or `NULL`
* if an [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @pointer_lifetime The returned string is allocated and freed by GLFW. You
* should not free it yourself. It is valid until the next call to @ref
* glfwGetX11SelectionString or @ref glfwSetX11SelectionString, or until the
* library is terminated.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref clipboard
* @sa glfwSetX11SelectionString
* @sa glfwGetClipboardString
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI const char* glfwGetX11SelectionString(void);
#endif
#if defined(GLFW_EXPOSE_NATIVE_GLX)
/*! @brief Returns the `GLXContext` of the specified window.
*
* @return The `GLXContext` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
/*! @brief Returns the `GLXWindow` of the specified window.
*
* @return The `GLXWindow` of the specified window, or `None` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.2.
*
* @ingroup native
*/
GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
/*! @brief Returns the `struct wl_display*` used by GLFW.
*
* @return The `struct wl_display*` used by GLFW, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.2.
*
* @ingroup native
*/
GLFWAPI struct wl_display* glfwGetWaylandDisplay(void);
/*! @brief Returns the `struct wl_output*` of the specified monitor.
*
* @return The `struct wl_output*` of the specified monitor, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.2.
*
* @ingroup native
*/
GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
/*! @brief Returns the main `struct wl_surface*` of the specified window.
*
* @return The main `struct wl_surface*` of the specified window, or `NULL` if
* an [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.2.
*
* @ingroup native
*/
GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_EGL)
/*! @brief Returns the `EGLDisplay` used by GLFW.
*
* @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI EGLDisplay glfwGetEGLDisplay(void);
/*! @brief Returns the `EGLContext` of the specified window.
*
* @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
/*! @brief Returns the `EGLSurface` of the specified window.
*
* @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
/*! @brief Retrieves the color buffer associated with the specified window.
*
* @param[in] window The window whose color buffer to retrieve.
* @param[out] width Where to store the width of the color buffer, or `NULL`.
* @param[out] height Where to store the height of the color buffer, or `NULL`.
* @param[out] format Where to store the OSMesa pixel format of the color
* buffer, or `NULL`.
* @param[out] buffer Where to store the address of the color buffer, or
* `NULL`.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height, int* format, void** buffer);
/*! @brief Retrieves the depth buffer associated with the specified window.
*
* @param[in] window The window whose depth buffer to retrieve.
* @param[out] width Where to store the width of the depth buffer, or `NULL`.
* @param[out] height Where to store the height of the depth buffer, or `NULL`.
* @param[out] bytesPerValue Where to store the number of bytes per depth
* buffer element, or `NULL`.
* @param[out] buffer Where to store the address of the depth buffer, or
* `NULL`.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height, int* bytesPerValue, void** buffer);
/*! @brief Returns the `OSMesaContext` of the specified window.
*
* @return The `OSMesaContext` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* window);
#endif
#ifdef __cplusplus
}
#endif
#endif /* _glfw3_native_h_ */

315
example/src/main.c Normal file
View File

@@ -0,0 +1,315 @@
#define GLFW_INCLUDE_NONE
#include "GLFW/glfw3.h"
#include "flextGL.h"
#define SOKOL_IMPL
#define SOKOL_GLCORE33
#include "sokol_gfx.h"
#include "../../HandmadeMath.h"
// TODO: Remove this
#include <stdio.h>
typedef struct {
hmm_mat4 mvp;
hmm_vec4 color;
} uniforms_t;
typedef struct {
sg_bindings bindings;
int numVerts;
} model_t;
model_t triangle;
model_t cube;
model_t cylinder;
model_t initModel(sg_buffer vbuf, sg_buffer ibuf, size_t sizeOfIndices) {
model_t result = {
.bindings = (sg_bindings) {
.vertex_buffers[0] = vbuf,
.index_buffer = ibuf,
},
.numVerts = sizeOfIndices / sizeof(uint16_t),
};
return result;
}
#define NUM_CYLINDER_SIDES 32
void initModels() {
{
// triangle
const hmm_vec3 verts[] = {
HMM_Vec3( 0.0f, 0.5f, 0.0f), HMM_Vec3(0.0f, 0.0f, 1.0f),
HMM_Vec3( 0.5f, -0.5f, 0.0f), HMM_Vec3(0.0f, 0.0f, 1.0f),
HMM_Vec3(-0.5f, -0.5f, 0.0f), HMM_Vec3(0.0f, 0.0f, 1.0f),
};
const uint16_t indices[] = { 0, 1, 2 };
sg_buffer vbuf = sg_make_buffer(&(sg_buffer_desc){
.size = sizeof(verts),
.content = verts,
});
sg_buffer ibuf = sg_make_buffer(&(sg_buffer_desc){
.type = SG_BUFFERTYPE_INDEXBUFFER,
.size = sizeof(indices),
.content = indices,
});
triangle = initModel(vbuf, ibuf, sizeof(indices));
}
{
// cube
const hmm_vec3 verts[] = {
// front
HMM_Vec3(-0.5f, 0.5f, 0.5f), HMM_Vec3(0.0f, 0.0f, 1.0f),
HMM_Vec3(-0.5f, -0.5f, 0.5f), HMM_Vec3(0.0f, 0.0f, 1.0f),
HMM_Vec3( 0.5f, 0.5f, 0.5f), HMM_Vec3(0.0f, 0.0f, 1.0f),
HMM_Vec3( 0.5f, -0.5f, 0.5f), HMM_Vec3(0.0f, 0.0f, 1.0f),
// back
HMM_Vec3( 0.5f, 0.5f, -0.5f), HMM_Vec3(0.0f, 0.0f, -1.0f),
HMM_Vec3( 0.5f, -0.5f, -0.5f), HMM_Vec3(0.0f, 0.0f, -1.0f),
HMM_Vec3(-0.5f, 0.5f, -0.5f), HMM_Vec3(0.0f, 0.0f, -1.0f),
HMM_Vec3(-0.5f, -0.5f, -0.5f), HMM_Vec3(0.0f, 0.0f, -1.0f),
// left
HMM_Vec3(-0.5f, 0.5f, -0.5f), HMM_Vec3(-1.0f, 0.0f, 0.0f),
HMM_Vec3(-0.5f, -0.5f, -0.5f), HMM_Vec3(-1.0f, 0.0f, 0.0f),
HMM_Vec3(-0.5f, 0.5f, 0.5f), HMM_Vec3(-1.0f, 0.0f, 0.0f),
HMM_Vec3(-0.5f, -0.5f, 0.5f), HMM_Vec3(-1.0f, 0.0f, 0.0f),
// right
HMM_Vec3(0.5f, 0.5f, 0.5f), HMM_Vec3(1.0f, 0.0f, 0.0f),
HMM_Vec3(0.5f, -0.5f, 0.5f), HMM_Vec3(1.0f, 0.0f, 0.0f),
HMM_Vec3(0.5f, 0.5f, -0.5f), HMM_Vec3(1.0f, 0.0f, 0.0f),
HMM_Vec3(0.5f, -0.5f, -0.5f), HMM_Vec3(1.0f, 0.0f, 0.0f),
// top
HMM_Vec3(-0.5f, 0.5f, -0.5f), HMM_Vec3(0.0f, 1.0f, 0.0f),
HMM_Vec3(-0.5f, 0.5f, 0.5f), HMM_Vec3(0.0f, 1.0f, 0.0f),
HMM_Vec3( 0.5f, 0.5f, -0.5f), HMM_Vec3(0.0f, 1.0f, 0.0f),
HMM_Vec3( 0.5f, 0.5f, 0.5f), HMM_Vec3(0.0f, 1.0f, 0.0f),
// bottom
HMM_Vec3(-0.5f, -0.5f, 0.5f), HMM_Vec3(0.0f, -1.0f, 0.0f),
HMM_Vec3(-0.5f, -0.5f, -0.5f), HMM_Vec3(0.0f, -1.0f, 0.0f),
HMM_Vec3( 0.5f, -0.5f, 0.5f), HMM_Vec3(0.0f, -1.0f, 0.0f),
HMM_Vec3( 0.5f, -0.5f, -0.5f), HMM_Vec3(0.0f, -1.0f, 0.0f),
};
const uint16_t indices[] = {
0, 1, 2, 2, 1, 3,
4, 5, 6, 6, 5, 7,
8, 9, 10, 10, 9, 11,
12, 13, 14, 14, 13, 15,
16, 17, 18, 18, 17, 19,
20, 21, 22, 22, 21, 23,
};
sg_buffer vbuf = sg_make_buffer(&(sg_buffer_desc){
.size = sizeof(verts),
.content = verts,
});
sg_buffer ibuf = sg_make_buffer(&(sg_buffer_desc){
.type = SG_BUFFERTYPE_INDEXBUFFER,
.size = sizeof(indices),
.content = indices,
});
cube = initModel(vbuf, ibuf, sizeof(indices));
}
{
// cylinder
// the vertex order will be:
// top middle, bottom middle, top cap ring, bottom cap ring, top side ring, bottom side ring
hmm_vec3 verts[(2 * (1 + NUM_CYLINDER_SIDES) + (2 * NUM_CYLINDER_SIDES)) * 2];
verts[0] = HMM_Vec3(0.0f, 0.5f, 0.0f); verts[1] = HMM_Vec3(0.0f, 1.0f, 0.0f);
verts[2] = HMM_Vec3(0.0f, -0.5f, 0.0f); verts[3] = HMM_Vec3(0.0f, -1.0f, 0.0f);
const int baseVertIndexTopCapRing = 4; // middles are vert, normal, vert, normal
const int baseVertIndexBottomCapRing = baseVertIndexTopCapRing + (NUM_CYLINDER_SIDES * 2);
const int baseVertIndexTopSideRing = baseVertIndexBottomCapRing + (NUM_CYLINDER_SIDES * 2);
const int baseVertIndexBottomSideRing = baseVertIndexTopSideRing + (NUM_CYLINDER_SIDES * 2);
for (int i = 0; i < NUM_CYLINDER_SIDES; i++) {
float t = 2 * HMM_PI32 * (i / (float)NUM_CYLINDER_SIDES);
float x = HMM_CosF(t);
float z = HMM_SinF(t);
hmm_vec3 top = HMM_Vec3(x, 0.5f, z);
hmm_vec3 bottom = HMM_Vec3(x, -0.5f, z);
hmm_vec3 sideNormal = HMM_NormalizeVec3(HMM_Vec3(x, 0.0f, z));
verts[baseVertIndexTopCapRing + (2 * i) ] = top;
verts[baseVertIndexTopCapRing + (2 * i) + 1] = HMM_Vec3(0.0f, 1.0f, 0.0f);
verts[baseVertIndexBottomCapRing + (2 * i) ] = bottom;
verts[baseVertIndexBottomCapRing + (2 * i) + 1] = HMM_Vec3(0.0f, -1.0f, 0.0f);
verts[baseVertIndexTopSideRing + (2 * i) ] = top;
verts[baseVertIndexTopSideRing + (2 * i) + 1] = sideNormal;
verts[baseVertIndexBottomSideRing + (2 * i) ] = bottom;
verts[baseVertIndexBottomSideRing + (2 * i) + 1] = sideNormal;
}
uint16_t indices[3 * NUM_CYLINDER_SIDES + 3 * NUM_CYLINDER_SIDES + 3 * 2 * NUM_CYLINDER_SIDES];
// top cap
for (int i = 0; i < NUM_CYLINDER_SIDES; i++) {
indices[3 * i] = 0;
indices[3 * i + 1] = 2 + i;
indices[3 * i + 2] = 2 + ((i + 1) % NUM_CYLINDER_SIDES);
}
// bottom cap
const int bottomCapBaseIndex = 3 * NUM_CYLINDER_SIDES;
for (int i = 0; i < NUM_CYLINDER_SIDES; i++) {
indices[bottomCapBaseIndex + 3 * i] = 1;
indices[bottomCapBaseIndex + 3 * i + 1] = (2 + NUM_CYLINDER_SIDES) + ((i + 1) % NUM_CYLINDER_SIDES);
indices[bottomCapBaseIndex + 3 * i + 2] = (2 + NUM_CYLINDER_SIDES) + i;
}
const int sideBaseIndex = bottomCapBaseIndex + 3 * NUM_CYLINDER_SIDES;
const int topSideRingStart = 2 + NUM_CYLINDER_SIDES + NUM_CYLINDER_SIDES;
const int bottomSideRingStart = topSideRingStart + NUM_CYLINDER_SIDES;
for (int i = 0; i < NUM_CYLINDER_SIDES; i++) {
indices[sideBaseIndex + 6 * i] = topSideRingStart + i;
indices[sideBaseIndex + 6 * i + 1] = bottomSideRingStart + i;
indices[sideBaseIndex + 6 * i + 2] = topSideRingStart + ((i + 1) % NUM_CYLINDER_SIDES);
indices[sideBaseIndex + 6 * i + 3] = topSideRingStart + ((i + 1) % NUM_CYLINDER_SIDES);
indices[sideBaseIndex + 6 * i + 4] = bottomSideRingStart + i;
indices[sideBaseIndex + 6 * i + 5] = bottomSideRingStart + ((i + 1) % NUM_CYLINDER_SIDES);
}
sg_buffer vbuf = sg_make_buffer(&(sg_buffer_desc){
.size = sizeof(verts),
.content = verts,
});
sg_buffer ibuf = sg_make_buffer(&(sg_buffer_desc){
.type = SG_BUFFERTYPE_INDEXBUFFER,
.size = sizeof(indices),
.content = indices,
});
cylinder = initModel(vbuf, ibuf, sizeof(indices));
}
}
int main() {
/* create window and GL context via GLFW */
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* w = glfwCreateWindow(640, 480, "Sokol Triangle GLFW", 0, 0);
glfwMakeContextCurrent(w);
glfwSwapInterval(1);
flextInit(w);
/* setup sokol_gfx */
sg_setup(&(sg_desc){0});
initModels();
sg_layout_desc layout = {
.attrs = {
[0].format=SG_VERTEXFORMAT_FLOAT3,
[1].format=SG_VERTEXFORMAT_FLOAT3,
}
};
sg_shader shd = sg_make_shader(&(sg_shader_desc){
.vs = {
.source =
"#version 330\n"
"uniform mat4 mvp;"
"uniform vec4 color0;"
"layout(location=0) in vec4 position;\n"
"out vec4 color;\n"
"void main() {\n"
" gl_Position = mvp * position;\n"
" color = color0;\n"
"}\n",
.uniform_blocks[0] = {
.size = sizeof(uniforms_t),
.uniforms = {
[0] = { .name="mvp", .type=SG_UNIFORMTYPE_MAT4 },
[1] = { .name="color0", .type=SG_UNIFORMTYPE_FLOAT4 },
},
},
},
.fs.source =
"#version 330\n"
"in vec4 color;\n"
"out vec4 frag_color;\n"
"void main() {\n"
" frag_color = color;\n"
"}\n",
});
/* a pipeline state object (default render states are fine for triangle) */
sg_pipeline pip = sg_make_pipeline(&(sg_pipeline_desc){
.shader = shd,
.layout = layout,
.index_type = SG_INDEXTYPE_UINT16,
.depth_stencil = {
.depth_compare_func = SG_COMPAREFUNC_LESS_EQUAL,
.depth_write_enabled = true,
},
.rasterizer = (sg_rasterizer_state) {
.cull_mode = SG_CULLMODE_BACK,
.face_winding = SG_FACEWINDING_CCW,
},
});
/* default pass action (clear to grey) */
sg_pass_action pass_action = {0};
double previousTime = glfwGetTime();
/* draw loop */
while (!glfwWindowShouldClose(w)) {
double time = glfwGetTime();
double deltaTime = time - previousTime;
double previousTime = time;
int cur_width, cur_height;
glfwGetFramebufferSize(w, &cur_width, &cur_height);
sg_begin_default_pass(&pass_action, cur_width, cur_height);
for (int j = 0; j < 3; j++) {
for (int i = 0; i < 3; i++) {
model_t model = cylinder;
hmm_mat4 scale = HMM_Scale(HMM_Vec3(0.25f, 0.5f, 0.25f));
hmm_mat4 rotateZ = HMM_Rotate(HMM_PI32 * i, HMM_Vec3(0.0f, 0.0f, 1.0f));
hmm_mat4 rotateY = HMM_Rotate(HMM_PI32 / 2.0f * time, HMM_Vec3(0.0f, 1.0f, 0.0f));
hmm_mat4 rotate = HMM_MultiplyMat4(rotateY, rotateZ);
hmm_mat4 translate = HMM_Translate(HMM_Vec3(-0.5f + 0.5f * i, -0.5f + 0.5f * j, 0.0f));
hmm_mat4 m = HMM_MultiplyMat4(translate, HMM_MultiplyMat4(rotate, scale));
hmm_mat4 v = HMM_Translate(HMM_Vec3(0.0f, 0.0f, -1.0f));
hmm_mat4 p = HMM_Perspective(HMM_PI32 / 2.0f, 1.0f, 0.01f, 10.0f);
uniforms_t uniforms = {
.mvp = HMM_MultiplyMat4(p, HMM_MultiplyMat4(v, m)),
.color = HMM_Vec4((i + j) + 1 & 2, ((i + j) % 2) == 1, ((i + j) % 4) == 2, 1.0f),
};
sg_apply_pipeline(pip);
sg_apply_bindings(&model.bindings);
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, &uniforms, sizeof(uniforms));
sg_draw(0, model.numVerts, 1);
}
}
sg_end_pass();
sg_commit();
glfwSwapBuffers(w);
glfwPollEvents();
}
/* cleanup */
sg_shutdown();
glfwTerminate();
return 0;
}

11943
example/src/sokol_gfx.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,4 @@
#include "HandmadeTest.h"
#endif
#define HANDMADE_MATH_IMPLEMENTATION
#define HANDMADE_MATH_NO_INLINE
#include "../HandmadeMath.h"

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

@@ -199,32 +199,3 @@ TEST(Subtraction, Quaternion)
EXPECT_FLOAT_EQ(q1.W, -4.0f);
#endif
}
#ifdef __cplusplus
TEST(UnaryMinus, Vec2)
{
hmm_vec2 VectorOne = {1.0f, 2.0f};
hmm_vec2 Result = -VectorOne;
EXPECT_FLOAT_EQ(Result.X, -1.0f);
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
}
TEST(UnaryMinus, Vec3)
{
hmm_vec3 VectorOne = {1.0f, 2.0f, 3.0f};
hmm_vec3 Result = -VectorOne;
EXPECT_FLOAT_EQ(Result.X, -1.0f);
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
EXPECT_FLOAT_EQ(Result.Z, -3.0f);
}
TEST(UnaryMinus, Vec4)
{
hmm_vec4 VectorOne = {1.0f, 2.0f, 3.0f, 4.0f};
hmm_vec4 Result = -VectorOne;
EXPECT_FLOAT_EQ(Result.X, -1.0f);
EXPECT_FLOAT_EQ(Result.Y, -2.0f);
EXPECT_FLOAT_EQ(Result.Z, -3.0f);
EXPECT_FLOAT_EQ(Result.W, -4.0f);
}
#endif

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

View File

@@ -1,18 +0,0 @@
@echo off
if not exist "build" mkdir build
pushd build
clang-cl /Fehmm_test_c.exe ..\HandmadeMath.c ..\hmm_test.c
hmm_test_c
clang-cl /Fehmm_test_c_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.c ..\hmm_test.c
hmm_test_c_no_sse
clang-cl /Fehmm_test_cpp.exe ..\HandmadeMath.cpp ..\hmm_test.cpp
hmm_test_cpp
clang-cl /Fehmm_test_cpp_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.cpp ..\hmm_test.cpp
hmm_test_cpp_no_sse
popd

View File

@@ -1,27 +1,27 @@
@echo off
if "%1%"=="travis" (
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\Tools\VsDevCmd.bat" -host_arch=amd64 -arch=amd64
) else (
where /q cl
if ERRORLEVEL 1 (
for /f "delims=" %%a in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -find VC\Auxiliary\Build\vcvarsall.bat') do (%%a x64)
)
)
if not exist "build" mkdir build
pushd build
cl /Fehmm_test_c.exe ..\HandmadeMath.c ..\hmm_test.c
hmm_test_c
cl /Fehmm_test_c_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.c ..\hmm_test.c
hmm_test_c_no_sse
cl /Fehmm_test_cpp.exe ..\HandmadeMath.cpp ..\hmm_test.cpp
hmm_test_cpp
cl /Fehmm_test_cpp_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.cpp ..\hmm_test.cpp
hmm_test_cpp_no_sse
popd
@echo off
if "%1%"=="travis" (
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\Tools\VsDevCmd.bat" -host_arch=amd64 -arch=amd64
) else (
where /q cl
if ERRORLEVEL 1 (
for /f "delims=" %%a in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -find VC\Auxiliary\Build\vcvarsall.bat') do (%%a x64)
)
)
if not exist "build" mkdir build
pushd build
cl /Fehmm_test_c.exe ..\HandmadeMath.c ..\hmm_test.c || popd && exit /B
hmm_test_c
cl /Fehmm_test_c_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.c ..\hmm_test.c || popd && exit /B
hmm_test_c_no_sse
cl /Fehmm_test_cpp.exe ..\HandmadeMath.cpp ..\hmm_test.cpp || popd && exit /B
hmm_test_cpp
cl /Fehmm_test_cpp_no_sse.exe /DHANDMADE_MATH_NO_SSE ..\HandmadeMath.cpp ..\hmm_test.cpp || popd && exit /B
hmm_test_cpp_no_sse
popd