HLML
HLML copied to clipboard
Auto-generated maths library for C and C++ based on HLSL/Cg
HLML
(High Level Maths Library).
HLML is a maths library for C and C++ focused on games/graphics programming which is loosely styled on HLSL syntax where all vector/matrix types are generated by a tool. This means that there are zero templates in the generated code, which gives the following advantages:
- Shorter compile times.
- Easier to read and debug.
- Ability to forward declare types.
As well as the above, HLML also offers the following:
- SIMD maths functions (functionality is experimental and still potentially subject to change).
- Non-uniform matrix types.
- Boolean vectors/matrices to aid equality checking of vector types.
Currently HLML is written to produce optimised assembly for Clang. If you use another compiler then YMMV.
HLML does not override any maths functions that are a part of C99.
See the "Licenses" section below for details about what licenses HLML uses.
Installation
- Go to the releases page and download the latest version.
- Unzip the header files into your project (you can use either the C or C++ files, NOT both).
Usage
Include hlml.h
.
For more detailed documentation on how to use HLML's experimental SSE functionality, please refer to the SSE document.
Code Examples
C:
Adding 2 vectors:
float3 a = { 1.0f, 2.0f, 3.0f };
float3 b = { 4.0f, 5.0f, 6.0f };
// the "c" part means "component-wise"
// the "v" part means vector
// there are also component-wise arithmetic functions for scalar ("s"), and matrix ("m" - for matrix types only)
float3 c = float3_caddv( &a, &b );
printf( "c is: (%f, %f, %f)", c.x, c.y, c.z );
Creating a Model-View-Projection matrix:
float4x4 model = float4x4_translate( &player_transform, &position );
float4x4 view = float4x4_lookat_lh_zo( &eye, &forward, &world_up );
float4x4 projection = float4x4_perspective_lh_zo( fov, aspect, znear, zfar );
// "float4_mulm" will do matrix multiplication
// "float4_cmulm" will do component-wise multiplication
float4x4 view_projection = float4x4_mulm( &view, &projection );
float4x4 mvp = float4x4_mulm( &model, &view_projection );
C++:
Adding 2 vectors:
float3 a = { 1.0f, 2.0f, 3.0f }; // in C++ you can initialise math types like this
float3 b = float3( 4.0f, 5.0f, 6.0f ); // or like this
float3 c = a + b;
printf( "c is: (%f, %f, %f)", c.x, c.y, c.z );
Creating a Model-View-Projection matrix:
float4x4 model = translate( player_transform, position );
// lh = left handed, zo = zero-to-one depth
// there also exists rh (right-handed) and no (negative-one-to-one) combinations
float4x4 view = lookat_lh_zo( eye, forward, world_up );
float4x4 projection = perspective_lh_zo( fov, aspect, znear, zfar );
// in C++ the multiply operator performs matrix multiplication
// not per-component multiplication
float4x4 view_projection = mul( view, projection );
float4x4 mvp = mul( model, view_projection );
Vector Swizzling (C++ only):
// all possible combinations are automatically generated and available
float4 a = { 1.0f, 2.0f, 3.0f, 4.0f };
float4 b = a.xxyy();
Common Pitfalls
READ THIS BEFORE USING HLML:
- Matrix types are row-major, so a
float3x4
is a matrix that holds 3float4
s (or, in other words: afloat4
array of size 3). - In C++ vector types are a union of
struct
/fixed-size array. - To avoid conflicts with Windows
min
/max
macros, you can#define NOMINMAX
before including HLML.
Contributing
If this is a project you'd like to contribute to then see the contribution document.
Credits
I'd like to extend credit to the following:
- GLM - I use some of their solutions for a couple of functions, therefore I take no credit for those.
- Unity.Mathematics - The idea of using a generator comes from this.
Contributors/Bug finders:
- @xwize
- David Smith @Flave229
I'd also just like to give a special thanks to the following people:
- Antony Bowler
- Mike Young
- Tom Whitcombe
Your help is very much appreciated. Thank you. =)
Motivation
I've always primarily used GLM as my maths library of choice, but there were a few things that always bugged me about it:
- Sometimes had trouble reading past all of the templates.
- Often have trouble debugging the templates.
- Typing the namespace all the time got annoying.
- Often found it frustrating to navigate the API files as everything is split into lots of little separate headers that weren't obviously named (IMO).
(This isn't an attack on GLM, just some of my personal gripes with it).
One day I stumbled upon the Unity.Mathematics library where I saw that all the maths types were being generated via a tool. I decided to try the same but for C and C++: Write a tool that generated maths types for me to see if there were any benefits of doing it that way, and I found that there were:
- Compile times were shorter due to lack of templates.
- Being able to just read plain, vanilla C/C++ code. No templates to read past, just very simple, minimal, and straightforward code.
- Maintaining changes across multiple (if not all) types was a lot easier than imagined. Write the changes into the generator and watch it reflect the change across all the desired generated types automatically.
Licenses
HLML is dual licensed.
All code that is part of the generator is licensed under GNU GPL v3.
All of the generated code (found in the releases) are licensed under MIT license. Please see the respective license files (found in the root of this project) for details.
HLML's generator also makes use of the following libraries, which are under their own respective licenses:
- Temper - MIT
- stb_sprintf - MIT/Public Domain