From 3d8e0b2840b487199ba61addbcb054cafb3a08ef Mon Sep 17 00:00:00 2001 From: matthew Date: Sun, 3 Aug 2025 12:56:33 +1000 Subject: [PATCH] wip before restructure --- assets/shaders/gradient.comp.spv | Bin 3944 -> 3944 bytes assets/shaders/gui.frag.spv | Bin 2716 -> 2716 bytes assets/shaders/gui.vert.spv | Bin 5204 -> 5204 bytes assets/shaders/pbr.frag.spv | Bin 5072 -> 5072 bytes assets/shaders/pbr.vert.spv | Bin 4184 -> 4184 bytes assets/shaders/triangle.frag.spv | Bin 2664 -> 2664 bytes assets/shaders/triangle.vert.spv | Bin 3556 -> 3556 bytes external/cglm/aabb2d.h | 270 ++++ external/cglm/affine-mat.h | 189 +++ external/cglm/affine-post.h | 247 +++ external/cglm/affine-pre.h | 304 ++++ external/cglm/affine.h | 238 +++ external/cglm/affine2d-post.h | 132 ++ external/cglm/affine2d.h | 268 ++++ external/cglm/applesimd.h | 136 ++ external/cglm/bezier.h | 154 ++ external/cglm/box.h | 281 ++++ external/cglm/call.h | 51 + external/cglm/call/aabb2d.h | 89 ++ external/cglm/call/affine.h | 167 ++ external/cglm/call/affine2d.h | 67 + external/cglm/call/bezier.h | 31 + external/cglm/call/box.h | 78 + external/cglm/call/cam.h | 133 ++ external/cglm/call/clipspace/ortho_lh_no.h | 46 + external/cglm/call/clipspace/ortho_lh_zo.h | 46 + external/cglm/call/clipspace/ortho_rh_no.h | 46 + external/cglm/call/clipspace/ortho_rh_zo.h | 46 + external/cglm/call/clipspace/persp_lh_no.h | 87 ++ external/cglm/call/clipspace/persp_lh_zo.h | 87 ++ external/cglm/call/clipspace/persp_rh_no.h | 87 ++ external/cglm/call/clipspace/persp_rh_zo.h | 87 ++ external/cglm/call/clipspace/project_no.h | 31 + external/cglm/call/clipspace/project_zo.h | 31 + external/cglm/call/clipspace/view_lh_no.h | 31 + external/cglm/call/clipspace/view_lh_zo.h | 31 + external/cglm/call/clipspace/view_rh_no.h | 31 + external/cglm/call/clipspace/view_rh_zo.h | 31 + external/cglm/call/curve.h | 23 + external/cglm/call/ease.h | 143 ++ external/cglm/call/euler.h | 80 + external/cglm/call/frustum.h | 41 + external/cglm/call/io.h | 45 + external/cglm/call/ivec2.h | 179 +++ external/cglm/call/ivec3.h | 183 +++ external/cglm/call/ivec4.h | 147 ++ external/cglm/call/mat2.h | 83 + external/cglm/call/mat2x3.h | 47 + external/cglm/call/mat2x4.h | 47 + external/cglm/call/mat3.h | 94 ++ external/cglm/call/mat3x2.h | 47 + external/cglm/call/mat3x4.h | 47 + external/cglm/call/mat4.h | 135 ++ external/cglm/call/mat4x2.h | 47 + external/cglm/call/mat4x3.h | 47 + external/cglm/call/noise.h | 31 + external/cglm/call/plane.h | 23 + external/cglm/call/project.h | 39 + external/cglm/call/quat.h | 175 +++ external/cglm/call/ray.h | 39 + external/cglm/call/sphere.h | 39 + external/cglm/call/vec2.h | 251 +++ external/cglm/call/vec3.h | 369 +++++ external/cglm/call/vec4.h | 342 +++++ external/cglm/cam.h | 582 +++++++ external/cglm/cglm.h | 48 + external/cglm/clipspace/ortho_lh_no.h | 183 +++ external/cglm/clipspace/ortho_lh_zo.h | 177 +++ external/cglm/clipspace/ortho_rh_no.h | 183 +++ external/cglm/clipspace/ortho_rh_zo.h | 181 +++ external/cglm/clipspace/persp.h | 48 + external/cglm/clipspace/persp_lh_no.h | 395 +++++ external/cglm/clipspace/persp_lh_zo.h | 387 +++++ external/cglm/clipspace/persp_rh_no.h | 395 +++++ external/cglm/clipspace/persp_rh_zo.h | 389 +++++ external/cglm/clipspace/project_no.h | 109 ++ external/cglm/clipspace/project_zo.h | 111 ++ external/cglm/clipspace/view_lh.h | 99 ++ external/cglm/clipspace/view_lh_no.h | 74 + external/cglm/clipspace/view_lh_zo.h | 74 + external/cglm/clipspace/view_rh.h | 99 ++ external/cglm/clipspace/view_rh_no.h | 74 + external/cglm/clipspace/view_rh_zo.h | 74 + external/cglm/color.h | 26 + external/cglm/common.h | 130 ++ external/cglm/curve.h | 40 + external/cglm/ease.h | 317 ++++ external/cglm/euler.h | 601 ++++++++ external/cglm/frustum.h | 255 ++++ external/cglm/handed/euler_to_quat_lh.h | 167 ++ external/cglm/handed/euler_to_quat_rh.h | 170 +++ external/cglm/io.h | 440 ++++++ external/cglm/ivec2.h | 659 ++++++++ external/cglm/ivec3.h | 713 +++++++++ external/cglm/ivec4.h | 608 ++++++++ external/cglm/mat2.h | 363 +++++ external/cglm/mat2x3.h | 154 ++ external/cglm/mat2x4.h | 168 ++ external/cglm/mat3.h | 480 ++++++ external/cglm/mat3x2.h | 148 ++ external/cglm/mat3x4.h | 177 +++ external/cglm/mat4.h | 831 ++++++++++ external/cglm/mat4x2.h | 153 ++ external/cglm/mat4x3.h | 168 ++ external/cglm/noise.h | 734 +++++++++ external/cglm/plane.h | 44 + external/cglm/project.h | 172 +++ external/cglm/quat.h | 949 ++++++++++++ external/cglm/ray.h | 174 +++ external/cglm/simd/arm.h | 206 +++ external/cglm/simd/avx/affine.h | 66 + external/cglm/simd/avx/mat4.h | 115 ++ external/cglm/simd/intrin.h | 153 ++ external/cglm/simd/neon/affine.h | 121 ++ external/cglm/simd/neon/mat2.h | 44 + external/cglm/simd/neon/mat4.h | 468 ++++++ external/cglm/simd/neon/quat.h | 57 + external/cglm/simd/sse2/affine.h | 115 ++ external/cglm/simd/sse2/mat2.h | 48 + external/cglm/simd/sse2/mat3.h | 76 + external/cglm/simd/sse2/mat4.h | 573 +++++++ external/cglm/simd/sse2/quat.h | 54 + external/cglm/simd/wasm.h | 198 +++ external/cglm/simd/wasm/affine.h | 127 ++ external/cglm/simd/wasm/mat2.h | 50 + external/cglm/simd/wasm/mat3.h | 85 ++ external/cglm/simd/wasm/mat4.h | 454 ++++++ external/cglm/simd/wasm/quat.h | 55 + external/cglm/simd/x86.h | 365 +++++ external/cglm/sphere.h | 99 ++ external/cglm/struct.h | 50 + external/cglm/struct/aabb2d.h | 253 ++++ external/cglm/struct/affine-mat.h | 90 ++ external/cglm/struct/affine-post.h | 184 +++ external/cglm/struct/affine-pre.h | 184 +++ external/cglm/struct/affine.h | 201 +++ external/cglm/struct/affine2d.h | 177 +++ external/cglm/struct/box.h | 259 ++++ external/cglm/struct/cam.h | 646 ++++++++ external/cglm/struct/clipspace/ortho_lh_no.h | 154 ++ external/cglm/struct/clipspace/ortho_lh_zo.h | 154 ++ external/cglm/struct/clipspace/ortho_rh_no.h | 154 ++ external/cglm/struct/clipspace/ortho_rh_zo.h | 154 ++ external/cglm/struct/clipspace/persp_lh_no.h | 312 ++++ external/cglm/struct/clipspace/persp_lh_zo.h | 312 ++++ external/cglm/struct/clipspace/persp_rh_no.h | 312 ++++ external/cglm/struct/clipspace/persp_rh_zo.h | 312 ++++ external/cglm/struct/clipspace/project_no.h | 98 ++ external/cglm/struct/clipspace/project_zo.h | 98 ++ external/cglm/struct/clipspace/view_lh_no.h | 89 ++ external/cglm/struct/clipspace/view_lh_zo.h | 89 ++ external/cglm/struct/clipspace/view_rh_no.h | 89 ++ external/cglm/struct/clipspace/view_rh_zo.h | 89 ++ external/cglm/struct/color.h | 27 + external/cglm/struct/curve.h | 40 + external/cglm/struct/euler.h | 249 +++ external/cglm/struct/frustum.h | 155 ++ .../cglm/struct/handed/euler_to_quat_lh.h | 115 ++ .../cglm/struct/handed/euler_to_quat_rh.h | 115 ++ external/cglm/struct/io.h | 107 ++ external/cglm/struct/ivec2.h | 708 +++++++++ external/cglm/struct/ivec3.h | 725 +++++++++ external/cglm/struct/ivec4.h | 588 +++++++ external/cglm/struct/mat2.h | 274 ++++ external/cglm/struct/mat2x3.h | 125 ++ external/cglm/struct/mat2x4.h | 125 ++ external/cglm/struct/mat3.h | 322 ++++ external/cglm/struct/mat3x2.h | 125 ++ external/cglm/struct/mat3x4.h | 125 ++ external/cglm/struct/mat4.h | 496 ++++++ external/cglm/struct/mat4x2.h | 126 ++ external/cglm/struct/mat4x3.h | 125 ++ external/cglm/struct/noise.h | 57 + external/cglm/struct/plane.h | 40 + external/cglm/struct/project.h | 162 ++ external/cglm/struct/quat.h | 601 ++++++++ external/cglm/struct/ray.h | 86 ++ external/cglm/struct/sphere.h | 93 ++ external/cglm/struct/vec2-ext.h | 337 +++++ external/cglm/struct/vec2.h | 747 +++++++++ external/cglm/struct/vec3-ext.h | 325 ++++ external/cglm/struct/vec3.h | 1132 ++++++++++++++ external/cglm/struct/vec4-ext.h | 325 ++++ external/cglm/struct/vec4.h | 961 ++++++++++++ external/cglm/types-struct.h | 303 ++++ external/cglm/types.h | 144 ++ external/cglm/util.h | 375 +++++ external/cglm/vec2-ext.h | 337 +++++ external/cglm/vec2.h | 798 ++++++++++ external/cglm/vec3-ext.h | 345 +++++ external/cglm/vec3.h | 1264 ++++++++++++++++ external/cglm/vec4-ext.h | 400 +++++ external/cglm/vec4.h | 1348 +++++++++++++++++ external/cglm/version.h | 15 + src/gears/game.d | 151 +- src/gears/platform.d | 43 +- src/gears/renderer.d | 12 +- src/gears/vulkan.d | 4 +- src/shaders/structures.layout | 2 +- src/shared/includes.c | 3 + src/shared/math.d | 753 +++++++-- 201 files changed, 42419 insertions(+), 224 deletions(-) create mode 100644 external/cglm/aabb2d.h create mode 100644 external/cglm/affine-mat.h create mode 100644 external/cglm/affine-post.h create mode 100644 external/cglm/affine-pre.h create mode 100644 external/cglm/affine.h create mode 100644 external/cglm/affine2d-post.h create mode 100644 external/cglm/affine2d.h create mode 100644 external/cglm/applesimd.h create mode 100644 external/cglm/bezier.h create mode 100644 external/cglm/box.h create mode 100644 external/cglm/call.h create mode 100644 external/cglm/call/aabb2d.h create mode 100644 external/cglm/call/affine.h create mode 100644 external/cglm/call/affine2d.h create mode 100644 external/cglm/call/bezier.h create mode 100644 external/cglm/call/box.h create mode 100644 external/cglm/call/cam.h create mode 100644 external/cglm/call/clipspace/ortho_lh_no.h create mode 100644 external/cglm/call/clipspace/ortho_lh_zo.h create mode 100644 external/cglm/call/clipspace/ortho_rh_no.h create mode 100644 external/cglm/call/clipspace/ortho_rh_zo.h create mode 100644 external/cglm/call/clipspace/persp_lh_no.h create mode 100644 external/cglm/call/clipspace/persp_lh_zo.h create mode 100644 external/cglm/call/clipspace/persp_rh_no.h create mode 100644 external/cglm/call/clipspace/persp_rh_zo.h create mode 100644 external/cglm/call/clipspace/project_no.h create mode 100644 external/cglm/call/clipspace/project_zo.h create mode 100644 external/cglm/call/clipspace/view_lh_no.h create mode 100644 external/cglm/call/clipspace/view_lh_zo.h create mode 100644 external/cglm/call/clipspace/view_rh_no.h create mode 100644 external/cglm/call/clipspace/view_rh_zo.h create mode 100644 external/cglm/call/curve.h create mode 100644 external/cglm/call/ease.h create mode 100644 external/cglm/call/euler.h create mode 100644 external/cglm/call/frustum.h create mode 100644 external/cglm/call/io.h create mode 100644 external/cglm/call/ivec2.h create mode 100644 external/cglm/call/ivec3.h create mode 100644 external/cglm/call/ivec4.h create mode 100644 external/cglm/call/mat2.h create mode 100644 external/cglm/call/mat2x3.h create mode 100644 external/cglm/call/mat2x4.h create mode 100644 external/cglm/call/mat3.h create mode 100644 external/cglm/call/mat3x2.h create mode 100644 external/cglm/call/mat3x4.h create mode 100644 external/cglm/call/mat4.h create mode 100644 external/cglm/call/mat4x2.h create mode 100644 external/cglm/call/mat4x3.h create mode 100644 external/cglm/call/noise.h create mode 100644 external/cglm/call/plane.h create mode 100644 external/cglm/call/project.h create mode 100644 external/cglm/call/quat.h create mode 100644 external/cglm/call/ray.h create mode 100644 external/cglm/call/sphere.h create mode 100644 external/cglm/call/vec2.h create mode 100644 external/cglm/call/vec3.h create mode 100644 external/cglm/call/vec4.h create mode 100644 external/cglm/cam.h create mode 100644 external/cglm/cglm.h create mode 100644 external/cglm/clipspace/ortho_lh_no.h create mode 100644 external/cglm/clipspace/ortho_lh_zo.h create mode 100644 external/cglm/clipspace/ortho_rh_no.h create mode 100644 external/cglm/clipspace/ortho_rh_zo.h create mode 100644 external/cglm/clipspace/persp.h create mode 100644 external/cglm/clipspace/persp_lh_no.h create mode 100644 external/cglm/clipspace/persp_lh_zo.h create mode 100644 external/cglm/clipspace/persp_rh_no.h create mode 100644 external/cglm/clipspace/persp_rh_zo.h create mode 100644 external/cglm/clipspace/project_no.h create mode 100644 external/cglm/clipspace/project_zo.h create mode 100644 external/cglm/clipspace/view_lh.h create mode 100644 external/cglm/clipspace/view_lh_no.h create mode 100644 external/cglm/clipspace/view_lh_zo.h create mode 100644 external/cglm/clipspace/view_rh.h create mode 100644 external/cglm/clipspace/view_rh_no.h create mode 100644 external/cglm/clipspace/view_rh_zo.h create mode 100644 external/cglm/color.h create mode 100644 external/cglm/common.h create mode 100644 external/cglm/curve.h create mode 100644 external/cglm/ease.h create mode 100644 external/cglm/euler.h create mode 100644 external/cglm/frustum.h create mode 100644 external/cglm/handed/euler_to_quat_lh.h create mode 100644 external/cglm/handed/euler_to_quat_rh.h create mode 100644 external/cglm/io.h create mode 100644 external/cglm/ivec2.h create mode 100644 external/cglm/ivec3.h create mode 100644 external/cglm/ivec4.h create mode 100644 external/cglm/mat2.h create mode 100644 external/cglm/mat2x3.h create mode 100644 external/cglm/mat2x4.h create mode 100644 external/cglm/mat3.h create mode 100644 external/cglm/mat3x2.h create mode 100644 external/cglm/mat3x4.h create mode 100644 external/cglm/mat4.h create mode 100644 external/cglm/mat4x2.h create mode 100644 external/cglm/mat4x3.h create mode 100644 external/cglm/noise.h create mode 100644 external/cglm/plane.h create mode 100644 external/cglm/project.h create mode 100644 external/cglm/quat.h create mode 100644 external/cglm/ray.h create mode 100644 external/cglm/simd/arm.h create mode 100644 external/cglm/simd/avx/affine.h create mode 100644 external/cglm/simd/avx/mat4.h create mode 100644 external/cglm/simd/intrin.h create mode 100644 external/cglm/simd/neon/affine.h create mode 100644 external/cglm/simd/neon/mat2.h create mode 100644 external/cglm/simd/neon/mat4.h create mode 100644 external/cglm/simd/neon/quat.h create mode 100644 external/cglm/simd/sse2/affine.h create mode 100644 external/cglm/simd/sse2/mat2.h create mode 100644 external/cglm/simd/sse2/mat3.h create mode 100644 external/cglm/simd/sse2/mat4.h create mode 100644 external/cglm/simd/sse2/quat.h create mode 100644 external/cglm/simd/wasm.h create mode 100644 external/cglm/simd/wasm/affine.h create mode 100644 external/cglm/simd/wasm/mat2.h create mode 100644 external/cglm/simd/wasm/mat3.h create mode 100644 external/cglm/simd/wasm/mat4.h create mode 100644 external/cglm/simd/wasm/quat.h create mode 100644 external/cglm/simd/x86.h create mode 100644 external/cglm/sphere.h create mode 100644 external/cglm/struct.h create mode 100644 external/cglm/struct/aabb2d.h create mode 100644 external/cglm/struct/affine-mat.h create mode 100644 external/cglm/struct/affine-post.h create mode 100644 external/cglm/struct/affine-pre.h create mode 100644 external/cglm/struct/affine.h create mode 100644 external/cglm/struct/affine2d.h create mode 100644 external/cglm/struct/box.h create mode 100644 external/cglm/struct/cam.h create mode 100644 external/cglm/struct/clipspace/ortho_lh_no.h create mode 100644 external/cglm/struct/clipspace/ortho_lh_zo.h create mode 100644 external/cglm/struct/clipspace/ortho_rh_no.h create mode 100644 external/cglm/struct/clipspace/ortho_rh_zo.h create mode 100644 external/cglm/struct/clipspace/persp_lh_no.h create mode 100644 external/cglm/struct/clipspace/persp_lh_zo.h create mode 100644 external/cglm/struct/clipspace/persp_rh_no.h create mode 100644 external/cglm/struct/clipspace/persp_rh_zo.h create mode 100644 external/cglm/struct/clipspace/project_no.h create mode 100644 external/cglm/struct/clipspace/project_zo.h create mode 100644 external/cglm/struct/clipspace/view_lh_no.h create mode 100644 external/cglm/struct/clipspace/view_lh_zo.h create mode 100644 external/cglm/struct/clipspace/view_rh_no.h create mode 100644 external/cglm/struct/clipspace/view_rh_zo.h create mode 100644 external/cglm/struct/color.h create mode 100644 external/cglm/struct/curve.h create mode 100644 external/cglm/struct/euler.h create mode 100644 external/cglm/struct/frustum.h create mode 100644 external/cglm/struct/handed/euler_to_quat_lh.h create mode 100644 external/cglm/struct/handed/euler_to_quat_rh.h create mode 100644 external/cglm/struct/io.h create mode 100644 external/cglm/struct/ivec2.h create mode 100644 external/cglm/struct/ivec3.h create mode 100644 external/cglm/struct/ivec4.h create mode 100644 external/cglm/struct/mat2.h create mode 100644 external/cglm/struct/mat2x3.h create mode 100644 external/cglm/struct/mat2x4.h create mode 100644 external/cglm/struct/mat3.h create mode 100644 external/cglm/struct/mat3x2.h create mode 100644 external/cglm/struct/mat3x4.h create mode 100644 external/cglm/struct/mat4.h create mode 100644 external/cglm/struct/mat4x2.h create mode 100644 external/cglm/struct/mat4x3.h create mode 100644 external/cglm/struct/noise.h create mode 100644 external/cglm/struct/plane.h create mode 100644 external/cglm/struct/project.h create mode 100644 external/cglm/struct/quat.h create mode 100644 external/cglm/struct/ray.h create mode 100644 external/cglm/struct/sphere.h create mode 100644 external/cglm/struct/vec2-ext.h create mode 100644 external/cglm/struct/vec2.h create mode 100644 external/cglm/struct/vec3-ext.h create mode 100644 external/cglm/struct/vec3.h create mode 100644 external/cglm/struct/vec4-ext.h create mode 100644 external/cglm/struct/vec4.h create mode 100644 external/cglm/types-struct.h create mode 100644 external/cglm/types.h create mode 100644 external/cglm/util.h create mode 100644 external/cglm/vec2-ext.h create mode 100644 external/cglm/vec2.h create mode 100644 external/cglm/vec3-ext.h create mode 100644 external/cglm/vec3.h create mode 100644 external/cglm/vec4-ext.h create mode 100644 external/cglm/vec4.h create mode 100644 external/cglm/version.h diff --git a/assets/shaders/gradient.comp.spv b/assets/shaders/gradient.comp.spv index a2239d5f187bb68c252dc0fd5e84a27be6dd62a7..1d9f82ad8972914e6c0d7d1dc314cf75a9745e31 100644 GIT binary patch delta 28 jcmaDM_d;&N14jOWqWrAXm87p}Kx5*4G delta 28 jcmaDM_d;&N14jO`%+&Juf};Ga)Z~)P{JhQY87p}Kx7!RY diff --git a/assets/shaders/gui.frag.spv b/assets/shaders/gui.frag.spv index bcbfac2dbc9f07bfcf4fb2a5fe5c17b0a42fb10e..c490d3e99eb0f4369a15a4862af525fbe7ac5d25 100644 GIT binary patch delta 28 kcmbOuI!AQF3`YKfqWrAXC8NYG>0G~(;Y5)KL delta 28 kcmbOuI!AQF3`YL4%+&Juf};Ga)Z~)P{JhP}8NYG>0H0b5Y5)KL diff --git a/assets/shaders/gui.vert.spv b/assets/shaders/gui.vert.spv index 45d2b37ad679ae43556df10f7f7eb7df72b1bb90..39374c1405cbd22681e6dd463845e5572179ff2d 100644 GIT binary patch delta 28 jcmcbjaYbXp2`2u6qWrAXOnQ8?Avo;I! delta 28 jcmcbjaYbXp2`2us%+&Juf};Ga)Z~)P{JhQAnQ8?Avq%f` diff --git a/assets/shaders/pbr.frag.spv b/assets/shaders/pbr.frag.spv index 049dc697655f2568fade810078bcdab137bfeac2..5d4e833c4305f35976feaac2a4c802cefee14e23 100644 GIT binary patch delta 28 jcmcbhenEYM4HJJsQGQlxa!F=>UVK?*YWZewrdB}!qjn0} delta 28 jcmcbhenEYM4HJJ^W@>qSK~a8IYH~?te%@wprdB}!qlgOG diff --git a/assets/shaders/pbr.vert.spv b/assets/shaders/pbr.vert.spv index fd390a894e9a58a9c51c12f95854fc81668ac0a8..c369eaafc8d000777bcff731898c856ae93aaca9 100644 GIT binary patch delta 28 jcmcbia6@5(2orxnQGQlxa!F=>UVK?*YWZemCR08Dp5F>M delta 28 jcmcbia6@5(2orxqSK~a8IYH~?te%@wfCR08Dp79De diff --git a/assets/shaders/triangle.frag.spv b/assets/shaders/triangle.frag.spv index 7c6c2436b8a7bfbcc330716943d278513807f405..1dd2a8e5d78f2a89cb35502f4e1a5506d479a55b 100644 GIT binary patch delta 28 jcmaDM@UVK?*YWe2bjAuCjt%wW2 delta 28 jcmaDM@qSK~a8IYH~?te%|KUjAuCjt(ptK diff --git a/assets/shaders/triangle.vert.spv b/assets/shaders/triangle.vert.spv index bdd93bf9ba7c6b8e793649e9bc2ff7d2483be9b2..97265db928df52d799554304202c2a8925902d31 100644 GIT binary patch delta 28 jcmaDN{X}|$3lo1qQGQlxa!F=>UVK?*YWe11rit7DrYH*k delta 28 jcmaDN{X}|$3lo1?W@>qSK~a8IYH~?te%|I_rit7DraB7$ diff --git a/external/cglm/aabb2d.h b/external/cglm/aabb2d.h new file mode 100644 index 0000000..6369d08 --- /dev/null +++ b/external/cglm/aabb2d.h @@ -0,0 +1,270 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_aabb2d_h +#define cglm_aabb2d_h + +#include "common.h" +#include "vec2.h" +#include "util.h" + +/* DEPRECATED! use _diag */ +#define glm_aabb2d_size(aabb) glm_aabb2d_diag(aabb) + +/*! + * @brief make [aabb] zero + * + * @param[in, out] aabb aabb + */ +CGLM_INLINE +void +glm_aabb2d_zero(vec2 aabb[2]) { + glm_vec2_zero(aabb[0]); + glm_vec2_zero(aabb[1]); +} + +/*! + * @brief copy all members of [aabb] to [dest] + * + * @param[in] aabb source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_aabb2d_copy(vec2 aabb[2], vec2 dest[2]) { + glm_vec2_copy(aabb[0], dest[0]); + glm_vec2_copy(aabb[1], dest[1]); +} + +/*! + * @brief apply transform to Axis-Aligned Bounding aabb + * + * @param[in] aabb bounding aabb + * @param[in] m transform matrix + * @param[out] dest transformed bounding aabb + */ +CGLM_INLINE +void +glm_aabb2d_transform(vec2 aabb[2], mat3 m, vec2 dest[2]) { + vec2 v[2], xa, xb, ya, yb; + + glm_vec2_scale(m[0], aabb[0][0], xa); + glm_vec2_scale(m[0], aabb[1][0], xb); + + glm_vec2_scale(m[1], aabb[0][1], ya); + glm_vec2_scale(m[1], aabb[1][1], yb); + + /* translation + min(xa, xb) + min(ya, yb) */ + glm_vec2(m[2], v[0]); + glm_vec2_minadd(xa, xb, v[0]); + glm_vec2_minadd(ya, yb, v[0]); + + /* translation + max(xa, xb) + max(ya, yb) */ + glm_vec2(m[2], v[1]); + glm_vec2_maxadd(xa, xb, v[1]); + glm_vec2_maxadd(ya, yb, v[1]); + + glm_vec2_copy(v[0], dest[0]); + glm_vec2_copy(v[1], dest[1]); +} + +/*! + * @brief merges two AABB bounding aabb and creates new one + * + * two aabb must be in same space, if one of aabb is in different space then + * you should consider to convert it's space by glm_aabb_space + * + * @param[in] aabb1 bounding aabb 1 + * @param[in] aabb2 bounding aabb 2 + * @param[out] dest merged bounding aabb + */ +CGLM_INLINE +void +glm_aabb2d_merge(vec2 aabb1[2], vec2 aabb2[2], vec2 dest[2]) { + dest[0][0] = glm_min(aabb1[0][0], aabb2[0][0]); + dest[0][1] = glm_min(aabb1[0][1], aabb2[0][1]); + + dest[1][0] = glm_max(aabb1[1][0], aabb2[1][0]); + dest[1][1] = glm_max(aabb1[1][1], aabb2[1][1]); +} + +/*! + * @brief crops a bounding aabb with another one. + * + * this could be useful for getting a baabb which fits with view frustum and + * object bounding aabbes. In this case you crop view frustum aabb with objects + * aabb + * + * @param[in] aabb bounding aabb 1 + * @param[in] cropAabb crop aabb + * @param[out] dest cropped bounding aabb + */ +CGLM_INLINE +void +glm_aabb2d_crop(vec2 aabb[2], vec2 cropAabb[2], vec2 dest[2]) { + dest[0][0] = glm_max(aabb[0][0], cropAabb[0][0]); + dest[0][1] = glm_max(aabb[0][1], cropAabb[0][1]); + + dest[1][0] = glm_min(aabb[1][0], cropAabb[1][0]); + dest[1][1] = glm_min(aabb[1][1], cropAabb[1][1]); +} + +/*! + * @brief crops a bounding aabb with another one. + * + * this could be useful for getting a baabb which fits with view frustum and + * object bounding aabbes. In this case you crop view frustum aabb with objects + * aabb + * + * @param[in] aabb bounding aabb + * @param[in] cropAabb crop aabb + * @param[in] clampAabb minimum aabb + * @param[out] dest cropped bounding aabb + */ +CGLM_INLINE +void +glm_aabb2d_crop_until(vec2 aabb[2], + vec2 cropAabb[2], + vec2 clampAabb[2], + vec2 dest[2]) { + glm_aabb2d_crop(aabb, cropAabb, dest); + glm_aabb2d_merge(clampAabb, dest, dest); +} + +/*! + * @brief invalidate AABB min and max values + * + * @param[in, out] aabb bounding aabb + */ +CGLM_INLINE +void +glm_aabb2d_invalidate(vec2 aabb[2]) { + glm_vec2_fill(aabb[0], FLT_MAX); + glm_vec2_fill(aabb[1], -FLT_MAX); +} + +/*! + * @brief check if AABB is valid or not + * + * @param[in] aabb bounding aabb + */ +CGLM_INLINE +bool +glm_aabb2d_isvalid(vec2 aabb[2]) { + return glm_vec2_max(aabb[0]) != FLT_MAX + && glm_vec2_min(aabb[1]) != -FLT_MAX; +} + +/*! + * @brief distance between of min and max + * + * @param[in] aabb bounding aabb + */ +CGLM_INLINE +float +glm_aabb2d_diag(vec2 aabb[2]) { + return glm_vec2_distance(aabb[0], aabb[1]); +} + +/*! + * @brief size of aabb + * + * @param[in] aabb bounding aabb + * @param[out] dest size + */ +CGLM_INLINE +void +glm_aabb2d_sizev(vec2 aabb[2], vec2 dest) { + glm_vec2_sub(aabb[1], aabb[0], dest); +} + +/*! + * @brief radius of sphere which surrounds AABB + * + * @param[in] aabb bounding aabb + */ +CGLM_INLINE +float +glm_aabb2d_radius(vec2 aabb[2]) { + return glm_aabb2d_diag(aabb) * 0.5f; +} + +/*! + * @brief computes center point of AABB + * + * @param[in] aabb bounding aabb + * @param[out] dest center of bounding aabb + */ +CGLM_INLINE +void +glm_aabb2d_center(vec2 aabb[2], vec2 dest) { + glm_vec2_center(aabb[0], aabb[1], dest); +} + +/*! + * @brief check if two AABB intersects + * + * @param[in] aabb bounding aabb + * @param[in] other other bounding aabb + */ +CGLM_INLINE +bool +glm_aabb2d_aabb(vec2 aabb[2], vec2 other[2]) { + return (aabb[0][0] <= other[1][0] && aabb[1][0] >= other[0][0]) + && (aabb[0][1] <= other[1][1] && aabb[1][1] >= other[0][1]); +} + +/*! + * @brief check if AABB intersects with a circle + * + * Circle Representation in cglm: [center.x, center.y, radii] + * + * @param[in] aabb solid bounding aabb + * @param[in] c solid circle + */ +CGLM_INLINE +bool +glm_aabb2d_circle(vec2 aabb[2], vec3 c) { + float dmin; + int a, b; + + a = (c[0] < aabb[0][0]) + (c[0] > aabb[1][0]); + b = (c[1] < aabb[0][1]) + (c[1] > aabb[1][1]); + + dmin = glm_pow2((c[0] - aabb[!(a - 1)][0]) * (a != 0)) + + glm_pow2((c[1] - aabb[!(b - 1)][1]) * (b != 0)); + + return dmin <= glm_pow2(c[2]); +} + +/*! + * @brief check if point is inside of AABB + * + * @param[in] aabb bounding aabb + * @param[in] point point + */ +CGLM_INLINE +bool +glm_aabb2d_point(vec2 aabb[2], vec2 point) { + return (point[0] >= aabb[0][0] && point[0] <= aabb[1][0]) + && (point[1] >= aabb[0][1] && point[1] <= aabb[1][1]); +} + +/*! + * @brief check if AABB contains other AABB + * + * @param[in] aabb bounding aabb + * @param[in] other other bounding aabb + */ +CGLM_INLINE +bool +glm_aabb2d_contains(vec2 aabb[2], vec2 other[2]) { + return (aabb[0][0] <= other[0][0] && aabb[1][0] >= other[1][0]) + && (aabb[0][1] <= other[0][1] && aabb[1][1] >= other[1][1]); +} + +#endif /* cglm_aabb2d_h */ diff --git a/external/cglm/affine-mat.h b/external/cglm/affine-mat.h new file mode 100644 index 0000000..c22c0e0 --- /dev/null +++ b/external/cglm/affine-mat.h @@ -0,0 +1,189 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_mul(mat4 m1, mat4 m2, mat4 dest); + CGLM_INLINE void glm_mul_rot(mat4 m1, mat4 m2, mat4 dest); + CGLM_INLINE void glm_inv_tr(mat4 mat); + */ + +#ifndef cglm_affine_mat_h +#define cglm_affine_mat_h + +#include "common.h" +#include "mat4.h" +#include "mat3.h" + +#ifdef CGLM_SSE_FP +# include "simd/sse2/affine.h" +#endif + +#ifdef CGLM_AVX_FP +# include "simd/avx/affine.h" +#endif + +#ifdef CGLM_NEON_FP +# include "simd/neon/affine.h" +#endif + +#ifdef CGLM_SIMD_WASM +# include "simd/wasm/affine.h" +#endif + +/*! + * @brief this is similar to glm_mat4_mul but specialized to affine transform + * + * Matrix format should be: + * R R R X + * R R R Y + * R R R Z + * 0 0 0 W + * + * this reduces some multiplications. It should be faster than mat4_mul. + * if you are not sure about matrix format then DON'T use this! use mat4_mul + * + * @param[in] m1 affine matrix 1 + * @param[in] m2 affine matrix 2 + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_mul(mat4 m1, mat4 m2, mat4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_mul_wasm(m1, m2, dest); +#elif defined(__AVX__) + glm_mul_avx(m1, m2, dest); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glm_mul_sse2(m1, m2, dest); +#elif defined(CGLM_NEON_FP) + glm_mul_neon(m1, m2, dest); +#else + float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], a03 = m1[0][3], + a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2], a13 = m1[1][3], + a20 = m1[2][0], a21 = m1[2][1], a22 = m1[2][2], a23 = m1[2][3], + a30 = m1[3][0], a31 = m1[3][1], a32 = m1[3][2], a33 = m1[3][3], + + b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2], + b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2], + b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2], + b30 = m2[3][0], b31 = m2[3][1], b32 = m2[3][2], b33 = m2[3][3]; + + dest[0][0] = a00 * b00 + a10 * b01 + a20 * b02; + dest[0][1] = a01 * b00 + a11 * b01 + a21 * b02; + dest[0][2] = a02 * b00 + a12 * b01 + a22 * b02; + dest[0][3] = a03 * b00 + a13 * b01 + a23 * b02; + + dest[1][0] = a00 * b10 + a10 * b11 + a20 * b12; + dest[1][1] = a01 * b10 + a11 * b11 + a21 * b12; + dest[1][2] = a02 * b10 + a12 * b11 + a22 * b12; + dest[1][3] = a03 * b10 + a13 * b11 + a23 * b12; + + dest[2][0] = a00 * b20 + a10 * b21 + a20 * b22; + dest[2][1] = a01 * b20 + a11 * b21 + a21 * b22; + dest[2][2] = a02 * b20 + a12 * b21 + a22 * b22; + dest[2][3] = a03 * b20 + a13 * b21 + a23 * b22; + + dest[3][0] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33; + dest[3][1] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33; + dest[3][2] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33; + dest[3][3] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33; +#endif +} + +/*! + * @brief this is similar to glm_mat4_mul but specialized to affine transform + * + * Right Matrix format should be: + * R R R 0 + * R R R 0 + * R R R 0 + * 0 0 0 1 + * + * this reduces some multiplications. It should be faster than mat4_mul. + * if you are not sure about matrix format then DON'T use this! use mat4_mul + * + * @param[in] m1 affine matrix 1 + * @param[in] m2 affine matrix 2 + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_mul_rot(mat4 m1, mat4 m2, mat4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_mul_rot_wasm(m1, m2, dest); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glm_mul_rot_sse2(m1, m2, dest); +#elif defined(CGLM_NEON_FP) + glm_mul_rot_neon(m1, m2, dest); +#else + float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], a03 = m1[0][3], + a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2], a13 = m1[1][3], + a20 = m1[2][0], a21 = m1[2][1], a22 = m1[2][2], a23 = m1[2][3], + a30 = m1[3][0], a31 = m1[3][1], a32 = m1[3][2], a33 = m1[3][3], + + b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2], + b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2], + b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2]; + + dest[0][0] = a00 * b00 + a10 * b01 + a20 * b02; + dest[0][1] = a01 * b00 + a11 * b01 + a21 * b02; + dest[0][2] = a02 * b00 + a12 * b01 + a22 * b02; + dest[0][3] = a03 * b00 + a13 * b01 + a23 * b02; + + dest[1][0] = a00 * b10 + a10 * b11 + a20 * b12; + dest[1][1] = a01 * b10 + a11 * b11 + a21 * b12; + dest[1][2] = a02 * b10 + a12 * b11 + a22 * b12; + dest[1][3] = a03 * b10 + a13 * b11 + a23 * b12; + + dest[2][0] = a00 * b20 + a10 * b21 + a20 * b22; + dest[2][1] = a01 * b20 + a11 * b21 + a21 * b22; + dest[2][2] = a02 * b20 + a12 * b21 + a22 * b22; + dest[2][3] = a03 * b20 + a13 * b21 + a23 * b22; + + dest[3][0] = a30; + dest[3][1] = a31; + dest[3][2] = a32; + dest[3][3] = a33; +#endif +} + +/*! + * @brief inverse orthonormal rotation + translation matrix (ridig-body) + * + * @code + * X = | R T | X' = | R' -R'T | + * | 0 1 | | 0 1 | + * @endcode + * + * @param[in,out] mat matrix + */ +CGLM_INLINE +void +glm_inv_tr(mat4 mat) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_inv_tr_wasm(mat); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glm_inv_tr_sse2(mat); +#elif defined(CGLM_NEON_FP) + glm_inv_tr_neon(mat); +#else + CGLM_ALIGN_MAT mat3 r; + CGLM_ALIGN(8) vec3 t; + + /* rotate */ + glm_mat4_pick3t(mat, r); + glm_mat4_ins3(r, mat); + + /* translate */ + glm_mat3_mulv(r, mat[3], t); + glm_vec3_negate(t); + glm_vec3_copy(t, mat[3]); +#endif +} + +#endif /* cglm_affine_mat_h */ diff --git a/external/cglm/affine-post.h b/external/cglm/affine-post.h new file mode 100644 index 0000000..3e297e6 --- /dev/null +++ b/external/cglm/affine-post.h @@ -0,0 +1,247 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_affine_post_h +#define cglm_affine_post_h + +/* + Functions: + CGLM_INLINE void glm_translated_to(mat4 m, vec3 v, mat4 dest); + CGLM_INLINE void glm_translated(mat4 m, vec3 v); + CGLM_INLINE void glm_translated_x(mat4 m, float to); + CGLM_INLINE void glm_translated_y(mat4 m, float to); + CGLM_INLINE void glm_translated_z(mat4 m, float to); + CGLM_INLINE void glm_rotated_x(mat4 m, float angle, mat4 dest); + CGLM_INLINE void glm_rotated_y(mat4 m, float angle, mat4 dest); + CGLM_INLINE void glm_rotated_z(mat4 m, float angle, mat4 dest); + CGLM_INLINE void glm_rotated(mat4 m, float angle, vec3 axis); + CGLM_INLINE void glm_rotated_at(mat4 m, vec3 pivot, float angle, vec3 axis); + CGLM_INLINE void glm_spinned(mat4 m, float angle, vec3 axis); + */ + +#include "common.h" +#include "util.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" +#include "affine-mat.h" + +/*! + * @brief translate existing transform matrix by v vector + * and stores result in same matrix + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] v translate vector [x, y, z] + */ +CGLM_INLINE +void +glm_translated(mat4 m, vec3 v) { + glm_vec3_add(m[3], v, m[3]); +} + +/*! + * @brief translate existing transform matrix by v vector + * and store result in dest + * + * source matrix will remain same + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in] m affine transform + * @param[in] v translate vector [x, y, z] + * @param[out] dest translated matrix + */ +CGLM_INLINE +void +glm_translated_to(mat4 m, vec3 v, mat4 dest) { + glm_mat4_copy(m, dest); + glm_translated(dest, v); +} + +/*! + * @brief translate existing transform matrix by x factor + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] x x factor + */ +CGLM_INLINE +void +glm_translated_x(mat4 m, float x) { + m[3][0] += x; +} + +/*! + * @brief translate existing transform matrix by y factor + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] y y factor + */ +CGLM_INLINE +void +glm_translated_y(mat4 m, float y) { + m[3][1] += y; +} + +/*! + * @brief translate existing transform matrix by z factor + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] z z factor + */ +CGLM_INLINE +void +glm_translated_z(mat4 m, float z) { + m[3][2] += z; +} + +/*! + * @brief rotate existing transform matrix around X axis by angle + * and store result in dest + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @param[out] dest rotated matrix + */ +CGLM_INLINE +void +glm_rotated_x(mat4 m, float angle, mat4 dest) { + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; + + c = cosf(angle); + s = sinf(angle); + + t[1][1] = c; + t[1][2] = s; + t[2][1] = -s; + t[2][2] = c; + + glm_mul_rot(t, m, dest); +} + +/*! + * @brief rotate existing transform matrix around Y axis by angle + * and store result in dest + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @param[out] dest rotated matrix + */ +CGLM_INLINE +void +glm_rotated_y(mat4 m, float angle, mat4 dest) { + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; + + c = cosf(angle); + s = sinf(angle); + + t[0][0] = c; + t[0][2] = -s; + t[2][0] = s; + t[2][2] = c; + + glm_mul_rot(t, m, dest); +} + +/*! + * @brief rotate existing transform matrix around Z axis by angle + * and store result in dest + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @param[out] dest rotated matrix + */ +CGLM_INLINE +void +glm_rotated_z(mat4 m, float angle, mat4 dest) { + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; + + c = cosf(angle); + s = sinf(angle); + + t[0][0] = c; + t[0][1] = s; + t[1][0] = -s; + t[1][1] = c; + + glm_mul_rot(t, m, dest); +} + +/*! + * @brief rotate existing transform matrix around given axis by angle + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_rotated(mat4 m, float angle, vec3 axis) { + CGLM_ALIGN_MAT mat4 rot; + glm_rotate_make(rot, angle, axis); + glm_mul_rot(rot, m, m); +} + +/*! + * @brief rotate existing transform + * around given axis by angle at given pivot point (rotation center) + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] pivot rotation center + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_rotated_at(mat4 m, vec3 pivot, float angle, vec3 axis) { + CGLM_ALIGN(8) vec3 pivotInv; + + glm_vec3_negate_to(pivot, pivotInv); + + glm_translated(m, pivot); + glm_rotated(m, angle, axis); + glm_translated(m, pivotInv); +} + +/*! + * @brief rotate existing transform matrix around given axis by angle around self (doesn't affected by position) + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_spinned(mat4 m, float angle, vec3 axis) { + CGLM_ALIGN_MAT mat4 rot; + glm_rotate_atm(rot, m[3], angle, axis); + glm_mat4_mul(rot, m, m); +} + +#endif /* cglm_affine_post_h */ diff --git a/external/cglm/affine-pre.h b/external/cglm/affine-pre.h new file mode 100644 index 0000000..2fa77f7 --- /dev/null +++ b/external/cglm/affine-pre.h @@ -0,0 +1,304 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_affine_pre_h +#define cglm_affine_pre_h + +/* + Functions: + CGLM_INLINE void glm_translate_to(mat4 m, vec3 v, mat4 dest); + CGLM_INLINE void glm_translate(mat4 m, vec3 v); + CGLM_INLINE void glm_translate_x(mat4 m, float to); + CGLM_INLINE void glm_translate_y(mat4 m, float to); + CGLM_INLINE void glm_translate_z(mat4 m, float to); + CGLM_INLINE void glm_rotate_x(mat4 m, float angle, mat4 dest); + CGLM_INLINE void glm_rotate_y(mat4 m, float angle, mat4 dest); + CGLM_INLINE void glm_rotate_z(mat4 m, float angle, mat4 dest); + CGLM_INLINE void glm_rotate(mat4 m, float angle, vec3 axis); + CGLM_INLINE void glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis); + CGLM_INLINE void glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis); + CGLM_INLINE void glm_spin(mat4 m, float angle, vec3 axis); + */ + +#include "common.h" +#include "util.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" +#include "affine-mat.h" + +/*! + * @brief translate existing transform matrix by v vector + * and stores result in same matrix + * + * @param[in, out] m affine transform + * @param[in] v translate vector [x, y, z] + */ +CGLM_INLINE +void +glm_translate(mat4 m, vec3 v) { +#if defined(CGLM_SIMD) + glmm_128 m0, m1, m2, m3; + + m0 = glmm_load(m[0]); + m1 = glmm_load(m[1]); + m2 = glmm_load(m[2]); + m3 = glmm_load(m[3]); + + glmm_store(m[3], + glmm_fmadd(m0, glmm_set1(v[0]), + glmm_fmadd(m1, glmm_set1(v[1]), + glmm_fmadd(m2, glmm_set1(v[2]), m3)))); +#else + glm_vec4_muladds(m[0], v[0], m[3]); + glm_vec4_muladds(m[1], v[1], m[3]); + glm_vec4_muladds(m[2], v[2], m[3]); +#endif +} + +/*! + * @brief translate existing transform matrix by v vector + * and store result in dest + * + * source matrix will remain same + * + * @param[in] m affine transform + * @param[in] v translate vector [x, y, z] + * @param[out] dest translated matrix + */ +CGLM_INLINE +void +glm_translate_to(mat4 m, vec3 v, mat4 dest) { + glm_mat4_copy(m, dest); + glm_translate(dest, v); +} + +/*! + * @brief translate existing transform matrix by x factor + * + * @param[in, out] m affine transform + * @param[in] x x factor + */ +CGLM_INLINE +void +glm_translate_x(mat4 m, float x) { +#if defined(CGLM_SIMD) + glmm_store(m[3], glmm_fmadd(glmm_load(m[0]), glmm_set1(x), glmm_load(m[3]))); +#else + vec4 v1; + glm_vec4_scale(m[0], x, v1); + glm_vec4_add(v1, m[3], m[3]); +#endif +} + +/*! + * @brief translate existing transform matrix by y factor + * + * @param[in, out] m affine transform + * @param[in] y y factor + */ +CGLM_INLINE +void +glm_translate_y(mat4 m, float y) { +#if defined(CGLM_SIMD) + glmm_store(m[3], glmm_fmadd(glmm_load(m[1]), glmm_set1(y), glmm_load(m[3]))); +#else + vec4 v1; + glm_vec4_scale(m[1], y, v1); + glm_vec4_add(v1, m[3], m[3]); +#endif +} + +/*! + * @brief translate existing transform matrix by z factor + * + * @param[in, out] m affine transform + * @param[in] z z factor + */ +CGLM_INLINE +void +glm_translate_z(mat4 m, float z) { +#if defined(CGLM_SIMD) + glmm_store(m[3], glmm_fmadd(glmm_load(m[2]), glmm_set1(z), glmm_load(m[3]))); +#else + vec4 v1; + glm_vec4_scale(m[2], z, v1); + glm_vec4_add(v1, m[3], m[3]); +#endif +} + +/*! + * @brief rotate existing transform matrix around X axis by angle + * and store result in dest + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @param[out] dest rotated matrix + */ +CGLM_INLINE +void +glm_rotate_x(mat4 m, float angle, mat4 dest) { + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; + + c = cosf(angle); + s = sinf(angle); + + t[1][1] = c; + t[1][2] = s; + t[2][1] = -s; + t[2][2] = c; + + glm_mul_rot(m, t, dest); +} + +/*! + * @brief rotate existing transform matrix around Y axis by angle + * and store result in dest + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @param[out] dest rotated matrix + */ +CGLM_INLINE +void +glm_rotate_y(mat4 m, float angle, mat4 dest) { + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; + + c = cosf(angle); + s = sinf(angle); + + t[0][0] = c; + t[0][2] = -s; + t[2][0] = s; + t[2][2] = c; + + glm_mul_rot(m, t, dest); +} + +/*! + * @brief rotate existing transform matrix around Z axis by angle + * and store result in dest + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @param[out] dest rotated matrix + */ +CGLM_INLINE +void +glm_rotate_z(mat4 m, float angle, mat4 dest) { + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; + float c, s; + + c = cosf(angle); + s = sinf(angle); + + t[0][0] = c; + t[0][1] = s; + t[1][0] = -s; + t[1][1] = c; + + glm_mul_rot(m, t, dest); +} + +/*! + * @brief rotate existing transform matrix + * around given axis by angle at ORIGIN (0,0,0) + * + * **❗️IMPORTANT ❗️** + * + * If you need to rotate object around itself e.g. center of object or at + * some point [of object] then `glm_rotate_at()` would be better choice to do so. + * + * Even if object's model transform is identity, rotation may not be around + * center of object if object does not lay out at ORIGIN perfectly. + * + * Using `glm_rotate_at()` with center of bounding shape ( AABB, Sphere ... ) + * would be an easy option to rotate around object if object is not at origin. + * + * One another option to rotate around itself at any point is `glm_spin()` + * which is perfect if only rotating around model position is desired e.g. not + * specific point on model for instance center of geometry or center of mass, + * again if geometry is not perfectly centered at origin at identity transform, + * rotation may not be around geometry. + * + * @param[in, out] m affine transform + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_rotate(mat4 m, float angle, vec3 axis) { + CGLM_ALIGN_MAT mat4 rot; + glm_rotate_make(rot, angle, axis); + glm_mul_rot(m, rot, m); +} + +/*! + * @brief rotate existing transform + * around given axis by angle at given pivot point (rotation center) + * + * @param[in, out] m affine transform + * @param[in] pivot rotation center + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis) { + CGLM_ALIGN(8) vec3 pivotInv; + + glm_vec3_negate_to(pivot, pivotInv); + + glm_translate(m, pivot); + glm_rotate(m, angle, axis); + glm_translate(m, pivotInv); +} + +/*! + * @brief creates NEW rotation matrix by angle and axis at given point + * + * this creates rotation matrix, it assumes you don't have a matrix + * + * this should work faster than glm_rotate_at because it reduces + * one glm_translate. + * + * @param[out] m affine transform + * @param[in] pivot rotation center + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis) { + CGLM_ALIGN(8) vec3 pivotInv; + + glm_vec3_negate_to(pivot, pivotInv); + + glm_translate_make(m, pivot); + glm_rotate(m, angle, axis); + glm_translate(m, pivotInv); +} + +/*! + * @brief rotate existing transform matrix + * around given axis by angle around self (doesn't affected by position) + * + * @param[in, out] m affine transform + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_spin(mat4 m, float angle, vec3 axis) { + CGLM_ALIGN_MAT mat4 rot; + glm_rotate_atm(rot, m[3], angle, axis); + glm_mat4_mul(m, rot, m); +} + +#endif /* cglm_affine_pre_h */ diff --git a/external/cglm/affine.h b/external/cglm/affine.h new file mode 100644 index 0000000..2c608f7 --- /dev/null +++ b/external/cglm/affine.h @@ -0,0 +1,238 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_translate_to(mat4 m, vec3 v, mat4 dest); + CGLM_INLINE void glm_translate(mat4 m, vec3 v); + CGLM_INLINE void glm_translate_x(mat4 m, float to); + CGLM_INLINE void glm_translate_y(mat4 m, float to); + CGLM_INLINE void glm_translate_z(mat4 m, float to); + CGLM_INLINE void glm_translate_make(mat4 m, vec3 v); + CGLM_INLINE void glm_scale_to(mat4 m, vec3 v, mat4 dest); + CGLM_INLINE void glm_scale_make(mat4 m, vec3 v); + CGLM_INLINE void glm_scale(mat4 m, vec3 v); + CGLM_INLINE void glm_scale_uni(mat4 m, float s); + CGLM_INLINE void glm_rotate_x(mat4 m, float angle, mat4 dest); + CGLM_INLINE void glm_rotate_y(mat4 m, float angle, mat4 dest); + CGLM_INLINE void glm_rotate_z(mat4 m, float angle, mat4 dest); + CGLM_INLINE void glm_rotate_make(mat4 m, float angle, vec3 axis); + CGLM_INLINE void glm_rotate(mat4 m, float angle, vec3 axis); + CGLM_INLINE void glm_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis); + CGLM_INLINE void glm_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis); + CGLM_INLINE void glm_spin(mat4 m, float angle, vec3 axis); + CGLM_INLINE void glm_decompose_scalev(mat4 m, vec3 s); + CGLM_INLINE bool glm_uniscaled(mat4 m); + CGLM_INLINE void glm_decompose_rs(mat4 m, mat4 r, vec3 s); + CGLM_INLINE void glm_decompose(mat4 m, vec4 t, mat4 r, vec3 s); + */ + +#ifndef cglm_affine_h +#define cglm_affine_h + +#include "common.h" +#include "util.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" +#include "affine-mat.h" + +/*! + * @brief creates NEW translate transform matrix by v vector + * + * @param[out] m affine transform + * @param[in] v translate vector [x, y, z] + */ +CGLM_INLINE +void +glm_translate_make(mat4 m, vec3 v) { + glm_mat4_identity(m); + glm_vec3_copy(v, m[3]); +} + +/*! + * @brief scale existing transform matrix by v vector + * and store result in dest + * + * @param[in] m affine transform + * @param[in] v scale vector [x, y, z] + * @param[out] dest scaled matrix + */ +CGLM_INLINE +void +glm_scale_to(mat4 m, vec3 v, mat4 dest) { + glm_vec4_scale(m[0], v[0], dest[0]); + glm_vec4_scale(m[1], v[1], dest[1]); + glm_vec4_scale(m[2], v[2], dest[2]); + + glm_vec4_copy(m[3], dest[3]); +} + +/*! + * @brief creates NEW scale matrix by v vector + * + * @param[out] m affine transform + * @param[in] v scale vector [x, y, z] + */ +CGLM_INLINE +void +glm_scale_make(mat4 m, vec3 v) { + glm_mat4_identity(m); + m[0][0] = v[0]; + m[1][1] = v[1]; + m[2][2] = v[2]; +} + +/*! + * @brief scales existing transform matrix by v vector + * and stores result in same matrix + * + * @param[in, out] m affine transform + * @param[in] v scale vector [x, y, z] + */ +CGLM_INLINE +void +glm_scale(mat4 m, vec3 v) { + glm_scale_to(m, v, m); +} + +/*! + * @brief applies uniform scale to existing transform matrix v = [s, s, s] + * and stores result in same matrix + * + * @param[in, out] m affine transform + * @param[in] s scale factor + */ +CGLM_INLINE +void +glm_scale_uni(mat4 m, float s) { + CGLM_ALIGN(8) vec3 v = { s, s, s }; + glm_scale_to(m, v, m); +} + +/*! + * @brief creates NEW rotation matrix by angle and axis + * + * axis will be normalized so you don't need to normalize it + * + * @param[out] m affine transform + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_rotate_make(mat4 m, float angle, vec3 axis) { + CGLM_ALIGN(8) vec3 axisn, v, vs; + float c; + + c = cosf(angle); + + glm_vec3_normalize_to(axis, axisn); + glm_vec3_scale(axisn, 1.0f - c, v); + glm_vec3_scale(axisn, sinf(angle), vs); + + glm_vec3_scale(axisn, v[0], m[0]); + glm_vec3_scale(axisn, v[1], m[1]); + glm_vec3_scale(axisn, v[2], m[2]); + + m[0][0] += c; m[1][0] -= vs[2]; m[2][0] += vs[1]; + m[0][1] += vs[2]; m[1][1] += c; m[2][1] -= vs[0]; + m[0][2] -= vs[1]; m[1][2] += vs[0]; m[2][2] += c; + + m[0][3] = m[1][3] = m[2][3] = m[3][0] = m[3][1] = m[3][2] = 0.0f; + m[3][3] = 1.0f; +} + +/*! + * @brief decompose scale vector + * + * @param[in] m affine transform + * @param[out] s scale vector (Sx, Sy, Sz) + */ +CGLM_INLINE +void +glm_decompose_scalev(mat4 m, vec3 s) { + s[0] = glm_vec3_norm(m[0]); + s[1] = glm_vec3_norm(m[1]); + s[2] = glm_vec3_norm(m[2]); +} + +/*! + * @brief returns true if matrix is uniform scaled. This is helpful for + * creating normal matrix. + * + * @param[in] m m + * + * @return boolean + */ +CGLM_INLINE +bool +glm_uniscaled(mat4 m) { + CGLM_ALIGN(8) vec3 s; + glm_decompose_scalev(m, s); + return glm_vec3_eq_all(s); +} + +/*! + * @brief decompose rotation matrix (mat4) and scale vector [Sx, Sy, Sz] + * DON'T pass projected matrix here + * + * @param[in] m affine transform + * @param[out] r rotation matrix + * @param[out] s scale matrix + */ +CGLM_INLINE +void +glm_decompose_rs(mat4 m, mat4 r, vec3 s) { + CGLM_ALIGN(16) vec4 t = {0.0f, 0.0f, 0.0f, 1.0f}; + CGLM_ALIGN(8) vec3 v; + + glm_vec4_copy(m[0], r[0]); + glm_vec4_copy(m[1], r[1]); + glm_vec4_copy(m[2], r[2]); + glm_vec4_copy(t, r[3]); + + s[0] = glm_vec3_norm(m[0]); + s[1] = glm_vec3_norm(m[1]); + s[2] = glm_vec3_norm(m[2]); + + glm_vec4_scale(r[0], 1.0f/s[0], r[0]); + glm_vec4_scale(r[1], 1.0f/s[1], r[1]); + glm_vec4_scale(r[2], 1.0f/s[2], r[2]); + + /* Note from Apple Open Source (assume that the matrix is orthonormal): + check for a coordinate system flip. If the determinant + is -1, then negate the matrix and the scaling factors. */ + glm_vec3_cross(m[0], m[1], v); + if (glm_vec3_dot(v, m[2]) < 0.0f) { + glm_vec4_negate(r[0]); + glm_vec4_negate(r[1]); + glm_vec4_negate(r[2]); + glm_vec3_negate(s); + } +} + +/*! + * @brief decompose affine transform, TODO: extract shear factors. + * DON'T pass projected matrix here + * + * @param[in] m affine transform + * @param[out] t translation vector + * @param[out] r rotation matrix (mat4) + * @param[out] s scaling vector [X, Y, Z] + */ +CGLM_INLINE +void +glm_decompose(mat4 m, vec4 t, mat4 r, vec3 s) { + glm_vec4_copy(m[3], t); + glm_decompose_rs(m, r, s); +} + +#include "affine-pre.h" +#include "affine-post.h" + +#endif /* cglm_affine_h */ diff --git a/external/cglm/affine2d-post.h b/external/cglm/affine2d-post.h new file mode 100644 index 0000000..c6605a8 --- /dev/null +++ b/external/cglm/affine2d-post.h @@ -0,0 +1,132 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_affine2d_post_h +#define cglm_affine2d_post_h + +/* + Functions: + CGLM_INLINE void glm_translated2d(mat3 m, vec2 v); + CGLM_INLINE void glm_translated2d_x(mat3 m, float to); + CGLM_INLINE void glm_translated2d_y(mat3 m, float to); + CGLM_INLINE void glm_rotated2d(mat3 m, float angle); + CGLM_INLINE void glm_scaled2d(mat3 m, vec2 v); + CGLM_INLINE void glm_scaled2d_uni(mat3 m, float s); + */ + +#include "vec2.h" + +/*! + * @brief translate existing transform matrix by v vector + * and store result in same matrix + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] v translate vector [x, y] + */ +CGLM_INLINE +void +glm_translated2d(mat3 m, vec2 v) { + glm_vec2_add(m[2], v, m[2]); +} + +/*! + * @brief translate existing transform matrix by x factor + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] x x factor + */ +CGLM_INLINE +void +glm_translated2d_x(mat3 m, float x) { + m[2][0] += x; +} + +/*! + * @brief translate existing transform matrix by y factor + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] y y factor + */ +CGLM_INLINE +void +glm_translated2d_y(mat3 m, float y) { + m[2][1] += y; +} + +/*! + * @brief rotate existing transform matrix by angle + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] angle angle (radians) + */ +CGLM_INLINE +void +glm_rotated2d(mat3 m, float angle) { + float c = cosf(angle), + s = sinf(angle), + + m00 = m[0][0], m10 = m[1][0], m20 = m[2][0], + m01 = m[0][1], m11 = m[1][1], m21 = m[2][1]; + + m[0][0] = c * m00 - s * m01; + m[1][0] = c * m10 - s * m11; + m[2][0] = c * m20 - s * m21; + + m[0][1] = s * m00 + c * m01; + m[1][1] = s * m10 + c * m11; + m[2][1] = s * m20 + c * m21; +} + +/*! + * @brief scale existing 2d transform matrix by v vector + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] v scale vector [x, y] + */ +CGLM_INLINE +void +glm_scaled2d(mat3 m, vec2 v) { + m[0][0] *= v[0]; + m[1][0] *= v[0]; + m[2][0] *= v[0]; + + m[0][1] *= v[1]; + m[1][1] *= v[1]; + m[2][1] *= v[1]; +} + +/*! + * @brief applies uniform scale to existing 2d transform matrix v = [s, s] + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] s scale factor + */ +CGLM_INLINE +void +glm_scaled2d_uni(mat3 m, float s) { + m[0][0] *= s; + m[1][0] *= s; + m[2][0] *= s; + + m[0][1] *= s; + m[1][1] *= s; + m[2][1] *= s; +} + +#endif /* cglm_affine2d_post_h */ diff --git a/external/cglm/affine2d.h b/external/cglm/affine2d.h new file mode 100644 index 0000000..0dcf50a --- /dev/null +++ b/external/cglm/affine2d.h @@ -0,0 +1,268 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_translate2d(mat3 m, vec2 v) + CGLM_INLINE void glm_translate2d_to(mat3 m, vec2 v, mat3 dest) + CGLM_INLINE void glm_translate2d_x(mat3 m, float x) + CGLM_INLINE void glm_translate2d_y(mat3 m, float y) + CGLM_INLINE void glm_translate2d_make(mat3 m, vec2 v) + CGLM_INLINE void glm_scale2d_to(mat3 m, vec2 v, mat3 dest) + CGLM_INLINE void glm_scale2d_make(mat3 m, vec2 v) + CGLM_INLINE void glm_scale2d(mat3 m, vec2 v) + CGLM_INLINE void glm_scale2d_uni(mat3 m, float s) + CGLM_INLINE void glm_rotate2d_make(mat3 m, float angle) + CGLM_INLINE void glm_rotate2d(mat3 m, float angle) + CGLM_INLINE void glm_rotate2d_to(mat3 m, float angle, mat3 dest) + */ + +#ifndef cglm_affine2d_h +#define cglm_affine2d_h + +#include "common.h" +#include "util.h" +#include "vec2.h" +#include "mat3.h" + +/*! + * @brief translate existing 2d transform matrix by v vector + * and stores result in same matrix + * + * @param[in, out] m affine transform + * @param[in] v translate vector [x, y] + */ +CGLM_INLINE +void +glm_translate2d(mat3 m, vec2 v) { + m[2][0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0]; + m[2][1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1]; + m[2][2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2]; +} + +/*! + * @brief translate existing 2d transform matrix by v vector + * and store result in dest + * + * source matrix will remain same + * + * @param[in] m affine transform + * @param[in] v translate vector [x, y] + * @param[out] dest translated matrix + */ +CGLM_INLINE +void +glm_translate2d_to(mat3 m, vec2 v, mat3 dest) { + glm_mat3_copy(m, dest); + glm_translate2d(dest, v); +} + +/*! + * @brief translate existing 2d transform matrix by x factor + * + * @param[in, out] m affine transform + * @param[in] x x factor + */ +CGLM_INLINE +void +glm_translate2d_x(mat3 m, float x) { + m[2][0] = m[0][0] * x + m[2][0]; + m[2][1] = m[0][1] * x + m[2][1]; + m[2][2] = m[0][2] * x + m[2][2]; +} + +/*! + * @brief translate existing 2d transform matrix by y factor + * + * @param[in, out] m affine transform + * @param[in] y y factor + */ +CGLM_INLINE +void +glm_translate2d_y(mat3 m, float y) { + m[2][0] = m[1][0] * y + m[2][0]; + m[2][1] = m[1][1] * y + m[2][1]; + m[2][2] = m[1][2] * y + m[2][2]; +} + +/*! + * @brief creates NEW translate 2d transform matrix by v vector + * + * @param[out] m affine transform + * @param[in] v translate vector [x, y] + */ +CGLM_INLINE +void +glm_translate2d_make(mat3 m, vec2 v) { + glm_mat3_identity(m); + m[2][0] = v[0]; + m[2][1] = v[1]; +} + +/*! + * @brief scale existing 2d transform matrix by v vector + * and store result in dest + * + * @param[in] m affine transform + * @param[in] v scale vector [x, y] + * @param[out] dest scaled matrix + */ +CGLM_INLINE +void +glm_scale2d_to(mat3 m, vec2 v, mat3 dest) { + dest[0][0] = m[0][0] * v[0]; + dest[0][1] = m[0][1] * v[0]; + dest[0][2] = m[0][2] * v[0]; + + dest[1][0] = m[1][0] * v[1]; + dest[1][1] = m[1][1] * v[1]; + dest[1][2] = m[1][2] * v[1]; + + dest[2][0] = m[2][0]; + dest[2][1] = m[2][1]; + dest[2][2] = m[2][2]; +} + +/*! + * @brief creates NEW 2d scale matrix by v vector + * + * @param[out] m affine transform + * @param[in] v scale vector [x, y] + */ +CGLM_INLINE +void +glm_scale2d_make(mat3 m, vec2 v) { + glm_mat3_identity(m); + m[0][0] = v[0]; + m[1][1] = v[1]; +} + +/*! + * @brief scales existing 2d transform matrix by v vector + * and stores result in same matrix + * + * @param[in, out] m affine transform + * @param[in] v scale vector [x, y] + */ +CGLM_INLINE +void +glm_scale2d(mat3 m, vec2 v) { + m[0][0] = m[0][0] * v[0]; + m[0][1] = m[0][1] * v[0]; + m[0][2] = m[0][2] * v[0]; + + m[1][0] = m[1][0] * v[1]; + m[1][1] = m[1][1] * v[1]; + m[1][2] = m[1][2] * v[1]; +} + +/*! + * @brief applies uniform scale to existing 2d transform matrix v = [s, s] + * and stores result in same matrix + * + * @param[in, out] m affine transform + * @param[in] s scale factor + */ +CGLM_INLINE +void +glm_scale2d_uni(mat3 m, float s) { + m[0][0] = m[0][0] * s; + m[0][1] = m[0][1] * s; + m[0][2] = m[0][2] * s; + + m[1][0] = m[1][0] * s; + m[1][1] = m[1][1] * s; + m[1][2] = m[1][2] * s; +} + +/*! + * @brief creates NEW rotation matrix by angle around Z axis + * + * @param[out] m affine transform + * @param[in] angle angle (radians) + */ +CGLM_INLINE +void +glm_rotate2d_make(mat3 m, float angle) { + float c, s; + + s = sinf(angle); + c = cosf(angle); + + m[0][0] = c; + m[0][1] = s; + m[0][2] = 0; + + m[1][0] = -s; + m[1][1] = c; + m[1][2] = 0; + + m[2][0] = 0.0f; + m[2][1] = 0.0f; + m[2][2] = 1.0f; +} + +/*! + * @brief rotate existing 2d transform matrix around Z axis by angle + * and store result in same matrix + * + * @param[in, out] m affine transform + * @param[in] angle angle (radians) + */ +CGLM_INLINE +void +glm_rotate2d(mat3 m, float angle) { + float m00 = m[0][0], m10 = m[1][0], + m01 = m[0][1], m11 = m[1][1], + m02 = m[0][2], m12 = m[1][2]; + float c, s; + + s = sinf(angle); + c = cosf(angle); + + m[0][0] = m00 * c + m10 * s; + m[0][1] = m01 * c + m11 * s; + m[0][2] = m02 * c + m12 * s; + + m[1][0] = m00 * -s + m10 * c; + m[1][1] = m01 * -s + m11 * c; + m[1][2] = m02 * -s + m12 * c; +} + +/*! + * @brief rotate existing 2d transform matrix around Z axis by angle + * and store result in dest + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_rotate2d_to(mat3 m, float angle, mat3 dest) { + float m00 = m[0][0], m10 = m[1][0], + m01 = m[0][1], m11 = m[1][1], + m02 = m[0][2], m12 = m[1][2]; + float c, s; + + s = sinf(angle); + c = cosf(angle); + + dest[0][0] = m00 * c + m10 * s; + dest[0][1] = m01 * c + m11 * s; + dest[0][2] = m02 * c + m12 * s; + + dest[1][0] = m00 * -s + m10 * c; + dest[1][1] = m01 * -s + m11 * c; + dest[1][2] = m02 * -s + m12 * c; + + dest[2][0] = m[2][0]; + dest[2][1] = m[2][1]; + dest[2][2] = m[2][2]; +} + +#endif /* cglm_affine2d_h */ diff --git a/external/cglm/applesimd.h b/external/cglm/applesimd.h new file mode 100644 index 0000000..479ada6 --- /dev/null +++ b/external/cglm/applesimd.h @@ -0,0 +1,136 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_applesimd_h +#define cglm_applesimd_h +#if defined(__APPLE__) \ + && defined(SIMD_COMPILER_HAS_REQUIRED_FEATURES) \ + && defined(SIMD_BASE) \ + && defined(SIMD_TYPES) \ + && defined(SIMD_VECTOR_TYPES) + +#include "common.h" +#include "struct.h" + +/*! + * @brief converts mat4 to Apple's simd type simd_float4x4 + * @return simd_float4x4 + */ +CGLM_INLINE +simd_float4x4 +glm_mat4_applesimd(mat4 m) { + simd_float4x4 t; + + t.columns[0][0] = m[0][0]; + t.columns[0][1] = m[0][1]; + t.columns[0][2] = m[0][2]; + t.columns[0][3] = m[0][3]; + + t.columns[1][0] = m[1][0]; + t.columns[1][1] = m[1][1]; + t.columns[1][2] = m[1][2]; + t.columns[1][3] = m[1][3]; + + t.columns[2][0] = m[2][0]; + t.columns[2][1] = m[2][1]; + t.columns[2][2] = m[2][2]; + t.columns[2][3] = m[2][3]; + + t.columns[3][0] = m[3][0]; + t.columns[3][1] = m[3][1]; + t.columns[3][2] = m[3][2]; + t.columns[3][3] = m[3][3]; + + return t; +} + +/*! +* @brief converts mat3 to Apple's simd type simd_float3x3 +* @return simd_float3x3 +*/ +CGLM_INLINE +simd_float3x3 +glm_mat3_applesimd(mat3 m) { + simd_float3x3 t; + + t.columns[0][0] = m[0][0]; + t.columns[0][1] = m[0][1]; + t.columns[0][2] = m[0][2]; + + t.columns[1][0] = m[1][0]; + t.columns[1][1] = m[1][1]; + t.columns[1][2] = m[1][2]; + + t.columns[2][0] = m[2][0]; + t.columns[2][1] = m[2][1]; + t.columns[2][2] = m[2][2]; + + return t; +} + +/*! +* @brief converts vec4 to Apple's simd type simd_float4 +* @return simd_float4 +*/ +CGLM_INLINE +simd_float4 +glm_vec4_applesimd(vec4 v) { + return (simd_float4){v[0], v[1], v[2], v[3]}; +} + +/*! +* @brief converts vec3 to Apple's simd type simd_float3 +* @return simd_float3 +*/ +CGLM_INLINE +simd_float3 +glm_vec3_applesimd(vec3 v) { + return (simd_float3){v[0], v[1], v[2]}; +} + +/*! + * @brief generic function to convert cglm types to Apple's simd types + * + * Example usage: + * simd_float4x4 m = applesimd(mat4_value); + * simd_float3 v = applesimd(vec3_value); + * + * @param x cglm type (mat4, mat3, vec4, vec3) + * @return corresponding Apple simd type + */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +# define applesimd(x) _Generic((x), \ + mat4: glm_mat4_applesimd, \ + mat3: glm_mat3_applesimd, \ + vec4: glm_vec4_applesimd, \ + vec3: glm_vec3_applesimd \ + )((x)) +#endif + +#ifdef cglm_types_struct_h +CGLM_INLINE simd_float4x4 glms_mat4_(applesimd)(mat4s m) { return glm_mat4_applesimd(m.raw); } +CGLM_INLINE simd_float3x3 glms_mat3_(applesimd)(mat3s m) { return glm_mat3_applesimd(m.raw); } +CGLM_INLINE simd_float4 glms_vec4_(applesimd)(vec4s v) { return glm_vec4_applesimd(v.raw); } +CGLM_INLINE simd_float3 glms_vec3_(applesimd)(vec3s v) { return glm_vec3_applesimd(v.raw); } + +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +# undef applesimd +# define applesimd(x) _Generic((x), \ + mat4: glm_mat4_applesimd, \ + mat3: glm_mat3_applesimd, \ + vec4: glm_vec4_applesimd, \ + vec3: glm_vec3_applesimd, \ + mat4s: glms_mat4_(applesimd), \ + mat3s: glms_mat3_(applesimd), \ + vec4s: glms_vec4_(applesimd), \ + vec3s: glms_vec3_(applesimd) \ + )((x)) +#endif +#endif + +#endif +#endif /* cglm_applesimd_h */ diff --git a/external/cglm/bezier.h b/external/cglm/bezier.h new file mode 100644 index 0000000..a6e5f8a --- /dev/null +++ b/external/cglm/bezier.h @@ -0,0 +1,154 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_bezier_h +#define cglm_bezier_h + +#include "common.h" + +#define GLM_BEZIER_MAT_INIT {{-1.0f, 3.0f, -3.0f, 1.0f}, \ + { 3.0f, -6.0f, 3.0f, 0.0f}, \ + {-3.0f, 3.0f, 0.0f, 0.0f}, \ + { 1.0f, 0.0f, 0.0f, 0.0f}} +#define GLM_HERMITE_MAT_INIT {{ 2.0f, -3.0f, 0.0f, 1.0f}, \ + {-2.0f, 3.0f, 0.0f, 0.0f}, \ + { 1.0f, -2.0f, 1.0f, 0.0f}, \ + { 1.0f, -1.0f, 0.0f, 0.0f}} +/* for C only */ +#define GLM_BEZIER_MAT ((mat4)GLM_BEZIER_MAT_INIT) +#define GLM_HERMITE_MAT ((mat4)GLM_HERMITE_MAT_INIT) + +#define CGLM_DECASTEL_EPS 1e-9f +#define CGLM_DECASTEL_MAX 1000 +#define CGLM_DECASTEL_SMALL 1e-20f + +/*! + * @brief cubic bezier interpolation + * + * Formula: + * B(s) = P0*(1-s)^3 + 3*C0*s*(1-s)^2 + 3*C1*s^2*(1-s) + P1*s^3 + * + * similar result using matrix: + * B(s) = glm_smc(t, GLM_BEZIER_MAT, (vec4){p0, c0, c1, p1}) + * + * glm_eq(glm_smc(...), glm_bezier(...)) should return TRUE + * + * @param[in] s parameter between 0 and 1 + * @param[in] p0 begin point + * @param[in] c0 control point 1 + * @param[in] c1 control point 2 + * @param[in] p1 end point + * + * @return B(s) + */ +CGLM_INLINE +float +glm_bezier(float s, float p0, float c0, float c1, float p1) { + float x, xx, ss, xs3, a; + + x = 1.0f - s; + xx = x * x; + ss = s * s; + xs3 = (s - ss) * 3.0f; + a = p0 * xx + c0 * xs3; + + return a + s * (c1 * xs3 + p1 * ss - a); +} + +/*! + * @brief cubic hermite interpolation + * + * Formula: + * H(s) = P0*(2*s^3 - 3*s^2 + 1) + T0*(s^3 - 2*s^2 + s) + * + P1*(-2*s^3 + 3*s^2) + T1*(s^3 - s^2) + * + * similar result using matrix: + * H(s) = glm_smc(t, GLM_HERMITE_MAT, (vec4){p0, p1, c0, c1}) + * + * glm_eq(glm_smc(...), glm_hermite(...)) should return TRUE + * + * @param[in] s parameter between 0 and 1 + * @param[in] p0 begin point + * @param[in] t0 tangent 1 + * @param[in] t1 tangent 2 + * @param[in] p1 end point + * + * @return H(s) + */ +CGLM_INLINE +float +glm_hermite(float s, float p0, float t0, float t1, float p1) { + float ss, d, a, b, c, e, f; + + ss = s * s; + a = ss + ss; + c = a + ss; + b = a * s; + d = s * ss; + f = d - ss; + e = b - c; + + return p0 * (e + 1.0f) + t0 * (f - ss + s) + t1 * f - p1 * e; +} + +/*! + * @brief iterative way to solve cubic equation + * + * @param[in] prm parameter between 0 and 1 + * @param[in] p0 begin point + * @param[in] c0 control point 1 + * @param[in] c1 control point 2 + * @param[in] p1 end point + * + * @return parameter to use in cubic equation + */ +CGLM_INLINE +float +glm_decasteljau(float prm, float p0, float c0, float c1, float p1) { + float u, v, a, b, c, d, e, f; + int i; + + if (prm - p0 < CGLM_DECASTEL_SMALL) + return 0.0f; + + if (p1 - prm < CGLM_DECASTEL_SMALL) + return 1.0f; + + u = 0.0f; + v = 1.0f; + + for (i = 0; i < CGLM_DECASTEL_MAX; i++) { + /* de Casteljau Subdivision */ + a = (p0 + c0) * 0.5f; + b = (c0 + c1) * 0.5f; + c = (c1 + p1) * 0.5f; + d = (a + b) * 0.5f; + e = (b + c) * 0.5f; + f = (d + e) * 0.5f; /* this one is on the curve! */ + + /* The curve point is close enough to our wanted t */ + if (fabsf(f - prm) < CGLM_DECASTEL_EPS) + return glm_clamp_zo((u + v) * 0.5f); + + /* dichotomy */ + if (f < prm) { + p0 = f; + c0 = e; + c1 = c; + u = (u + v) * 0.5f; + } else { + c0 = a; + c1 = d; + p1 = f; + v = (u + v) * 0.5f; + } + } + + return glm_clamp_zo((u + v) * 0.5f); +} + +#endif /* cglm_bezier_h */ diff --git a/external/cglm/box.h b/external/cglm/box.h new file mode 100644 index 0000000..8bba678 --- /dev/null +++ b/external/cglm/box.h @@ -0,0 +1,281 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_box_h +#define cglm_box_h + +#include "common.h" +#include "vec3.h" +#include "vec4.h" +#include "util.h" + +/*! + * @brief apply transform to Axis-Aligned Bounding Box + * + * @param[in] box bounding box + * @param[in] m transform matrix + * @param[out] dest transformed bounding box + */ +CGLM_INLINE +void +glm_aabb_transform(vec3 box[2], mat4 m, vec3 dest[2]) { + vec3 v[2], xa, xb, ya, yb, za, zb; + + glm_vec3_scale(m[0], box[0][0], xa); + glm_vec3_scale(m[0], box[1][0], xb); + + glm_vec3_scale(m[1], box[0][1], ya); + glm_vec3_scale(m[1], box[1][1], yb); + + glm_vec3_scale(m[2], box[0][2], za); + glm_vec3_scale(m[2], box[1][2], zb); + + /* translation + min(xa, xb) + min(ya, yb) + min(za, zb) */ + glm_vec3(m[3], v[0]); + glm_vec3_minadd(xa, xb, v[0]); + glm_vec3_minadd(ya, yb, v[0]); + glm_vec3_minadd(za, zb, v[0]); + + /* translation + max(xa, xb) + max(ya, yb) + max(za, zb) */ + glm_vec3(m[3], v[1]); + glm_vec3_maxadd(xa, xb, v[1]); + glm_vec3_maxadd(ya, yb, v[1]); + glm_vec3_maxadd(za, zb, v[1]); + + glm_vec3_copy(v[0], dest[0]); + glm_vec3_copy(v[1], dest[1]); +} + +/*! + * @brief merges two AABB bounding box and creates new one + * + * two box must be in same space, if one of box is in different space then + * you should consider to convert it's space by glm_box_space + * + * @param[in] box1 bounding box 1 + * @param[in] box2 bounding box 2 + * @param[out] dest merged bounding box + */ +CGLM_INLINE +void +glm_aabb_merge(vec3 box1[2], vec3 box2[2], vec3 dest[2]) { + dest[0][0] = glm_min(box1[0][0], box2[0][0]); + dest[0][1] = glm_min(box1[0][1], box2[0][1]); + dest[0][2] = glm_min(box1[0][2], box2[0][2]); + + dest[1][0] = glm_max(box1[1][0], box2[1][0]); + dest[1][1] = glm_max(box1[1][1], box2[1][1]); + dest[1][2] = glm_max(box1[1][2], box2[1][2]); +} + +/*! + * @brief crops a bounding box with another one. + * + * this could be useful for getting a bbox which fits with view frustum and + * object bounding boxes. In this case you crop view frustum box with objects + * box + * + * @param[in] box bounding box 1 + * @param[in] cropBox crop box + * @param[out] dest cropped bounding box + */ +CGLM_INLINE +void +glm_aabb_crop(vec3 box[2], vec3 cropBox[2], vec3 dest[2]) { + dest[0][0] = glm_max(box[0][0], cropBox[0][0]); + dest[0][1] = glm_max(box[0][1], cropBox[0][1]); + dest[0][2] = glm_max(box[0][2], cropBox[0][2]); + + dest[1][0] = glm_min(box[1][0], cropBox[1][0]); + dest[1][1] = glm_min(box[1][1], cropBox[1][1]); + dest[1][2] = glm_min(box[1][2], cropBox[1][2]); +} + +/*! + * @brief crops a bounding box with another one. + * + * this could be useful for getting a bbox which fits with view frustum and + * object bounding boxes. In this case you crop view frustum box with objects + * box + * + * @param[in] box bounding box + * @param[in] cropBox crop box + * @param[in] clampBox minimum box + * @param[out] dest cropped bounding box + */ +CGLM_INLINE +void +glm_aabb_crop_until(vec3 box[2], + vec3 cropBox[2], + vec3 clampBox[2], + vec3 dest[2]) { + glm_aabb_crop(box, cropBox, dest); + glm_aabb_merge(clampBox, dest, dest); +} + +/*! + * @brief check if AABB intersects with frustum planes + * + * this could be useful for frustum culling using AABB. + * + * OPTIMIZATION HINT: + * if planes order is similar to LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR + * then this method should run even faster because it would only use two + * planes if object is not inside the two planes + * fortunately cglm extracts planes as this order! just pass what you got! + * + * @param[in] box bounding box + * @param[in] planes frustum planes + */ +CGLM_INLINE +bool +glm_aabb_frustum(vec3 box[2], vec4 planes[6]) { + float *p, dp; + int i; + + for (i = 0; i < 6; i++) { + p = planes[i]; + dp = p[0] * box[p[0] > 0.0f][0] + + p[1] * box[p[1] > 0.0f][1] + + p[2] * box[p[2] > 0.0f][2]; + + if (dp < -p[3]) + return false; + } + + return true; +} + +/*! + * @brief invalidate AABB min and max values + * + * @param[in, out] box bounding box + */ +CGLM_INLINE +void +glm_aabb_invalidate(vec3 box[2]) { + glm_vec3_broadcast(FLT_MAX, box[0]); + glm_vec3_broadcast(-FLT_MAX, box[1]); +} + +/*! + * @brief check if AABB is valid or not + * + * @param[in] box bounding box + */ +CGLM_INLINE +bool +glm_aabb_isvalid(vec3 box[2]) { + return glm_vec3_max(box[0]) != FLT_MAX + && glm_vec3_min(box[1]) != -FLT_MAX; +} + +/*! + * @brief distance between of min and max + * + * @param[in] box bounding box + */ +CGLM_INLINE +float +glm_aabb_size(vec3 box[2]) { + return glm_vec3_distance(box[0], box[1]); +} + +/*! + * @brief radius of sphere which surrounds AABB + * + * @param[in] box bounding box + */ +CGLM_INLINE +float +glm_aabb_radius(vec3 box[2]) { + return glm_aabb_size(box) * 0.5f; +} + +/*! + * @brief computes center point of AABB + * + * @param[in] box bounding box + * @param[out] dest center of bounding box + */ +CGLM_INLINE +void +glm_aabb_center(vec3 box[2], vec3 dest) { + glm_vec3_center(box[0], box[1], dest); +} + +/*! + * @brief check if two AABB intersects + * + * @param[in] box bounding box + * @param[in] other other bounding box + */ +CGLM_INLINE +bool +glm_aabb_aabb(vec3 box[2], vec3 other[2]) { + return (box[0][0] <= other[1][0] && box[1][0] >= other[0][0]) + && (box[0][1] <= other[1][1] && box[1][1] >= other[0][1]) + && (box[0][2] <= other[1][2] && box[1][2] >= other[0][2]); +} + +/*! + * @brief check if AABB intersects with sphere + * + * https://github.com/erich666/GraphicsGems/blob/master/gems/BoxSphere.c + * Solid Box - Solid Sphere test. + * + * Sphere Representation in cglm: [center.x, center.y, center.z, radii] + * + * @param[in] box solid bounding box + * @param[in] s solid sphere + */ +CGLM_INLINE +bool +glm_aabb_sphere(vec3 box[2], vec4 s) { + float dmin; + int a, b, c; + + a = (s[0] < box[0][0]) + (s[0] > box[1][0]); + b = (s[1] < box[0][1]) + (s[1] > box[1][1]); + c = (s[2] < box[0][2]) + (s[2] > box[1][2]); + + dmin = glm_pow2((s[0] - box[!(a - 1)][0]) * (a != 0)) + + glm_pow2((s[1] - box[!(b - 1)][1]) * (b != 0)) + + glm_pow2((s[2] - box[!(c - 1)][2]) * (c != 0)); + + return dmin <= glm_pow2(s[3]); +} + +/*! + * @brief check if point is inside of AABB + * + * @param[in] box bounding box + * @param[in] point point + */ +CGLM_INLINE +bool +glm_aabb_point(vec3 box[2], vec3 point) { + return (point[0] >= box[0][0] && point[0] <= box[1][0]) + && (point[1] >= box[0][1] && point[1] <= box[1][1]) + && (point[2] >= box[0][2] && point[2] <= box[1][2]); +} + +/*! + * @brief check if AABB contains other AABB + * + * @param[in] box bounding box + * @param[in] other other bounding box + */ +CGLM_INLINE +bool +glm_aabb_contains(vec3 box[2], vec3 other[2]) { + return (box[0][0] <= other[0][0] && box[1][0] >= other[1][0]) + && (box[0][1] <= other[0][1] && box[1][1] >= other[1][1]) + && (box[0][2] <= other[0][2] && box[1][2] >= other[1][2]); +} + +#endif /* cglm_box_h */ diff --git a/external/cglm/call.h b/external/cglm/call.h new file mode 100644 index 0000000..165f502 --- /dev/null +++ b/external/cglm/call.h @@ -0,0 +1,51 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_call_h +#define cglm_call_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "cglm.h" +#include "call/vec2.h" +#include "call/vec3.h" +#include "call/vec4.h" +#include "call/ivec2.h" +#include "call/ivec3.h" +#include "call/ivec4.h" +#include "call/mat2.h" +#include "call/mat2x3.h" +#include "call/mat2x4.h" +#include "call/mat3.h" +#include "call/mat3x2.h" +#include "call/mat3x4.h" +#include "call/mat4.h" +#include "call/mat4x2.h" +#include "call/mat4x3.h" +#include "call/affine.h" +#include "call/cam.h" +#include "call/quat.h" +#include "call/euler.h" +#include "call/plane.h" +#include "call/noise.h" +#include "call/frustum.h" +#include "call/aabb2d.h" +#include "call/box.h" +#include "call/io.h" +#include "call/project.h" +#include "call/sphere.h" +#include "call/ease.h" +#include "call/curve.h" +#include "call/bezier.h" +#include "call/ray.h" +#include "call/affine2d.h" + +#ifdef __cplusplus +} +#endif +#endif /* cglm_call_h */ diff --git a/external/cglm/call/aabb2d.h b/external/cglm/call/aabb2d.h new file mode 100644 index 0000000..e6f36a0 --- /dev/null +++ b/external/cglm/call/aabb2d.h @@ -0,0 +1,89 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_aabb2d_h +#define cglmc_aabb2d_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +/* DEPRECATED! use _diag */ +#define glmc_aabb2d_size(aabb) glmc_aabb2d_diag(aabb) + +CGLM_EXPORT +void +glmc_aabb2d_zero(vec2 aabb[2]); + +CGLM_EXPORT +void +glmc_aabb2d_copy(vec2 aabb[2], vec2 dest[2]); + +CGLM_EXPORT +void +glmc_aabb2d_transform(vec2 aabb[2], mat3 m, vec2 dest[2]); + +CGLM_EXPORT +void +glmc_aabb2d_merge(vec2 aabb1[2], vec2 aabb2[2], vec2 dest[2]); + +CGLM_EXPORT +void +glmc_aabb2d_crop(vec2 aabb[2], vec2 cropAabb[2], vec2 dest[2]); + +CGLM_EXPORT +void +glmc_aabb2d_crop_until(vec2 aabb[2], + vec2 cropAabb[2], + vec2 clampAabb[2], + vec2 dest[2]); + +CGLM_EXPORT +void +glmc_aabb2d_invalidate(vec2 aabb[2]); + +CGLM_EXPORT +bool +glmc_aabb2d_isvalid(vec2 aabb[2]); + +CGLM_EXPORT +float +glmc_aabb2d_diag(vec2 aabb[2]); + +CGLM_EXPORT +void +glmc_aabb2d_sizev(vec2 aabb[2], vec2 dest); + +CGLM_EXPORT +float +glmc_aabb2d_radius(vec2 aabb[2]); + +CGLM_EXPORT +void +glmc_aabb2d_center(vec2 aabb[2], vec2 dest); + +CGLM_EXPORT +bool +glmc_aabb2d_aabb(vec2 aabb[2], vec2 other[2]); + +CGLM_EXPORT +bool +glmc_aabb2d_point(vec2 aabb[2], vec2 point); + +CGLM_EXPORT +bool +glmc_aabb2d_contains(vec2 aabb[2], vec2 other[2]); + +CGLM_EXPORT +bool +glmc_aabb2d_circle(vec2 aabb[2], vec3 s); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_aabb2d_h */ diff --git a/external/cglm/call/affine.h b/external/cglm/call/affine.h new file mode 100644 index 0000000..52b8501 --- /dev/null +++ b/external/cglm/call/affine.h @@ -0,0 +1,167 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_affine_h +#define cglmc_affine_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_translate_make(mat4 m, vec3 v); + +CGLM_EXPORT +void +glmc_translate_to(mat4 m, vec3 v, mat4 dest); + +CGLM_EXPORT +void +glmc_translate(mat4 m, vec3 v); + +CGLM_EXPORT +void +glmc_translate_x(mat4 m, float to); + +CGLM_EXPORT +void +glmc_translate_y(mat4 m, float to); + +CGLM_EXPORT +void +glmc_translate_z(mat4 m, float to); + +CGLM_EXPORT +void +glmc_scale_make(mat4 m, vec3 v); + +CGLM_EXPORT +void +glmc_scale_to(mat4 m, vec3 v, mat4 dest); + +CGLM_EXPORT +void +glmc_scale(mat4 m, vec3 v); + +CGLM_EXPORT +void +glmc_scale_uni(mat4 m, float s); + +CGLM_EXPORT +void +glmc_rotate_x(mat4 m, float rad, mat4 dest); + +CGLM_EXPORT +void +glmc_rotate_y(mat4 m, float rad, mat4 dest); + +CGLM_EXPORT +void +glmc_rotate_z(mat4 m, float rad, mat4 dest); + +CGLM_EXPORT +void +glmc_rotate_make(mat4 m, float angle, vec3 axis); + +CGLM_EXPORT +void +glmc_rotate(mat4 m, float angle, vec3 axis); + +CGLM_EXPORT +void +glmc_rotate_at(mat4 m, vec3 pivot, float angle, vec3 axis); + +CGLM_EXPORT +void +glmc_rotate_atm(mat4 m, vec3 pivot, float angle, vec3 axis); + +CGLM_EXPORT +void +glmc_spin(mat4 m, float angle, vec3 axis); + +CGLM_EXPORT +void +glmc_decompose_scalev(mat4 m, vec3 s); + +CGLM_EXPORT +bool +glmc_uniscaled(mat4 m); + +CGLM_EXPORT +void +glmc_decompose_rs(mat4 m, mat4 r, vec3 s); + +CGLM_EXPORT +void +glmc_decompose(mat4 m, vec4 t, mat4 r, vec3 s); + +/* affine-post */ + +CGLM_EXPORT +void +glmc_translated(mat4 m, vec3 v); + +CGLM_EXPORT +void +glmc_translated_to(mat4 m, vec3 v, mat4 dest); + +CGLM_EXPORT +void +glmc_translated_x(mat4 m, float x); + +CGLM_EXPORT +void +glmc_translated_y(mat4 m, float y); + +CGLM_EXPORT +void +glmc_translated_z(mat4 m, float z); + +CGLM_EXPORT +void +glmc_rotated_x(mat4 m, float angle, mat4 dest); + +CGLM_EXPORT +void +glmc_rotated_y(mat4 m, float angle, mat4 dest); + +CGLM_EXPORT +void +glmc_rotated_z(mat4 m, float angle, mat4 dest); + +CGLM_EXPORT +void +glmc_rotated(mat4 m, float angle, vec3 axis); + +CGLM_EXPORT +void +glmc_rotated_at(mat4 m, vec3 pivot, float angle, vec3 axis); + +CGLM_EXPORT +void +glmc_spinned(mat4 m, float angle, vec3 axis); + +/* affine-mat */ + +CGLM_EXPORT +void +glmc_mul(mat4 m1, mat4 m2, mat4 dest); + +CGLM_EXPORT +void +glmc_mul_rot(mat4 m1, mat4 m2, mat4 dest); + +CGLM_EXPORT +void +glmc_inv_tr(mat4 mat); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_affine_h */ diff --git a/external/cglm/call/affine2d.h b/external/cglm/call/affine2d.h new file mode 100644 index 0000000..e1b9462 --- /dev/null +++ b/external/cglm/call/affine2d.h @@ -0,0 +1,67 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_affine2d_h +#define cglmc_affine2d_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_translate2d_make(mat3 m, vec2 v); + +CGLM_EXPORT +void +glmc_translate2d_to(mat3 m, vec2 v, mat3 dest); + +CGLM_EXPORT +void +glmc_translate2d(mat3 m, vec2 v); + +CGLM_EXPORT +void +glmc_translate2d_x(mat3 m, float to); + +CGLM_EXPORT +void +glmc_translate2d_y(mat3 m, float to); + +CGLM_EXPORT +void +glmc_scale2d_to(mat3 m, vec2 v, mat3 dest); + +CGLM_EXPORT +void +glmc_scale2d_make(mat3 m, vec2 v); + +CGLM_EXPORT +void +glmc_scale2d(mat3 m, vec2 v); + +CGLM_EXPORT +void +glmc_scale2d_uni(mat3 m, float s); + +CGLM_EXPORT +void +glmc_rotate2d_make(mat3 m, float angle); + +CGLM_EXPORT +void +glmc_rotate2d(mat3 m, float angle); + +CGLM_EXPORT +void +glmc_rotate2d_to(mat3 m, float angle, mat3 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_affine2d_h */ diff --git a/external/cglm/call/bezier.h b/external/cglm/call/bezier.h new file mode 100644 index 0000000..a6a0eb4 --- /dev/null +++ b/external/cglm/call/bezier.h @@ -0,0 +1,31 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_bezier_h +#define cglmc_bezier_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +float +glmc_bezier(float s, float p0, float c0, float c1, float p1); + +CGLM_EXPORT +float +glmc_hermite(float s, float p0, float t0, float t1, float p1); + +CGLM_EXPORT +float +glmc_decasteljau(float prm, float p0, float c0, float c1, float p1); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_bezier_h */ diff --git a/external/cglm/call/box.h b/external/cglm/call/box.h new file mode 100644 index 0000000..3617eed --- /dev/null +++ b/external/cglm/call/box.h @@ -0,0 +1,78 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_box_h +#define cglmc_box_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_aabb_transform(vec3 box[2], mat4 m, vec3 dest[2]); + +CGLM_EXPORT +void +glmc_aabb_merge(vec3 box1[2], vec3 box2[2], vec3 dest[2]); + +CGLM_EXPORT +void +glmc_aabb_crop(vec3 box[2], vec3 cropBox[2], vec3 dest[2]); + +CGLM_EXPORT +void +glmc_aabb_crop_until(vec3 box[2], + vec3 cropBox[2], + vec3 clampBox[2], + vec3 dest[2]); + +CGLM_EXPORT +bool +glmc_aabb_frustum(vec3 box[2], vec4 planes[6]); + +CGLM_EXPORT +void +glmc_aabb_invalidate(vec3 box[2]); + +CGLM_EXPORT +bool +glmc_aabb_isvalid(vec3 box[2]); + +CGLM_EXPORT +float +glmc_aabb_size(vec3 box[2]); + +CGLM_EXPORT +float +glmc_aabb_radius(vec3 box[2]); + +CGLM_EXPORT +void +glmc_aabb_center(vec3 box[2], vec3 dest); + +CGLM_EXPORT +bool +glmc_aabb_aabb(vec3 box[2], vec3 other[2]); + +CGLM_EXPORT +bool +glmc_aabb_point(vec3 box[2], vec3 point); + +CGLM_EXPORT +bool +glmc_aabb_contains(vec3 box[2], vec3 other[2]); + +CGLM_EXPORT +bool +glmc_aabb_sphere(vec3 box[2], vec4 s); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_box_h */ diff --git a/external/cglm/call/cam.h b/external/cglm/call/cam.h new file mode 100644 index 0000000..d9567ec --- /dev/null +++ b/external/cglm/call/cam.h @@ -0,0 +1,133 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_cam_h +#define cglmc_cam_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_frustum(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest); + +CGLM_EXPORT +void +glmc_ortho(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb(vec3 box[2], mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb_p(vec3 box[2], float padding, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb_pz(vec3 box[2], float padding, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_default(float aspect, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_default_s(float aspect, float size, mat4 dest); + +CGLM_EXPORT +void +glmc_perspective(float fovy, float aspect, float nearZ, float farZ, mat4 dest); + +CGLM_EXPORT +void +glmc_persp_move_far(mat4 proj, float deltaFar); + +CGLM_EXPORT +void +glmc_perspective_default(float aspect, mat4 dest); + +CGLM_EXPORT +void +glmc_perspective_resize(float aspect, mat4 proj); + +CGLM_EXPORT +void +glmc_lookat(vec3 eye, vec3 center, vec3 up, mat4 dest); + +CGLM_EXPORT +void +glmc_look(vec3 eye, vec3 dir, vec3 up, mat4 dest); + +CGLM_EXPORT +void +glmc_look_anyup(vec3 eye, vec3 dir, mat4 dest); + +CGLM_EXPORT +void +glmc_persp_decomp(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ, + float * __restrict top, + float * __restrict bottom, + float * __restrict left, + float * __restrict right); + +CGLM_EXPORT +void +glmc_persp_decompv(mat4 proj, float dest[6]); + +CGLM_EXPORT +void +glmc_persp_decomp_x(mat4 proj, + float * __restrict left, + float * __restrict right); + +CGLM_EXPORT +void +glmc_persp_decomp_y(mat4 proj, + float * __restrict top, + float * __restrict bottom); + +CGLM_EXPORT +void +glmc_persp_decomp_z(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ); + +CGLM_EXPORT +void +glmc_persp_decomp_far(mat4 proj, float * __restrict farZ); + +CGLM_EXPORT +void +glmc_persp_decomp_near(mat4 proj, float * __restrict nearZ); + +CGLM_EXPORT +float +glmc_persp_fovy(mat4 proj); + +CGLM_EXPORT +float +glmc_persp_aspect(mat4 proj); + +CGLM_EXPORT +void +glmc_persp_sizes(mat4 proj, float fovy, vec4 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_cam_h */ diff --git a/external/cglm/call/clipspace/ortho_lh_no.h b/external/cglm/call/clipspace/ortho_lh_no.h new file mode 100644 index 0000000..3e26fa9 --- /dev/null +++ b/external/cglm/call/clipspace/ortho_lh_no.h @@ -0,0 +1,46 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_ortho_lh_no_h +#define cglmc_ortho_lh_no_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../cglm.h" + +CGLM_EXPORT +void +glmc_ortho_lh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb_lh_no(vec3 box[2], mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb_p_lh_no(vec3 box[2], float padding, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb_pz_lh_no(vec3 box[2], float padding, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_default_lh_no(float aspect, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_default_s_lh_no(float aspect, float size, mat4 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_ortho_lh_no_h */ diff --git a/external/cglm/call/clipspace/ortho_lh_zo.h b/external/cglm/call/clipspace/ortho_lh_zo.h new file mode 100644 index 0000000..dc4c610 --- /dev/null +++ b/external/cglm/call/clipspace/ortho_lh_zo.h @@ -0,0 +1,46 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_ortho_lh_zo_h +#define cglmc_ortho_lh_zo_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../cglm.h" + +CGLM_EXPORT +void +glmc_ortho_lh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb_lh_zo(vec3 box[2], mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb_p_lh_zo(vec3 box[2], float padding, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb_pz_lh_zo(vec3 box[2], float padding, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_default_lh_zo(float aspect, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_default_s_lh_zo(float aspect, float size, mat4 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_ortho_lh_zo_h */ diff --git a/external/cglm/call/clipspace/ortho_rh_no.h b/external/cglm/call/clipspace/ortho_rh_no.h new file mode 100644 index 0000000..dbba497 --- /dev/null +++ b/external/cglm/call/clipspace/ortho_rh_no.h @@ -0,0 +1,46 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_ortho_rh_no_h +#define cglmc_ortho_rh_no_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../cglm.h" + +CGLM_EXPORT +void +glmc_ortho_rh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb_rh_no(vec3 box[2], mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb_p_rh_no(vec3 box[2], float padding, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb_pz_rh_no(vec3 box[2], float padding, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_default_rh_no(float aspect, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_default_s_rh_no(float aspect, float size, mat4 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_ortho_rh_no_h */ diff --git a/external/cglm/call/clipspace/ortho_rh_zo.h b/external/cglm/call/clipspace/ortho_rh_zo.h new file mode 100644 index 0000000..e79ae83 --- /dev/null +++ b/external/cglm/call/clipspace/ortho_rh_zo.h @@ -0,0 +1,46 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_ortho_rh_zo_h +#define cglmc_ortho_rh_zo_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../cglm.h" + +CGLM_EXPORT +void +glmc_ortho_rh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb_rh_zo(vec3 box[2], mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb_p_rh_zo(vec3 box[2], float padding, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_aabb_pz_rh_zo(vec3 box[2], float padding, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_default_rh_zo(float aspect, mat4 dest); + +CGLM_EXPORT +void +glmc_ortho_default_s_rh_zo(float aspect, float size, mat4 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_ortho_rh_zo_h */ diff --git a/external/cglm/call/clipspace/persp_lh_no.h b/external/cglm/call/clipspace/persp_lh_no.h new file mode 100644 index 0000000..4bdbcfe --- /dev/null +++ b/external/cglm/call/clipspace/persp_lh_no.h @@ -0,0 +1,87 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_persp_lh_no_h +#define cglmc_persp_lh_no_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../cglm.h" + +CGLM_EXPORT +void +glmc_frustum_lh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest); + +CGLM_EXPORT +void +glmc_perspective_lh_no(float fovy, + float aspect, + float nearVal, + float farVal, + mat4 dest); + +CGLM_EXPORT +void +glmc_persp_move_far_lh_no(mat4 proj, float deltaFar); + +CGLM_EXPORT +void +glmc_persp_decomp_lh_no(mat4 proj, + float * __restrict nearZ, float * __restrict farZ, + float * __restrict top, float * __restrict bottom, + float * __restrict left, float * __restrict right); + +CGLM_EXPORT +void +glmc_persp_decompv_lh_no(mat4 proj, float dest[6]); + +CGLM_EXPORT +void +glmc_persp_decomp_x_lh_no(mat4 proj, + float * __restrict left, + float * __restrict right); + +CGLM_EXPORT +void +glmc_persp_decomp_y_lh_no(mat4 proj, + float * __restrict top, + float * __restrict bottom); + +CGLM_EXPORT +void +glmc_persp_decomp_z_lh_no(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ); + +CGLM_EXPORT +void +glmc_persp_decomp_far_lh_no(mat4 proj, float * __restrict farZ); + +CGLM_EXPORT +void +glmc_persp_decomp_near_lh_no(mat4 proj, float * __restrict nearZ); + +CGLM_EXPORT +void +glmc_persp_sizes_lh_no(mat4 proj, float fovy, vec4 dest); + +CGLM_EXPORT +float +glmc_persp_fovy_lh_no(mat4 proj); + +CGLM_EXPORT +float +glmc_persp_aspect_lh_no(mat4 proj); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_persp_lh_no_h */ diff --git a/external/cglm/call/clipspace/persp_lh_zo.h b/external/cglm/call/clipspace/persp_lh_zo.h new file mode 100644 index 0000000..53c2c1c --- /dev/null +++ b/external/cglm/call/clipspace/persp_lh_zo.h @@ -0,0 +1,87 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_persp_lh_zo_h +#define cglmc_persp_lh_zo_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../cglm.h" + +CGLM_EXPORT +void +glmc_frustum_lh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest); + +CGLM_EXPORT +void +glmc_perspective_lh_zo(float fovy, + float aspect, + float nearVal, + float farVal, + mat4 dest); + +CGLM_EXPORT +void +glmc_persp_move_far_lh_zo(mat4 proj, float deltaFar); + +CGLM_EXPORT +void +glmc_persp_decomp_lh_zo(mat4 proj, + float * __restrict nearZ, float * __restrict farZ, + float * __restrict top, float * __restrict bottom, + float * __restrict left, float * __restrict right); + +CGLM_EXPORT +void +glmc_persp_decompv_lh_zo(mat4 proj, float dest[6]); + +CGLM_EXPORT +void +glmc_persp_decomp_x_lh_zo(mat4 proj, + float * __restrict left, + float * __restrict right); + +CGLM_EXPORT +void +glmc_persp_decomp_y_lh_zo(mat4 proj, + float * __restrict top, + float * __restrict bottom); + +CGLM_EXPORT +void +glmc_persp_decomp_z_lh_zo(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ); + +CGLM_EXPORT +void +glmc_persp_decomp_far_lh_zo(mat4 proj, float * __restrict farZ); + +CGLM_EXPORT +void +glmc_persp_decomp_near_lh_zo(mat4 proj, float * __restrict nearZ); + +CGLM_EXPORT +void +glmc_persp_sizes_lh_zo(mat4 proj, float fovy, vec4 dest); + +CGLM_EXPORT +float +glmc_persp_fovy_lh_zo(mat4 proj); + +CGLM_EXPORT +float +glmc_persp_aspect_lh_zo(mat4 proj); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_persp_lh_zo_h */ diff --git a/external/cglm/call/clipspace/persp_rh_no.h b/external/cglm/call/clipspace/persp_rh_no.h new file mode 100644 index 0000000..9c0d65d --- /dev/null +++ b/external/cglm/call/clipspace/persp_rh_no.h @@ -0,0 +1,87 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_persp_rh_no_h +#define cglmc_persp_rh_no_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../cglm.h" + +CGLM_EXPORT +void +glmc_frustum_rh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest); + +CGLM_EXPORT +void +glmc_perspective_rh_no(float fovy, + float aspect, + float nearVal, + float farVal, + mat4 dest); + +CGLM_EXPORT +void +glmc_persp_move_far_rh_no(mat4 proj, float deltaFar); + +CGLM_EXPORT +void +glmc_persp_decomp_rh_no(mat4 proj, + float * __restrict nearZ, float * __restrict farZ, + float * __restrict top, float * __restrict bottom, + float * __restrict left, float * __restrict right); + +CGLM_EXPORT +void +glmc_persp_decompv_rh_no(mat4 proj, float dest[6]); + +CGLM_EXPORT +void +glmc_persp_decomp_x_rh_no(mat4 proj, + float * __restrict left, + float * __restrict right); + +CGLM_EXPORT +void +glmc_persp_decomp_y_rh_no(mat4 proj, + float * __restrict top, + float * __restrict bottom); + +CGLM_EXPORT +void +glmc_persp_decomp_z_rh_no(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ); + +CGLM_EXPORT +void +glmc_persp_decomp_far_rh_no(mat4 proj, float * __restrict farZ); + +CGLM_EXPORT +void +glmc_persp_decomp_near_rh_no(mat4 proj, float * __restrict nearZ); + +CGLM_EXPORT +void +glmc_persp_sizes_rh_no(mat4 proj, float fovy, vec4 dest); + +CGLM_EXPORT +float +glmc_persp_fovy_rh_no(mat4 proj); + +CGLM_EXPORT +float +glmc_persp_aspect_rh_no(mat4 proj); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_persp_rh_no_h */ diff --git a/external/cglm/call/clipspace/persp_rh_zo.h b/external/cglm/call/clipspace/persp_rh_zo.h new file mode 100644 index 0000000..718d4ad --- /dev/null +++ b/external/cglm/call/clipspace/persp_rh_zo.h @@ -0,0 +1,87 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_persp_rh_zo_h +#define cglmc_persp_rh_zo_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../cglm.h" + +CGLM_EXPORT +void +glmc_frustum_rh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest); + +CGLM_EXPORT +void +glmc_perspective_rh_zo(float fovy, + float aspect, + float nearVal, + float farVal, + mat4 dest); + +CGLM_EXPORT +void +glmc_persp_move_far_rh_zo(mat4 proj, float deltaFar); + +CGLM_EXPORT +void +glmc_persp_decomp_rh_zo(mat4 proj, + float * __restrict nearZ, float * __restrict farZ, + float * __restrict top, float * __restrict bottom, + float * __restrict left, float * __restrict right); + +CGLM_EXPORT +void +glmc_persp_decompv_rh_zo(mat4 proj, float dest[6]); + +CGLM_EXPORT +void +glmc_persp_decomp_x_rh_zo(mat4 proj, + float * __restrict left, + float * __restrict right); + +CGLM_EXPORT +void +glmc_persp_decomp_y_rh_zo(mat4 proj, + float * __restrict top, + float * __restrict bottom); + +CGLM_EXPORT +void +glmc_persp_decomp_z_rh_zo(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ); + +CGLM_EXPORT +void +glmc_persp_decomp_far_rh_zo(mat4 proj, float * __restrict farZ); + +CGLM_EXPORT +void +glmc_persp_decomp_near_rh_zo(mat4 proj, float * __restrict nearZ); + +CGLM_EXPORT +void +glmc_persp_sizes_rh_zo(mat4 proj, float fovy, vec4 dest); + +CGLM_EXPORT +float +glmc_persp_fovy_rh_zo(mat4 proj); + +CGLM_EXPORT +float +glmc_persp_aspect_rh_zo(mat4 proj); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_persp_rh_zo_h */ diff --git a/external/cglm/call/clipspace/project_no.h b/external/cglm/call/clipspace/project_no.h new file mode 100644 index 0000000..3cba860 --- /dev/null +++ b/external/cglm/call/clipspace/project_no.h @@ -0,0 +1,31 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_project_no_h +#define cglmc_project_no_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../cglm.h" + +CGLM_EXPORT +void +glmc_unprojecti_no(vec3 pos, mat4 invMat, vec4 vp, vec3 dest); + +CGLM_EXPORT +void +glmc_project_no(vec3 pos, mat4 m, vec4 vp, vec3 dest); + +CGLM_EXPORT +float +glmc_project_z_no(vec3 pos, mat4 m); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_project_no_h */ diff --git a/external/cglm/call/clipspace/project_zo.h b/external/cglm/call/clipspace/project_zo.h new file mode 100644 index 0000000..d2a6c62 --- /dev/null +++ b/external/cglm/call/clipspace/project_zo.h @@ -0,0 +1,31 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_project_zo_h +#define cglmc_project_zo_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../cglm.h" + +CGLM_EXPORT +void +glmc_unprojecti_zo(vec3 pos, mat4 invMat, vec4 vp, vec3 dest); + +CGLM_EXPORT +void +glmc_project_zo(vec3 pos, mat4 m, vec4 vp, vec3 dest); + +CGLM_EXPORT +float +glmc_project_z_zo(vec3 pos, mat4 m); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_project_zo_h */ diff --git a/external/cglm/call/clipspace/view_lh_no.h b/external/cglm/call/clipspace/view_lh_no.h new file mode 100644 index 0000000..3b58c84 --- /dev/null +++ b/external/cglm/call/clipspace/view_lh_no.h @@ -0,0 +1,31 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_view_lh_no_h +#define cglmc_view_lh_no_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../cglm.h" + +CGLM_EXPORT +void +glmc_lookat_lh_no(vec3 eye, vec3 center, vec3 up, mat4 dest); + +CGLM_EXPORT +void +glmc_look_lh_no(vec3 eye, vec3 dir, vec3 up, mat4 dest); + +CGLM_EXPORT +void +glmc_look_anyup_lh_no(vec3 eye, vec3 dir, mat4 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_view_lh_no_h */ diff --git a/external/cglm/call/clipspace/view_lh_zo.h b/external/cglm/call/clipspace/view_lh_zo.h new file mode 100644 index 0000000..c877367 --- /dev/null +++ b/external/cglm/call/clipspace/view_lh_zo.h @@ -0,0 +1,31 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_view_lh_zo_h +#define cglmc_view_lh_zo_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../cglm.h" + +CGLM_EXPORT +void +glmc_lookat_lh_zo(vec3 eye, vec3 center, vec3 up, mat4 dest); + +CGLM_EXPORT +void +glmc_look_lh_zo(vec3 eye, vec3 dir, vec3 up, mat4 dest); + +CGLM_EXPORT +void +glmc_look_anyup_lh_zo(vec3 eye, vec3 dir, mat4 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_view_lh_zo_h */ diff --git a/external/cglm/call/clipspace/view_rh_no.h b/external/cglm/call/clipspace/view_rh_no.h new file mode 100644 index 0000000..6303dbf --- /dev/null +++ b/external/cglm/call/clipspace/view_rh_no.h @@ -0,0 +1,31 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_view_rh_no_h +#define cglmc_view_rh_no_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../cglm.h" + +CGLM_EXPORT +void +glmc_lookat_rh_no(vec3 eye, vec3 center, vec3 up, mat4 dest); + +CGLM_EXPORT +void +glmc_look_rh_no(vec3 eye, vec3 dir, vec3 up, mat4 dest); + +CGLM_EXPORT +void +glmc_look_anyup_rh_no(vec3 eye, vec3 dir, mat4 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_view_rh_no_h */ diff --git a/external/cglm/call/clipspace/view_rh_zo.h b/external/cglm/call/clipspace/view_rh_zo.h new file mode 100644 index 0000000..00b8707 --- /dev/null +++ b/external/cglm/call/clipspace/view_rh_zo.h @@ -0,0 +1,31 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_view_rh_zo_h +#define cglmc_view_rh_zo_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../cglm.h" + +CGLM_EXPORT +void +glmc_lookat_rh_zo(vec3 eye, vec3 center, vec3 up, mat4 dest); + +CGLM_EXPORT +void +glmc_look_rh_zo(vec3 eye, vec3 dir, vec3 up, mat4 dest); + +CGLM_EXPORT +void +glmc_look_anyup_rh_zo(vec3 eye, vec3 dir, mat4 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_view_rh_zo_h */ diff --git a/external/cglm/call/curve.h b/external/cglm/call/curve.h new file mode 100644 index 0000000..061fdb9 --- /dev/null +++ b/external/cglm/call/curve.h @@ -0,0 +1,23 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_curve_h +#define cglmc_curve_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +float +glmc_smc(float s, mat4 m, vec4 c); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_curve_h */ diff --git a/external/cglm/call/ease.h b/external/cglm/call/ease.h new file mode 100644 index 0000000..87e39ca --- /dev/null +++ b/external/cglm/call/ease.h @@ -0,0 +1,143 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_ease_h +#define cglmc_ease_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +float +glmc_ease_linear(float t); + +CGLM_EXPORT +float +glmc_ease_sine_in(float t); + +CGLM_EXPORT +float +glmc_ease_sine_out(float t); + +CGLM_EXPORT +float +glmc_ease_sine_inout(float t); + +CGLM_EXPORT +float +glmc_ease_quad_in(float t); + +CGLM_EXPORT +float +glmc_ease_quad_out(float t); + +CGLM_EXPORT +float +glmc_ease_quad_inout(float t); + +CGLM_EXPORT +float +glmc_ease_cubic_in(float t); + +CGLM_EXPORT +float +glmc_ease_cubic_out(float t); + +CGLM_EXPORT +float +glmc_ease_cubic_inout(float t); + +CGLM_EXPORT +float +glmc_ease_quart_in(float t); + +CGLM_EXPORT +float +glmc_ease_quart_out(float t); + +CGLM_EXPORT +float +glmc_ease_quart_inout(float t); + +CGLM_EXPORT +float +glmc_ease_quint_in(float t); + +CGLM_EXPORT +float +glmc_ease_quint_out(float t); + +CGLM_EXPORT +float +glmc_ease_quint_inout(float t); + +CGLM_EXPORT +float +glmc_ease_exp_in(float t); + +CGLM_EXPORT +float +glmc_ease_exp_out(float t); + +CGLM_EXPORT +float +glmc_ease_exp_inout(float t); + +CGLM_EXPORT +float +glmc_ease_circ_in(float t); + +CGLM_EXPORT +float +glmc_ease_circ_out(float t); + +CGLM_EXPORT +float +glmc_ease_circ_inout(float t); + +CGLM_EXPORT +float +glmc_ease_back_in(float t); + +CGLM_EXPORT +float +glmc_ease_back_out(float t); + +CGLM_EXPORT +float +glmc_ease_back_inout(float t); + +CGLM_EXPORT +float +glmc_ease_elast_in(float t); + +CGLM_EXPORT +float +glmc_ease_elast_out(float t); + +CGLM_EXPORT +float +glmc_ease_elast_inout(float t); + +CGLM_EXPORT +float +glmc_ease_bounce_out(float t); + +CGLM_EXPORT +float +glmc_ease_bounce_in(float t); + +CGLM_EXPORT +float +glmc_ease_bounce_inout(float t); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_ease_h */ diff --git a/external/cglm/call/euler.h b/external/cglm/call/euler.h new file mode 100644 index 0000000..182bcbb --- /dev/null +++ b/external/cglm/call/euler.h @@ -0,0 +1,80 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_euler_h +#define cglmc_euler_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_euler_angles(mat4 m, vec3 dest); + +CGLM_EXPORT +void +glmc_euler(vec3 angles, mat4 dest); + +CGLM_EXPORT +void +glmc_euler_xyz(vec3 angles, mat4 dest); + +CGLM_EXPORT +void +glmc_euler_zyx(vec3 angles, mat4 dest); + +CGLM_EXPORT +void +glmc_euler_zxy(vec3 angles, mat4 dest); + +CGLM_EXPORT +void +glmc_euler_xzy(vec3 angles, mat4 dest); + +CGLM_EXPORT +void +glmc_euler_yzx(vec3 angles, mat4 dest); + +CGLM_EXPORT +void +glmc_euler_yxz(vec3 angles, mat4 dest); + +CGLM_EXPORT +void +glmc_euler_by_order(vec3 angles, glm_euler_seq axis, mat4 dest); + +CGLM_EXPORT +void +glmc_euler_xyz_quat(vec3 angles, versor dest); + +CGLM_EXPORT +void +glmc_euler_xzy_quat(vec3 angles, versor dest); + +CGLM_EXPORT +void +glmc_euler_yxz_quat(vec3 angles, versor dest); + +CGLM_EXPORT +void +glmc_euler_yzx_quat(vec3 angles, versor dest); + +CGLM_EXPORT +void +glmc_euler_zxy_quat(vec3 angles, versor dest); + +CGLM_EXPORT +void +glmc_euler_zyx_quat(vec3 angles, versor dest); + + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_euler_h */ diff --git a/external/cglm/call/frustum.h b/external/cglm/call/frustum.h new file mode 100644 index 0000000..6b4facb --- /dev/null +++ b/external/cglm/call/frustum.h @@ -0,0 +1,41 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_frustum_h +#define cglmc_frustum_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_frustum_planes(mat4 m, vec4 dest[6]); + +CGLM_EXPORT +void +glmc_frustum_corners(mat4 invMat, vec4 dest[8]); + +CGLM_EXPORT +void +glmc_frustum_center(vec4 corners[8], vec4 dest); + +CGLM_EXPORT +void +glmc_frustum_box(vec4 corners[8], mat4 m, vec3 box[2]); + +CGLM_EXPORT +void +glmc_frustum_corners_at(vec4 corners[8], + float splitDist, + float farDist, + vec4 planeCorners[4]); +#ifdef __cplusplus +} +#endif +#endif /* cglmc_frustum_h */ diff --git a/external/cglm/call/io.h b/external/cglm/call/io.h new file mode 100644 index 0000000..19ea06f --- /dev/null +++ b/external/cglm/call/io.h @@ -0,0 +1,45 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_io_h +#define cglmc_io_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_mat4_print(mat4 matrix, + FILE * __restrict ostream); + +CGLM_EXPORT +void +glmc_mat3_print(mat3 matrix, + FILE * __restrict ostream); + +CGLM_EXPORT +void +glmc_vec4_print(vec4 vec, + FILE * __restrict ostream); + +CGLM_EXPORT +void +glmc_vec3_print(vec3 vec, + FILE * __restrict ostream); + +CGLM_EXPORT +void +glmc_versor_print(versor vec, + FILE * __restrict ostream); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_io_h */ diff --git a/external/cglm/call/ivec2.h b/external/cglm/call/ivec2.h new file mode 100644 index 0000000..82f70eb --- /dev/null +++ b/external/cglm/call/ivec2.h @@ -0,0 +1,179 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_ivec2_h +#define cglmc_ivec2_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_ivec2(int * __restrict v, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_copy(ivec2 a, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_zero(ivec2 v); + +CGLM_EXPORT +void +glmc_ivec2_one(ivec2 v); + +CGLM_EXPORT +int +glmc_ivec2_dot(ivec2 a, ivec2 b); + +CGLM_EXPORT +int +glmc_ivec2_cross(ivec2 a, ivec2 b); + +CGLM_EXPORT +void +glmc_ivec2_add(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_adds(ivec2 v, int s, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_sub(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_subs(ivec2 v, int s, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_mul(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_scale(ivec2 v, int s, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_div(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_divs(ivec2 v, int s, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_mod(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_addadd(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_addadds(ivec2 a, int s, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_subadd(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_subadds(ivec2 a, int s, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_muladd(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_muladds(ivec2 a, int s, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_maxadd(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_minadd(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_subsub(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_subsubs(ivec2 a, int s, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_addsub(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_addsubs(ivec2 a, int s, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_mulsub(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_mulsubs(ivec2 a, int s, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_maxsub(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_minsub(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +int +glmc_ivec2_distance2(ivec2 a, ivec2 b); + +CGLM_EXPORT +float +glmc_ivec2_distance(ivec2 a, ivec2 b); + +CGLM_EXPORT +void +glmc_ivec2_fill(ivec2 v, int val); + +CGLM_EXPORT +bool +glmc_ivec2_eq(ivec2 v, int val); + +CGLM_EXPORT +bool +glmc_ivec2_eqv(ivec2 a, ivec2 b); + +CGLM_EXPORT +void +glmc_ivec2_maxv(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_minv(ivec2 a, ivec2 b, ivec2 dest); + +CGLM_EXPORT +void +glmc_ivec2_clamp(ivec2 v, int minVal, int maxVal); + +CGLM_EXPORT +void +glmc_ivec2_abs(ivec2 v, ivec2 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_ivec2_h */ diff --git a/external/cglm/call/ivec3.h b/external/cglm/call/ivec3.h new file mode 100644 index 0000000..a6cec53 --- /dev/null +++ b/external/cglm/call/ivec3.h @@ -0,0 +1,183 @@ +/* + * Copyright (c);, Recep Aslantas. + * + * MIT License (MIT);, http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_ivec3_h +#define cglmc_ivec3_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_ivec3(ivec4 v4, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_copy(ivec3 a, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_zero(ivec3 v); + +CGLM_EXPORT +void +glmc_ivec3_one(ivec3 v); + +CGLM_EXPORT +int +glmc_ivec3_dot(ivec3 a, ivec3 b); + +CGLM_EXPORT +int +glmc_ivec3_norm2(ivec3 v); + +CGLM_EXPORT +int +glmc_ivec3_norm(ivec3 v); + +CGLM_EXPORT +void +glmc_ivec3_add(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_adds(ivec3 v, int s, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_sub(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_subs(ivec3 v, int s, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_mul(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_scale(ivec3 v, int s, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_div(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_divs(ivec3 v, int s, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_mod(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_addadd(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_addadds(ivec3 a, int s, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_subadd(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_subadds(ivec3 a, int s, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_muladd(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_muladds(ivec3 a, int s, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_maxadd(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_minadd(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_subsub(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_subsubs(ivec3 a, int s, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_addsub(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_addsubs(ivec3 a, int s, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_mulsub(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_mulsubs(ivec3 a, int s, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_maxsub(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_minsub(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +int +glmc_ivec3_distance2(ivec3 a, ivec3 b); + +CGLM_EXPORT +float +glmc_ivec3_distance(ivec3 a, ivec3 b); + +CGLM_EXPORT +void +glmc_ivec3_fill(ivec3 v, int val); + +CGLM_EXPORT +bool +glmc_ivec3_eq(ivec3 v, int val); + +CGLM_EXPORT +bool +glmc_ivec3_eqv(ivec3 a, ivec3 b); + +CGLM_EXPORT +void +glmc_ivec3_maxv(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_minv(ivec3 a, ivec3 b, ivec3 dest); + +CGLM_EXPORT +void +glmc_ivec3_clamp(ivec3 v, int minVal, int maxVal); + +CGLM_EXPORT +void +glmc_ivec3_abs(ivec3 v, ivec3 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_ivec3_h */ diff --git a/external/cglm/call/ivec4.h b/external/cglm/call/ivec4.h new file mode 100644 index 0000000..0e6d721 --- /dev/null +++ b/external/cglm/call/ivec4.h @@ -0,0 +1,147 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_ivec4_h +#define cglmc_ivec4_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_ivec4(ivec3 v3, int last, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_copy(ivec4 a, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_zero(ivec4 v); + +CGLM_EXPORT +void +glmc_ivec4_one(ivec4 v); + +CGLM_EXPORT +void +glmc_ivec4_add(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_adds(ivec4 v, int s, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_sub(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_subs(ivec4 v, int s, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_mul(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_scale(ivec4 v, int s, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_addadd(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_addadds(ivec4 a, int s, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_subadd(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_subadds(ivec4 a, int s, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_muladd(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_muladds(ivec4 a, int s, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_maxadd(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_minadd(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_subsub(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_subsubs(ivec4 a, int s, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_addsub(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_addsubs(ivec4 a, int s, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_mulsub(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_mulsubs(ivec4 a, int s, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_maxsub(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_minsub(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +int +glmc_ivec4_distance2(ivec4 a, ivec4 b); + +CGLM_EXPORT +float +glmc_ivec4_distance(ivec4 a, ivec4 b); + +CGLM_EXPORT +void +glmc_ivec4_maxv(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_minv(ivec4 a, ivec4 b, ivec4 dest); + +CGLM_EXPORT +void +glmc_ivec4_clamp(ivec4 v, int minVal, int maxVal); + +CGLM_EXPORT +void +glmc_ivec4_abs(ivec4 v, ivec4 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_ivec4_h */ diff --git a/external/cglm/call/mat2.h b/external/cglm/call/mat2.h new file mode 100644 index 0000000..c268938 --- /dev/null +++ b/external/cglm/call/mat2.h @@ -0,0 +1,83 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_mat2_h +#define cglmc_mat2_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_mat2_make(const float * __restrict src, mat2 dest); + +CGLM_EXPORT +void +glmc_mat2_copy(mat2 mat, mat2 dest); + +CGLM_EXPORT +void +glmc_mat2_identity(mat2 m); + +CGLM_EXPORT +void +glmc_mat2_identity_array(mat2 * __restrict mats, size_t count); + +CGLM_EXPORT +void +glmc_mat2_zero(mat2 m); + +CGLM_EXPORT +void +glmc_mat2_mul(mat2 m1, mat2 m2, mat2 dest); + +CGLM_EXPORT +void +glmc_mat2_mulv(mat2 m, vec2 v, vec2 dest); + +CGLM_EXPORT +void +glmc_mat2_transpose_to(mat2 mat, mat2 dest); + +CGLM_EXPORT +void +glmc_mat2_transpose(mat2 m); + +CGLM_EXPORT +void +glmc_mat2_scale(mat2 m, float s); + +CGLM_EXPORT +void +glmc_mat2_inv(mat2 mat, mat2 dest); + +CGLM_EXPORT +void +glmc_mat2_swap_col(mat2 mat, int col1, int col2); + +CGLM_EXPORT +void +glmc_mat2_swap_row(mat2 mat, int row1, int row2); + +CGLM_EXPORT +float +glmc_mat2_trace(mat2 m); + +CGLM_EXPORT +float +glmc_mat2_det(mat2 m); + +CGLM_EXPORT +float +glmc_mat2_rmc(vec2 r, mat2 m, vec2 c); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_mat2_h */ diff --git a/external/cglm/call/mat2x3.h b/external/cglm/call/mat2x3.h new file mode 100644 index 0000000..215d9a4 --- /dev/null +++ b/external/cglm/call/mat2x3.h @@ -0,0 +1,47 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_mat2x3_h +#define cglmc_mat2x3_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_mat2x3_copy(mat2x3 src, mat2x3 dest); + +CGLM_EXPORT +void +glmc_mat2x3_zero(mat2x3 m); + +CGLM_EXPORT +void +glmc_mat2x3_make(const float * __restrict src, mat2x3 dest); + +CGLM_EXPORT +void +glmc_mat2x3_mul(mat2x3 m1, mat3x2 m2, mat3 dest); + +CGLM_EXPORT +void +glmc_mat2x3_mulv(mat2x3 m, vec2 v, vec3 dest); + +CGLM_EXPORT +void +glmc_mat2x3_transpose(mat2x3 src, mat3x2 dest); + +CGLM_EXPORT +void +glmc_mat2x3_scale(mat2x3 m, float s); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_mat2x3_h */ diff --git a/external/cglm/call/mat2x4.h b/external/cglm/call/mat2x4.h new file mode 100644 index 0000000..e2775a4 --- /dev/null +++ b/external/cglm/call/mat2x4.h @@ -0,0 +1,47 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_mat2x4_h +#define cglmc_mat2x4_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_mat2x4_copy(mat2x4 src, mat2x4 dest); + +CGLM_EXPORT +void +glmc_mat2x4_zero(mat2x4 m); + +CGLM_EXPORT +void +glmc_mat2x4_make(const float * __restrict src, mat2x4 dest); + +CGLM_EXPORT +void +glmc_mat2x4_mul(mat2x4 m1, mat4x2 m2, mat4 dest); + +CGLM_EXPORT +void +glmc_mat2x4_mulv(mat2x4 m, vec2 v, vec4 dest); + +CGLM_EXPORT +void +glmc_mat2x4_transpose(mat2x4 src, mat4x2 dest); + +CGLM_EXPORT +void +glmc_mat2x4_scale(mat2x4 m, float s); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_mat2x4_h */ diff --git a/external/cglm/call/mat3.h b/external/cglm/call/mat3.h new file mode 100644 index 0000000..47820f9 --- /dev/null +++ b/external/cglm/call/mat3.h @@ -0,0 +1,94 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_mat3_h +#define cglmc_mat3_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +/* DEPRECATED! use _copy, _ucopy versions */ +#define glmc_mat3_dup(mat, dest) glmc_mat3_copy(mat, dest) + +CGLM_EXPORT +void +glmc_mat3_copy(mat3 mat, mat3 dest); + +CGLM_EXPORT +void +glmc_mat3_identity(mat3 mat); + +CGLM_EXPORT +void +glmc_mat3_zero(mat3 mat); + +CGLM_EXPORT +void +glmc_mat3_identity_array(mat3 * __restrict mat, size_t count); + +CGLM_EXPORT +void +glmc_mat3_mul(mat3 m1, mat3 m2, mat3 dest); + +CGLM_EXPORT +void +glmc_mat3_transpose_to(mat3 m, mat3 dest); + +CGLM_EXPORT +void +glmc_mat3_transpose(mat3 m); + +CGLM_EXPORT +void +glmc_mat3_mulv(mat3 m, vec3 v, vec3 dest); + +CGLM_EXPORT +float +glmc_mat3_trace(mat3 m); + +CGLM_EXPORT +void +glmc_mat3_quat(mat3 m, versor dest); + +CGLM_EXPORT +void +glmc_mat3_scale(mat3 m, float s); + +CGLM_EXPORT +float +glmc_mat3_det(mat3 mat); + +CGLM_EXPORT +void +glmc_mat3_inv(mat3 mat, mat3 dest); + +CGLM_EXPORT +void +glmc_mat3_swap_col(mat3 mat, int col1, int col2); + +CGLM_EXPORT +void +glmc_mat3_swap_row(mat3 mat, int row1, int row2); + +CGLM_EXPORT +float +glmc_mat3_rmc(vec3 r, mat3 m, vec3 c); + +CGLM_EXPORT +void +glmc_mat3_make(const float * __restrict src, mat3 dest); + +CGLM_EXPORT +void +glmc_mat3_textrans(float sx, float sy, float rot, float tx, float ty, mat3 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_mat3_h */ diff --git a/external/cglm/call/mat3x2.h b/external/cglm/call/mat3x2.h new file mode 100644 index 0000000..246a269 --- /dev/null +++ b/external/cglm/call/mat3x2.h @@ -0,0 +1,47 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_mat3x2_h +#define cglmc_mat3x2_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_mat3x2_copy(mat3x2 src, mat3x2 dest); + +CGLM_EXPORT +void +glmc_mat3x2_zero(mat3x2 m); + +CGLM_EXPORT +void +glmc_mat3x2_make(const float * __restrict src, mat3x2 dest); + +CGLM_EXPORT +void +glmc_mat3x2_mul(mat3x2 m1, mat2x3 m2, mat2 dest); + +CGLM_EXPORT +void +glmc_mat3x2_mulv(mat3x2 m, vec3 v, vec2 dest); + +CGLM_EXPORT +void +glmc_mat3x2_transpose(mat3x2 src, mat2x3 dest); + +CGLM_EXPORT +void +glmc_mat3x2_scale(mat3x2 m, float s); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_mat3x2_h */ diff --git a/external/cglm/call/mat3x4.h b/external/cglm/call/mat3x4.h new file mode 100644 index 0000000..5ead2f4 --- /dev/null +++ b/external/cglm/call/mat3x4.h @@ -0,0 +1,47 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_mat3x4_h +#define cglmc_mat3x4_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_mat3x4_copy(mat3x4 src, mat3x4 dest); + +CGLM_EXPORT +void +glmc_mat3x4_zero(mat3x4 m); + +CGLM_EXPORT +void +glmc_mat3x4_make(const float * __restrict src, mat3x4 dest); + +CGLM_EXPORT +void +glmc_mat3x4_mul(mat3x4 m1, mat4x3 m2, mat4 dest); + +CGLM_EXPORT +void +glmc_mat3x4_mulv(mat3x4 m, vec3 v, vec4 dest); + +CGLM_EXPORT +void +glmc_mat3x4_transpose(mat3x4 src, mat4x3 dest); + +CGLM_EXPORT +void +glmc_mat3x4_scale(mat3x4 m, float s); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_mat3x4_h */ diff --git a/external/cglm/call/mat4.h b/external/cglm/call/mat4.h new file mode 100644 index 0000000..f8cd70a --- /dev/null +++ b/external/cglm/call/mat4.h @@ -0,0 +1,135 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_mat_h +#define cglmc_mat_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +/* DEPRECATED! use _copy, _ucopy versions */ +#define glmc_mat4_udup(mat, dest) glmc_mat4_ucopy(mat, dest) +#define glmc_mat4_dup(mat, dest) glmc_mat4_copy(mat, dest) + +CGLM_EXPORT +void +glmc_mat4_ucopy(mat4 mat, mat4 dest); + +CGLM_EXPORT +void +glmc_mat4_copy(mat4 mat, mat4 dest); + +CGLM_EXPORT +void +glmc_mat4_identity(mat4 mat); + +CGLM_EXPORT +void +glmc_mat4_identity_array(mat4 * __restrict mat, size_t count); + +CGLM_EXPORT +void +glmc_mat4_zero(mat4 mat); + +CGLM_EXPORT +void +glmc_mat4_pick3(mat4 mat, mat3 dest); + +CGLM_EXPORT +void +glmc_mat4_pick3t(mat4 mat, mat3 dest); + +CGLM_EXPORT +void +glmc_mat4_ins3(mat3 mat, mat4 dest); + +CGLM_EXPORT +void +glmc_mat4_mul(mat4 m1, mat4 m2, mat4 dest); + +CGLM_EXPORT +void +glmc_mat4_mulN(mat4 * __restrict matrices[], uint32_t len, mat4 dest); + +CGLM_EXPORT +void +glmc_mat4_mulv(mat4 m, vec4 v, vec4 dest); + +CGLM_EXPORT +void +glmc_mat4_mulv3(mat4 m, vec3 v, float last, vec3 dest); + +CGLM_EXPORT +float +glmc_mat4_trace(mat4 m); + +CGLM_EXPORT +float +glmc_mat4_trace3(mat4 m); + +CGLM_EXPORT +void +glmc_mat4_quat(mat4 m, versor dest); + +CGLM_EXPORT +void +glmc_mat4_transpose_to(mat4 m, mat4 dest); + +CGLM_EXPORT +void +glmc_mat4_transpose(mat4 m); + +CGLM_EXPORT +void +glmc_mat4_scale_p(mat4 m, float s); + +CGLM_EXPORT +void +glmc_mat4_scale(mat4 m, float s); + +CGLM_EXPORT +float +glmc_mat4_det(mat4 mat); + +CGLM_EXPORT +void +glmc_mat4_inv(mat4 mat, mat4 dest); + +CGLM_EXPORT +void +glmc_mat4_inv_precise(mat4 mat, mat4 dest); + +CGLM_EXPORT +void +glmc_mat4_inv_fast(mat4 mat, mat4 dest); + +CGLM_EXPORT +void +glmc_mat4_swap_col(mat4 mat, int col1, int col2); + +CGLM_EXPORT +void +glmc_mat4_swap_row(mat4 mat, int row1, int row2); + +CGLM_EXPORT +float +glmc_mat4_rmc(vec4 r, mat4 m, vec4 c); + +CGLM_EXPORT +void +glmc_mat4_make(const float * __restrict src, mat4 dest); + +CGLM_EXPORT +void +glmc_mat4_textrans(float sx, float sy, float rot, float tx, float ty, mat4 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_mat_h */ diff --git a/external/cglm/call/mat4x2.h b/external/cglm/call/mat4x2.h new file mode 100644 index 0000000..4711d2b --- /dev/null +++ b/external/cglm/call/mat4x2.h @@ -0,0 +1,47 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_mat4x2_h +#define cglmc_mat4x2_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_mat4x2_copy(mat4x2 src, mat4x2 dest); + +CGLM_EXPORT +void +glmc_mat4x2_zero(mat4x2 m); + +CGLM_EXPORT +void +glmc_mat4x2_make(const float * __restrict src, mat4x2 dest); + +CGLM_EXPORT +void +glmc_mat4x2_mul(mat4x2 m1, mat2x4 m2, mat2 dest); + +CGLM_EXPORT +void +glmc_mat4x2_mulv(mat4x2 m, vec4 v, vec2 dest); + +CGLM_EXPORT +void +glmc_mat4x2_transpose(mat4x2 src, mat2x4 dest); + +CGLM_EXPORT +void +glmc_mat4x2_scale(mat4x2 m, float s); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_mat4x2_h */ diff --git a/external/cglm/call/mat4x3.h b/external/cglm/call/mat4x3.h new file mode 100644 index 0000000..e06e102 --- /dev/null +++ b/external/cglm/call/mat4x3.h @@ -0,0 +1,47 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_mat4x3_h +#define cglmc_mat4x3_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_mat4x3_copy(mat4x3 src, mat4x3 dest); + +CGLM_EXPORT +void +glmc_mat4x3_zero(mat4x3 m); + +CGLM_EXPORT +void +glmc_mat4x3_make(const float * __restrict src, mat4x3 dest); + +CGLM_EXPORT +void +glmc_mat4x3_mul(mat4x3 m1, mat3x4 m2, mat3 dest); + +CGLM_EXPORT +void +glmc_mat4x3_mulv(mat4x3 m, vec4 v, vec3 dest); + +CGLM_EXPORT +void +glmc_mat4x3_transpose(mat4x3 src, mat3x4 dest); + +CGLM_EXPORT +void +glmc_mat4x3_scale(mat4x3 m, float s); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_mat4x3_h */ diff --git a/external/cglm/call/noise.h b/external/cglm/call/noise.h new file mode 100644 index 0000000..6020c89 --- /dev/null +++ b/external/cglm/call/noise.h @@ -0,0 +1,31 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_noise_h +#define cglmc_noise_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +float +glmc_perlin_vec4(vec4 point); + +CGLM_EXPORT +float +glmc_perlin_vec3(vec3 point); + +CGLM_EXPORT +float +glmc_perlin_vec2(vec2 point); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_noise_h */ diff --git a/external/cglm/call/plane.h b/external/cglm/call/plane.h new file mode 100644 index 0000000..f991121 --- /dev/null +++ b/external/cglm/call/plane.h @@ -0,0 +1,23 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_plane_h +#define cglmc_plane_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_plane_normalize(vec4 plane); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_plane_h */ diff --git a/external/cglm/call/project.h b/external/cglm/call/project.h new file mode 100644 index 0000000..8fa7172 --- /dev/null +++ b/external/cglm/call/project.h @@ -0,0 +1,39 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_project_h +#define cglmc_project_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_unprojecti(vec3 pos, mat4 invMat, vec4 vp, vec3 dest); + +CGLM_EXPORT +void +glmc_unproject(vec3 pos, mat4 m, vec4 vp, vec3 dest); + +CGLM_EXPORT +void +glmc_project(vec3 pos, mat4 m, vec4 vp, vec3 dest); + +CGLM_EXPORT +float +glmc_project_z(vec3 pos, mat4 m); + +CGLM_EXPORT +void +glmc_pickmatrix(vec2 center, vec2 size, vec4 vp, mat4 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_project_h */ diff --git a/external/cglm/call/quat.h b/external/cglm/call/quat.h new file mode 100644 index 0000000..4244d36 --- /dev/null +++ b/external/cglm/call/quat.h @@ -0,0 +1,175 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_quat_h +#define cglmc_quat_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_quat_identity(versor q); + +CGLM_EXPORT +void +glmc_quat_identity_array(versor * __restrict q, size_t count); + +CGLM_EXPORT +void +glmc_quat_init(versor q, float x, float y, float z, float w); + +CGLM_EXPORT +void +glmc_quat(versor q, float angle, float x, float y, float z); + +CGLM_EXPORT +void +glmc_quatv(versor q, float angle, vec3 axis); + +CGLM_EXPORT +void +glmc_quat_copy(versor q, versor dest); + +CGLM_EXPORT +void +glmc_quat_from_vecs(vec3 a, vec3 b, versor dest); + +CGLM_EXPORT +float +glmc_quat_norm(versor q); + +CGLM_EXPORT +void +glmc_quat_normalize_to(versor q, versor dest); + +CGLM_EXPORT +void +glmc_quat_normalize(versor q); + +CGLM_EXPORT +float +glmc_quat_dot(versor p, versor q); + +CGLM_EXPORT +void +glmc_quat_conjugate(versor q, versor dest); + +CGLM_EXPORT +void +glmc_quat_inv(versor q, versor dest); + +CGLM_EXPORT +void +glmc_quat_add(versor p, versor q, versor dest); + +CGLM_EXPORT +void +glmc_quat_sub(versor p, versor q, versor dest); + +CGLM_EXPORT +float +glmc_quat_real(versor q); + +CGLM_EXPORT +void +glmc_quat_imag(versor q, vec3 dest); + +CGLM_EXPORT +void +glmc_quat_imagn(versor q, vec3 dest); + +CGLM_EXPORT +float +glmc_quat_imaglen(versor q); + +CGLM_EXPORT +float +glmc_quat_angle(versor q); + +CGLM_EXPORT +void +glmc_quat_axis(versor q, vec3 dest); + +CGLM_EXPORT +void +glmc_quat_mul(versor p, versor q, versor dest); + +CGLM_EXPORT +void +glmc_quat_mat4(versor q, mat4 dest); + +CGLM_EXPORT +void +glmc_quat_mat4t(versor q, mat4 dest); + +CGLM_EXPORT +void +glmc_quat_mat3(versor q, mat3 dest); + +CGLM_EXPORT +void +glmc_quat_mat3t(versor q, mat3 dest); + +CGLM_EXPORT +void +glmc_quat_lerp(versor from, versor to, float t, versor dest); + +CGLM_EXPORT +void +glmc_quat_lerpc(versor from, versor to, float t, versor dest); + +CGLM_EXPORT +void +glmc_quat_nlerp(versor q, versor r, float t, versor dest); + +CGLM_EXPORT +void +glmc_quat_slerp(versor q, versor r, float t, versor dest); + +CGLM_EXPORT +void +glmc_quat_slerp_longest(versor q, versor r, float t, versor dest); + +CGLM_EXPORT +void +glmc_quat_look(vec3 eye, versor ori, mat4 dest); + +CGLM_EXPORT +void +glmc_quat_for(vec3 dir, vec3 up, versor dest); + +CGLM_EXPORT +void +glmc_quat_forp(vec3 from, vec3 to, vec3 up, versor dest); + +CGLM_EXPORT +void +glmc_quat_rotatev(versor from, vec3 to, vec3 dest); + +CGLM_EXPORT +void +glmc_quat_rotate(mat4 m, versor q, mat4 dest); + +CGLM_EXPORT +void +glmc_quat_rotate_at(mat4 model, versor q, vec3 pivot); + +CGLM_EXPORT +void +glmc_quat_rotate_atm(mat4 m, versor q, vec3 pivot); + +CGLM_EXPORT +void +glmc_quat_make(const float * __restrict src, versor dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_quat_h */ diff --git a/external/cglm/call/ray.h b/external/cglm/call/ray.h new file mode 100644 index 0000000..e529fdf --- /dev/null +++ b/external/cglm/call/ray.h @@ -0,0 +1,39 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_ray_h +#define cglmc_ray_h +#ifdef __cplusplus +extern "C" { +#endif +#include "../cglm.h" + +CGLM_EXPORT +bool +glmc_ray_triangle(vec3 origin, + vec3 direction, + vec3 v0, + vec3 v1, + vec3 v2, + float *d); + +CGLM_EXPORT +bool +glmc_ray_sphere(vec3 origin, + vec3 dir, + vec4 s, + float * __restrict t1, + float * __restrict t2); + +CGLM_EXPORT +void +glmc_ray_at(vec3 orig, vec3 dir, float t, vec3 point); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_ray_h */ diff --git a/external/cglm/call/sphere.h b/external/cglm/call/sphere.h new file mode 100644 index 0000000..9b96546 --- /dev/null +++ b/external/cglm/call/sphere.h @@ -0,0 +1,39 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_sphere_h +#define cglmc_sphere_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +float +glmc_sphere_radii(vec4 s); + +CGLM_EXPORT +void +glmc_sphere_transform(vec4 s, mat4 m, vec4 dest); + +CGLM_EXPORT +void +glmc_sphere_merge(vec4 s1, vec4 s2, vec4 dest); + +CGLM_EXPORT +bool +glmc_sphere_sphere(vec4 s1, vec4 s2); + +CGLM_EXPORT +bool +glmc_sphere_point(vec4 s, vec3 point); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_sphere_h */ diff --git a/external/cglm/call/vec2.h b/external/cglm/call/vec2.h new file mode 100644 index 0000000..0284a8c --- /dev/null +++ b/external/cglm/call/vec2.h @@ -0,0 +1,251 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_vec2_h +#define cglmc_vec2_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +CGLM_EXPORT +void +glmc_vec2(float * __restrict v, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_fill(vec2 v, float val); + +CGLM_EXPORT +bool +glmc_vec2_eq(vec2 v, float val); + +CGLM_EXPORT +bool +glmc_vec2_eqv(vec2 a, vec2 b); + +CGLM_EXPORT +void +glmc_vec2_copy(vec2 a, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_zero(vec2 v); + +CGLM_EXPORT +void +glmc_vec2_one(vec2 v); + +CGLM_EXPORT +float +glmc_vec2_dot(vec2 a, vec2 b); + +CGLM_EXPORT +float +glmc_vec2_cross(vec2 a, vec2 b); + +CGLM_EXPORT +float +glmc_vec2_norm2(vec2 v); + +CGLM_EXPORT +float +glmc_vec2_norm(vec2 v); + +CGLM_EXPORT +void +glmc_vec2_add(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_adds(vec2 v, float s, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_sub(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_subs(vec2 v, float s, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_mul(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_scale(vec2 v, float s, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_scale_as(vec2 v, float s, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_div(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_divs(vec2 v, float s, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_addadd(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_subadd(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_muladd(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_muladds(vec2 a, float s, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_maxadd(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_minadd(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_subsub(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_addsub(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_mulsub(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_mulsubs(vec2 a, float s, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_maxsub(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_minsub(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_negate_to(vec2 v, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_negate(vec2 v); + +CGLM_EXPORT +void +glmc_vec2_normalize(vec2 v); + +CGLM_EXPORT +void +glmc_vec2_normalize_to(vec2 v, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_rotate(vec2 v, float angle, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_center(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +float +glmc_vec2_distance2(vec2 a, vec2 b); + +CGLM_EXPORT +float +glmc_vec2_distance(vec2 a, vec2 b); + +CGLM_EXPORT +void +glmc_vec2_maxv(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_minv(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_clamp(vec2 v, float minval, float maxval); + +CGLM_EXPORT +void +glmc_vec2_abs(vec2 v, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_fract(vec2 v, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_floor(vec2 v, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_mods(vec2 v, float s, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_swizzle(vec2 v, int mask, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_lerp(vec2 from, vec2 to, float t, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_step(vec2 edge, vec2 x, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_steps(float edge, vec2 x, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_stepr(vec2 edge, float x, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_complex_mul(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_complex_div(vec2 a, vec2 b, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_complex_conjugate(vec2 a, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_make(const float * __restrict src, vec2 dest); + +CGLM_EXPORT +void +glmc_vec2_reflect(vec2 v, vec2 n, vec2 dest); + +CGLM_EXPORT +bool +glmc_vec2_refract(vec2 v, vec2 n, float eta, vec2 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_vec2_h */ diff --git a/external/cglm/call/vec3.h b/external/cglm/call/vec3.h new file mode 100644 index 0000000..640fac7 --- /dev/null +++ b/external/cglm/call/vec3.h @@ -0,0 +1,369 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_vec3_h +#define cglmc_vec3_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +/* DEPRECATED! use _copy, _ucopy versions */ +#define glmc_vec_dup(v, dest) glmc_vec3_copy(v, dest) +#define glmc_vec3_flipsign(v) glmc_vec3_negate(v) +#define glmc_vec3_flipsign_to(v, dest) glmc_vec3_negate_to(v, dest) +#define glmc_vec3_inv(v) glmc_vec3_negate(v) +#define glmc_vec3_inv_to(v, dest) glmc_vec3_negate_to(v, dest) +#define glmc_vec3_step_uni(edge, x, dest) glmc_vec3_steps(edge, x, dest); + +CGLM_EXPORT +void +glmc_vec3(vec4 v4, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_copy(vec3 a, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_zero(vec3 v); + +CGLM_EXPORT +void +glmc_vec3_one(vec3 v); + +CGLM_EXPORT +float +glmc_vec3_dot(vec3 a, vec3 b); + +CGLM_EXPORT +void +glmc_vec3_cross(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_crossn(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +float +glmc_vec3_norm(vec3 v); + +CGLM_EXPORT +float +glmc_vec3_norm2(vec3 v); + +CGLM_EXPORT +float +glmc_vec3_norm_one(vec3 v); + +CGLM_EXPORT +float +glmc_vec3_norm_inf(vec3 v); + +CGLM_EXPORT +void +glmc_vec3_normalize_to(vec3 v, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_normalize(vec3 v); + +CGLM_EXPORT +void +glmc_vec3_add(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_adds(vec3 v, float s, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_sub(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_subs(vec3 v, float s, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_mul(vec3 a, vec3 b, vec3 d); + +CGLM_EXPORT +void +glmc_vec3_scale(vec3 v, float s, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_scale_as(vec3 v, float s, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_div(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_divs(vec3 a, float s, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_addadd(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_subadd(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_muladd(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_muladds(vec3 a, float s, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_maxadd(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_minadd(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_subsub(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_addsub(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_mulsub(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_mulsubs(vec3 a, float s, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_maxsub(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_minsub(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_negate(vec3 v); + +CGLM_EXPORT +void +glmc_vec3_negate_to(vec3 v, vec3 dest); + +CGLM_EXPORT +float +glmc_vec3_angle(vec3 a, vec3 b); + +CGLM_EXPORT +void +glmc_vec3_rotate(vec3 v, float angle, vec3 axis); + +CGLM_EXPORT +void +glmc_vec3_rotate_m4(mat4 m, vec3 v, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_rotate_m3(mat3 m, vec3 v, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_proj(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_center(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +float +glmc_vec3_distance2(vec3 a, vec3 b); + +CGLM_EXPORT +float +glmc_vec3_distance(vec3 a, vec3 b); + +CGLM_EXPORT +void +glmc_vec3_maxv(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_minv(vec3 a, vec3 b, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_clamp(vec3 v, float minVal, float maxVal); + +CGLM_EXPORT +void +glmc_vec3_ortho(vec3 v, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_lerpc(vec3 from, vec3 to, float t, vec3 dest); + +CGLM_INLINE +void +glmc_vec3_mix(vec3 from, vec3 to, float t, vec3 dest) { + glmc_vec3_lerp(from, to, t, dest); +} + +CGLM_INLINE +void +glmc_vec3_mixc(vec3 from, vec3 to, float t, vec3 dest) { + glmc_vec3_lerpc(from, to, t, dest); +} + +CGLM_EXPORT +void +glmc_vec3_step(vec3 edge, vec3 x, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_smoothstep_uni(float edge0, float edge1, vec3 x, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_smoothstep(vec3 edge0, vec3 edge1, vec3 x, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_smoothinterp(vec3 from, vec3 to, float t, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_swizzle(vec3 v, int mask, vec3 dest); + +/* ext */ + +CGLM_EXPORT +void +glmc_vec3_mulv(vec3 a, vec3 b, vec3 d); + +CGLM_EXPORT +void +glmc_vec3_broadcast(float val, vec3 d); + +CGLM_EXPORT +void +glmc_vec3_fill(vec3 v, float val); + +CGLM_EXPORT +bool +glmc_vec3_eq(vec3 v, float val); + +CGLM_EXPORT +bool +glmc_vec3_eq_eps(vec3 v, float val); + +CGLM_EXPORT +bool +glmc_vec3_eq_all(vec3 v); + +CGLM_EXPORT +bool +glmc_vec3_eqv(vec3 a, vec3 b); + +CGLM_EXPORT +bool +glmc_vec3_eqv_eps(vec3 a, vec3 b); + +CGLM_EXPORT +float +glmc_vec3_max(vec3 v); + +CGLM_EXPORT +float +glmc_vec3_min(vec3 v); + +CGLM_EXPORT +bool +glmc_vec3_isnan(vec3 v); + +CGLM_EXPORT +bool +glmc_vec3_isinf(vec3 v); + +CGLM_EXPORT +bool +glmc_vec3_isvalid(vec3 v); + +CGLM_EXPORT +void +glmc_vec3_sign(vec3 v, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_abs(vec3 v, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_fract(vec3 v, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_floor(vec3 v, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_mods(vec3 v, float s, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_steps(float edge, vec3 x, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_stepr(vec3 edge, float x, vec3 dest); + +CGLM_EXPORT +float +glmc_vec3_hadd(vec3 v); + +CGLM_EXPORT +void +glmc_vec3_sqrt(vec3 v, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_make(const float * __restrict src, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_faceforward(vec3 n, vec3 v, vec3 nref, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_reflect(vec3 v, vec3 n, vec3 dest); + +CGLM_EXPORT +bool +glmc_vec3_refract(vec3 v, vec3 n, float eta, vec3 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_vec3_h */ diff --git a/external/cglm/call/vec4.h b/external/cglm/call/vec4.h new file mode 100644 index 0000000..22eee24 --- /dev/null +++ b/external/cglm/call/vec4.h @@ -0,0 +1,342 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglmc_vec4_h +#define cglmc_vec4_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "../cglm.h" + +/* DEPRECATED! use _copy, _ucopy versions */ +#define glmc_vec4_dup3(v, dest) glmc_vec4_copy3(v, dest) +#define glmc_vec4_dup(v, dest) glmc_vec4_copy(v, dest) +#define glmc_vec4_flipsign(v) glmc_vec4_negate(v) +#define glmc_vec4_flipsign_to(v, dest) glmc_vec4_negate_to(v, dest) +#define glmc_vec4_inv(v) glmc_vec4_negate(v) +#define glmc_vec4_inv_to(v, dest) glmc_vec4_negate_to(v, dest) +#define glmc_vec4_step_uni(edge, x, dest) glmc_vec4_steps(edge, x, dest) + +CGLM_EXPORT +void +glmc_vec4(vec3 v3, float last, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_zero(vec4 v); + +CGLM_EXPORT +void +glmc_vec4_one(vec4 v); + +CGLM_EXPORT +void +glmc_vec4_copy3(vec4 v, vec3 dest); + +CGLM_EXPORT +void +glmc_vec4_copy(vec4 v, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_ucopy(vec4 v, vec4 dest); + +CGLM_EXPORT +float +glmc_vec4_dot(vec4 a, vec4 b); + +CGLM_EXPORT +float +glmc_vec4_norm(vec4 v); + +CGLM_EXPORT +float +glmc_vec4_norm2(vec4 v); + +CGLM_EXPORT +float +glmc_vec4_norm_one(vec4 v); + +CGLM_EXPORT +float +glmc_vec4_norm_inf(vec4 v); + +CGLM_EXPORT +void +glmc_vec4_normalize_to(vec4 v, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_normalize(vec4 v); + +CGLM_EXPORT +void +glmc_vec4_add(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_adds(vec4 v, float s, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_sub(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_subs(vec4 v, float s, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_mul(vec4 a, vec4 b, vec4 d); + +CGLM_EXPORT +void +glmc_vec4_scale(vec4 v, float s, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_scale_as(vec4 v, float s, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_div(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_divs(vec4 v, float s, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_addadd(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_subadd(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_muladd(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_muladds(vec4 a, float s, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_maxadd(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_minadd(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_subsub(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_addsub(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_mulsub(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_mulsubs(vec4 a, float s, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_maxsub(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_minsub(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_negate(vec4 v); + +CGLM_EXPORT +void +glmc_vec4_negate_to(vec4 v, vec4 dest); + +CGLM_EXPORT +float +glmc_vec4_distance(vec4 a, vec4 b); + +CGLM_EXPORT +float +glmc_vec4_distance2(vec4 a, vec4 b); + +CGLM_EXPORT +void +glmc_vec4_maxv(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_minv(vec4 a, vec4 b, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_clamp(vec4 v, float minVal, float maxVal); + +CGLM_EXPORT +void +glmc_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest); + +CGLM_INLINE +void +glmc_vec4_mix(vec4 from, vec4 to, float t, vec4 dest) { + glmc_vec4_lerp(from, to, t, dest); +} + +CGLM_INLINE +void +glmc_vec4_mixc(vec4 from, vec4 to, float t, vec4 dest) { + glmc_vec4_lerpc(from, to, t, dest); +} + +CGLM_EXPORT +void +glmc_vec4_step(vec4 edge, vec4 x, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_cubic(float s, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_swizzle(vec4 v, int mask, vec4 dest); + +/* ext */ + +CGLM_EXPORT +void +glmc_vec4_mulv(vec4 a, vec4 b, vec4 d); + +CGLM_EXPORT +void +glmc_vec4_broadcast(float val, vec4 d); + +CGLM_EXPORT +void +glmc_vec4_fill(vec4 v, float val); + +CGLM_EXPORT +bool +glmc_vec4_eq(vec4 v, float val); + +CGLM_EXPORT +bool +glmc_vec4_eq_eps(vec4 v, float val); + +CGLM_EXPORT +bool +glmc_vec4_eq_all(vec4 v); + +CGLM_EXPORT +bool +glmc_vec4_eqv(vec4 a, vec4 b); + +CGLM_EXPORT +bool +glmc_vec4_eqv_eps(vec4 a, vec4 b); + +CGLM_EXPORT +float +glmc_vec4_max(vec4 v); + +CGLM_EXPORT +float +glmc_vec4_min(vec4 v); + +CGLM_EXPORT +bool +glmc_vec4_isnan(vec4 v); + +CGLM_EXPORT +bool +glmc_vec4_isinf(vec4 v); + +CGLM_EXPORT +bool +glmc_vec4_isvalid(vec4 v); + +CGLM_EXPORT +void +glmc_vec4_sign(vec4 v, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_abs(vec4 v, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_fract(vec4 v, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_floor(vec4 v, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_mods(vec4 v, float s, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_steps(float edge, vec4 x, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_stepr(vec4 edge, float x, vec4 dest); + +CGLM_EXPORT +float +glmc_vec4_hadd(vec4 v); + +CGLM_EXPORT +void +glmc_vec4_sqrt(vec4 v, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_make(const float * __restrict src, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_reflect(vec4 v, vec4 n, vec4 dest); + +CGLM_EXPORT +bool +glmc_vec4_refract(vec4 v, vec4 n, float eta, vec4 dest); + +#ifdef __cplusplus +} +#endif +#endif /* cglmc_vec4_h */ diff --git a/external/cglm/cam.h b/external/cglm/cam.h new file mode 100644 index 0000000..816cb5e --- /dev/null +++ b/external/cglm/cam.h @@ -0,0 +1,582 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_frustum(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) + CGLM_INLINE void glm_ortho(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) + CGLM_INLINE void glm_ortho_aabb(vec3 box[2], mat4 dest) + CGLM_INLINE void glm_ortho_aabb_p(vec3 box[2], float padding, mat4 dest) + CGLM_INLINE void glm_ortho_aabb_pz(vec3 box[2], float padding, mat4 dest) + CGLM_INLINE void glm_ortho_default(float aspect, mat4 dest) + CGLM_INLINE void glm_ortho_default_s(float aspect, float size, mat4 dest) + CGLM_INLINE void glm_perspective(float fovy, + float aspect, + float nearZ, + float farZ, + mat4 dest) + CGLM_INLINE void glm_perspective_default(float aspect, mat4 dest) + CGLM_INLINE void glm_perspective_resize(float aspect, mat4 proj) + CGLM_INLINE void glm_lookat(vec3 eye, vec3 center, vec3 up, mat4 dest) + CGLM_INLINE void glm_look(vec3 eye, vec3 dir, vec3 up, mat4 dest) + CGLM_INLINE void glm_look_anyup(vec3 eye, vec3 dir, mat4 dest) + CGLM_INLINE void glm_persp_decomp(mat4 proj, + float *nearZ, float *farZ, + float *top, float *bottom, + float *left, float *right) + CGLM_INLINE void glm_persp_decompv(mat4 proj, float dest[6]) + CGLM_INLINE void glm_persp_decomp_x(mat4 proj, float *left, float *right) + CGLM_INLINE void glm_persp_decomp_y(mat4 proj, float *top, float *bottom) + CGLM_INLINE void glm_persp_decomp_z(mat4 proj, float *nearv, float *farv) + CGLM_INLINE void glm_persp_decomp_far(mat4 proj, float *farZ) + CGLM_INLINE void glm_persp_decomp_near(mat4 proj, float *nearZ) + CGLM_INLINE float glm_persp_fovy(mat4 proj) + CGLM_INLINE float glm_persp_aspect(mat4 proj) + CGLM_INLINE void glm_persp_sizes(mat4 proj, float fovy, vec4 dest) + */ + +#ifndef cglm_cam_h +#define cglm_cam_h + +#include "common.h" +#include "plane.h" + +#include "clipspace/persp.h" + +#ifndef CGLM_CLIPSPACE_INCLUDE_ALL +# if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO +# include "clipspace/ortho_lh_zo.h" +# include "clipspace/persp_lh_zo.h" +# include "clipspace/view_lh_zo.h" +# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO +# include "clipspace/ortho_lh_no.h" +# include "clipspace/persp_lh_no.h" +# include "clipspace/view_lh_no.h" +# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO +# include "clipspace/ortho_rh_zo.h" +# include "clipspace/persp_rh_zo.h" +# include "clipspace/view_rh_zo.h" +# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO +# include "clipspace/ortho_rh_no.h" +# include "clipspace/persp_rh_no.h" +# include "clipspace/view_rh_no.h" +# endif +#else +# include "clipspace/ortho_lh_zo.h" +# include "clipspace/persp_lh_zo.h" +# include "clipspace/ortho_lh_no.h" +# include "clipspace/persp_lh_no.h" +# include "clipspace/ortho_rh_zo.h" +# include "clipspace/persp_rh_zo.h" +# include "clipspace/ortho_rh_no.h" +# include "clipspace/persp_rh_no.h" +# include "clipspace/view_lh_zo.h" +# include "clipspace/view_lh_no.h" +# include "clipspace/view_rh_zo.h" +# include "clipspace/view_rh_no.h" +#endif + +/*! + * @brief set up perspective peprojection matrix + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_frustum(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_frustum_lh_zo(left, right, bottom, top, nearZ, farZ, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_frustum_lh_no(left, right, bottom, top, nearZ, farZ, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_frustum_rh_zo(left, right, bottom, top, nearZ, farZ, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_frustum_rh_no(left, right, bottom, top, nearZ, farZ, dest); +#endif +} + +/*! + * @brief set up orthographic projection matrix + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_ortho_lh_zo(left, right, bottom, top, nearZ, farZ, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_ortho_lh_no(left, right, bottom, top, nearZ, farZ, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_ortho_rh_zo(left, right, bottom, top, nearZ, farZ, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_ortho_rh_no(left, right, bottom, top, nearZ, farZ, dest); +#endif +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb(vec3 box[2], mat4 dest) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_ortho_aabb_lh_zo(box, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_ortho_aabb_lh_no(box, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_ortho_aabb_rh_zo(box, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_ortho_aabb_rh_no(box, dest); +#endif +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb_p(vec3 box[2], float padding, mat4 dest) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_ortho_aabb_p_lh_zo(box, padding, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_ortho_aabb_p_lh_no(box, padding, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_ortho_aabb_p_rh_zo(box, padding, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_ortho_aabb_p_rh_no(box, padding, dest); +#endif +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding for near and far + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb_pz(vec3 box[2], float padding, mat4 dest) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_ortho_aabb_pz_lh_zo(box, padding, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_ortho_aabb_pz_lh_no(box, padding, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_ortho_aabb_pz_rh_zo(box, padding, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_ortho_aabb_pz_rh_no(box, padding, dest); +#endif +} + +/*! + * @brief set up unit orthographic projection matrix + * + * @param[in] aspect aspect ration ( width / height ) + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_default(float aspect, mat4 dest) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_ortho_default_lh_zo(aspect, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_ortho_default_lh_no(aspect, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_ortho_default_rh_zo(aspect, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_ortho_default_rh_no(aspect, dest); +#endif +} + +/*! + * @brief set up orthographic projection matrix with given CUBE size + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] size cube size + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_default_s(float aspect, float size, mat4 dest) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_ortho_default_s_lh_zo(aspect, size, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_ortho_default_s_lh_no(aspect, size, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_ortho_default_s_rh_zo(aspect, size, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_ortho_default_s_rh_no(aspect, size, dest); +#endif +} + +/*! + * @brief set up perspective projection matrix + * + * @param[in] fovy field of view angle + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping planes + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_perspective(float fovy, float aspect, float nearZ, float farZ, mat4 dest) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_perspective_lh_zo(fovy, aspect, nearZ, farZ, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_perspective_lh_no(fovy, aspect, nearZ, farZ, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_perspective_rh_zo(fovy, aspect, nearZ, farZ, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_perspective_rh_no(fovy, aspect, nearZ, farZ, dest); +#endif +} + +/*! + * @brief extend perspective projection matrix's far distance + * + * this function does not guarantee far >= near, be aware of that! + * + * @param[in, out] proj projection matrix to extend + * @param[in] deltaFar distance from existing far (negative to shink) + */ +CGLM_INLINE +void +glm_persp_move_far(mat4 proj, float deltaFar) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_persp_move_far_lh_zo(proj, deltaFar); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_persp_move_far_lh_no(proj, deltaFar); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_persp_move_far_rh_zo(proj, deltaFar); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_persp_move_far_rh_no(proj, deltaFar); +#endif +} + +/*! + * @brief set up perspective projection matrix with default near/far + * and angle values + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_perspective_default(float aspect, mat4 dest) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_perspective_default_lh_zo(aspect, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_perspective_default_lh_no(aspect, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_perspective_default_rh_zo(aspect, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_perspective_default_rh_no(aspect, dest); +#endif +} + +/*! + * @brief resize perspective matrix by aspect ratio ( width / height ) + * this makes very easy to resize proj matrix when window /viewport + * reized + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in, out] proj perspective projection matrix + */ +CGLM_INLINE +void +glm_perspective_resize(float aspect, mat4 proj) { + if (proj[0][0] == 0.0f) + return; + + proj[0][0] = proj[1][1] / aspect; +} + +/*! + * @brief set up view matrix + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] center center vector + * @param[in] up up vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_lookat(vec3 eye, vec3 center, vec3 up, mat4 dest) { +#if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_LH_BIT + glm_lookat_lh(eye, center, up, dest); +#elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_RH_BIT + glm_lookat_rh(eye, center, up, dest); +#endif +} + +/*! + * @brief set up view matrix + * + * convenient wrapper for lookat: if you only have direction not target self + * then this might be useful. Because you need to get target from direction. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[in] up up vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_look(vec3 eye, vec3 dir, vec3 up, mat4 dest) { +#if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_LH_BIT + glm_look_lh(eye, dir, up, dest); +#elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_RH_BIT + glm_look_rh(eye, dir, up, dest); +#endif +} + +/*! + * @brief set up view matrix + * + * convenient wrapper for look: if you only have direction and if you don't + * care what UP vector is then this might be useful to create view matrix + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_look_anyup(vec3 eye, vec3 dir, mat4 dest) { +#if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_LH_BIT + glm_look_anyup_lh(eye, dir, dest); +#elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_RH_BIT + glm_look_anyup_rh(eye, dir, dest); +#endif +} + +/*! + * @brief decomposes frustum values of perspective projection. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + * @param[out] top top + * @param[out] bottom bottom + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glm_persp_decomp(mat4 proj, + float * __restrict nearZ, float * __restrict farZ, + float * __restrict top, float * __restrict bottom, + float * __restrict left, float * __restrict right) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_persp_decomp_lh_zo(proj, nearZ, farZ, top, bottom, left, right); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_persp_decomp_lh_no(proj, nearZ, farZ, top, bottom, left, right); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_persp_decomp_rh_zo(proj, nearZ, farZ, top, bottom, left, right); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_persp_decomp_rh_no(proj, nearZ, farZ, top, bottom, left, right); +#endif +} + +/*! + * @brief decomposes frustum values of perspective projection. + * this makes easy to get all values at once + * + * @param[in] proj perspective projection matrix + * @param[out] dest array + */ +CGLM_INLINE +void +glm_persp_decompv(mat4 proj, float dest[6]) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_persp_decompv_lh_zo(proj, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_persp_decompv_lh_no(proj, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_persp_decompv_rh_zo(proj, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_persp_decompv_rh_no(proj, dest); +#endif +} + +/*! + * @brief decomposes left and right values of perspective projection. + * x stands for x axis (left / right axis) + * + * @param[in] proj perspective projection matrix + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glm_persp_decomp_x(mat4 proj, + float * __restrict left, + float * __restrict right) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_persp_decomp_x_lh_zo(proj, left, right); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_persp_decomp_x_lh_no(proj, left, right); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_persp_decomp_x_rh_zo(proj, left, right); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_persp_decomp_x_rh_no(proj, left, right); +#endif +} + +/*! + * @brief decomposes top and bottom values of perspective projection. + * y stands for y axis (top / bottom axis) + * + * @param[in] proj perspective projection matrix + * @param[out] top top + * @param[out] bottom bottom + */ +CGLM_INLINE +void +glm_persp_decomp_y(mat4 proj, + float * __restrict top, + float * __restrict bottom) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_persp_decomp_y_lh_zo(proj, top, bottom); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_persp_decomp_y_lh_no(proj, top, bottom); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_persp_decomp_y_rh_zo(proj, top, bottom); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_persp_decomp_y_rh_no(proj, top, bottom); +#endif +} + +/*! + * @brief decomposes near and far values of perspective projection. + * z stands for z axis (near / far axis) + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + */ +CGLM_INLINE +void +glm_persp_decomp_z(mat4 proj, float * __restrict nearZ, float * __restrict farZ) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_persp_decomp_z_lh_zo(proj, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_persp_decomp_z_lh_no(proj, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_persp_decomp_z_rh_zo(proj, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_persp_decomp_z_rh_no(proj, nearZ, farZ); +#endif +} + +/*! + * @brief decomposes far value of perspective projection. + * + * @param[in] proj perspective projection matrix + * @param[out] farZ far + */ +CGLM_INLINE +void +glm_persp_decomp_far(mat4 proj, float * __restrict farZ) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_persp_decomp_far_lh_zo(proj, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_persp_decomp_far_lh_no(proj, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_persp_decomp_far_rh_zo(proj, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_persp_decomp_far_rh_no(proj, farZ); +#endif +} + +/*! + * @brief decomposes near value of perspective projection. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + */ +CGLM_INLINE +void +glm_persp_decomp_near(mat4 proj, float * __restrict nearZ) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_persp_decomp_near_lh_zo(proj, nearZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_persp_decomp_near_lh_no(proj, nearZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_persp_decomp_near_rh_zo(proj, nearZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_persp_decomp_near_rh_no(proj, nearZ); +#endif +} + +/*! + * @brief returns sizes of near and far planes of perspective projection + * + * @param[in] proj perspective projection matrix + * @param[in] fovy fovy (see brief) + * @param[out] dest sizes order: [Wnear, Hnear, Wfar, Hfar] + */ +CGLM_INLINE +void +glm_persp_sizes(mat4 proj, float fovy, vec4 dest) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glm_persp_sizes_lh_zo(proj, fovy, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glm_persp_sizes_lh_no(proj, fovy, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glm_persp_sizes_rh_zo(proj, fovy, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glm_persp_sizes_rh_no(proj, fovy, dest); +#endif +} + +#endif /* cglm_cam_h */ diff --git a/external/cglm/cglm.h b/external/cglm/cglm.h new file mode 100644 index 0000000..3532830 --- /dev/null +++ b/external/cglm/cglm.h @@ -0,0 +1,48 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_h +#define cglm_h + +#include "common.h" +#include "vec2.h" +#include "vec3.h" +#include "vec4.h" +#include "ivec2.h" +#include "ivec3.h" +#include "ivec4.h" +#include "mat4.h" +#include "mat4x2.h" +#include "mat4x3.h" +#include "mat3.h" +#include "mat3x2.h" +#include "mat3x4.h" +#include "mat2.h" +#include "mat2x3.h" +#include "mat2x4.h" +#include "affine.h" +#include "cam.h" +#include "frustum.h" +#include "quat.h" +#include "euler.h" +#include "plane.h" +#include "noise.h" +#include "aabb2d.h" +#include "box.h" +#include "color.h" +#include "util.h" +#include "io.h" +#include "project.h" +#include "sphere.h" +#include "ease.h" +#include "curve.h" +#include "bezier.h" +#include "ray.h" +#include "affine2d.h" +#include "affine2d-post.h" + +#endif /* cglm_h */ diff --git a/external/cglm/clipspace/ortho_lh_no.h b/external/cglm/clipspace/ortho_lh_no.h new file mode 100644 index 0000000..76c7a94 --- /dev/null +++ b/external/cglm/clipspace/ortho_lh_no.h @@ -0,0 +1,183 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_ortho_lh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) + CGLM_INLINE void glm_ortho_aabb_lh_no(vec3 box[2], mat4 dest) + CGLM_INLINE void glm_ortho_aabb_p_lh_no(vec3 box[2], + float padding, + mat4 dest) + CGLM_INLINE void glm_ortho_aabb_pz_lh_no(vec3 box[2], + float padding, + mat4 dest) + CGLM_INLINE void glm_ortho_default_lh_no(float aspect, + mat4 dest) + CGLM_INLINE void glm_ortho_default_s_lh_no(float aspect, + float size, + mat4 dest) + */ + +#ifndef cglm_ortho_lh_no_h +#define cglm_ortho_lh_no_h + +#include "../common.h" +#include "../plane.h" +#include "../mat4.h" + +/*! + * @brief set up orthographic projection matrix + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_lh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) { + float rl, tb, fn; + + glm_mat4_zero(dest); + + rl = 1.0f / (right - left); + tb = 1.0f / (top - bottom); + fn =-1.0f / (farZ - nearZ); + + dest[0][0] = 2.0f * rl; + dest[1][1] = 2.0f * tb; + dest[2][2] =-2.0f * fn; + dest[3][0] =-(right + left) * rl; + dest[3][1] =-(top + bottom) * tb; + dest[3][2] = (farZ + nearZ) * fn; + dest[3][3] = 1.0f; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb_lh_no(vec3 box[2], mat4 dest) { + glm_ortho_lh_no(box[0][0], box[1][0], + box[0][1], box[1][1], + -box[1][2], -box[0][2], + dest); +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb_p_lh_no(vec3 box[2], float padding, mat4 dest) { + glm_ortho_lh_no(box[0][0] - padding, box[1][0] + padding, + box[0][1] - padding, box[1][1] + padding, + -(box[1][2] + padding), -(box[0][2] - padding), + dest); +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding for near and far + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb_pz_lh_no(vec3 box[2], float padding, mat4 dest) { + glm_ortho_lh_no(box[0][0], box[1][0], + box[0][1], box[1][1], + -(box[1][2] + padding), -(box[0][2] - padding), + dest); +} + +/*! + * @brief set up unit orthographic projection matrix + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] aspect aspect ration ( width / height ) + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_default_lh_no(float aspect, mat4 dest) { + if (aspect >= 1.0f) { + glm_ortho_lh_no(-aspect, aspect, -1.0f, 1.0f, -100.0f, 100.0f, dest); + return; + } + + aspect = 1.0f / aspect; + + glm_ortho_lh_no(-1.0f, 1.0f, -aspect, aspect, -100.0f, 100.0f, dest); +} + +/*! + * @brief set up orthographic projection matrix with given CUBE size + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] size cube size + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_default_s_lh_no(float aspect, float size, mat4 dest) { + if (aspect >= 1.0f) { + glm_ortho_lh_no(-size * aspect, + size * aspect, + -size, + size, + -size - 100.0f, + size + 100.0f, + dest); + return; + } + + glm_ortho_lh_no(-size, + size, + -size / aspect, + size / aspect, + -size - 100.0f, + size + 100.0f, + dest); +} + +#endif /*cglm_ortho_lh_no_h*/ diff --git a/external/cglm/clipspace/ortho_lh_zo.h b/external/cglm/clipspace/ortho_lh_zo.h new file mode 100644 index 0000000..e45530d --- /dev/null +++ b/external/cglm/clipspace/ortho_lh_zo.h @@ -0,0 +1,177 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_ortho_lh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) + CGLM_INLINE void glm_ortho_aabb_lh_zo(vec3 box[2], mat4 dest) + CGLM_INLINE void glm_ortho_aabb_p_lh_zo(vec3 box[2], + float padding, + mat4 dest) + CGLM_INLINE void glm_ortho_aabb_pz_lh_zo(vec3 box[2], + float padding, + mat4 dest) + CGLM_INLINE void glm_ortho_default_lh_zo(float aspect, + mat4 dest) + CGLM_INLINE void glm_ortho_default_s_lh_zo(float aspect, + float size, + mat4 dest) + */ + +#ifndef cglm_ortho_lh_zo_h +#define cglm_ortho_lh_zo_h + +#include "../common.h" +#include "../plane.h" +#include "../mat4.h" + +/*! + * @brief set up orthographic projection matrix with a left-hand coordinate + * system and a clip-space of [0, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_lh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) { + float rl, tb, fn; + + glm_mat4_zero(dest); + + rl = 1.0f / (right - left); + tb = 1.0f / (top - bottom); + fn =-1.0f / (farZ - nearZ); + + dest[0][0] = 2.0f * rl; + dest[1][1] = 2.0f * tb; + dest[2][2] =-fn; + dest[3][0] =-(right + left) * rl; + dest[3][1] =-(top + bottom) * tb; + dest[3][2] = nearZ * fn; + dest[3][3] = 1.0f; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a left-hand coordinate system and a clip-space of [0, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb_lh_zo(vec3 box[2], mat4 dest) { + glm_ortho_lh_zo(box[0][0], box[1][0], + box[0][1], box[1][1], + -box[1][2], -box[0][2], + dest); +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a left-hand coordinate system and a clip-space of [0, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb_p_lh_zo(vec3 box[2], float padding, mat4 dest) { + glm_ortho_lh_zo(box[0][0] - padding, box[1][0] + padding, + box[0][1] - padding, box[1][1] + padding, + -(box[1][2] + padding), -(box[0][2] - padding), + dest); +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a left-hand coordinate system and a clip-space of [0, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding for near and far + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb_pz_lh_zo(vec3 box[2], float padding, mat4 dest) { + glm_ortho_lh_zo(box[0][0], box[1][0], + box[0][1], box[1][1], + -(box[1][2] + padding), -(box[0][2] - padding), + dest); +} + +/*! + * @brief set up unit orthographic projection matrix + * with a left-hand coordinate system and a clip-space of [0, 1]. + * + * @param[in] aspect aspect ration ( width / height ) + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_default_lh_zo(float aspect, mat4 dest) { + if (aspect >= 1.0f) { + glm_ortho_lh_zo(-aspect, aspect, -1.0f, 1.0f, -100.0f, 100.0f, dest); + return; + } + + aspect = 1.0f / aspect; + + glm_ortho_lh_zo(-1.0f, 1.0f, -aspect, aspect, -100.0f, 100.0f, dest); +} + +/*! + * @brief set up orthographic projection matrix with given CUBE size + * with a left-hand coordinate system and a clip-space of [0, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] size cube size + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_default_s_lh_zo(float aspect, float size, mat4 dest) { + if (aspect >= 1.0f) { + glm_ortho_lh_zo(-size * aspect, + size * aspect, + -size, + size, + -size - 100.0f, + size + 100.0f, + dest); + return; + } + + glm_ortho_lh_zo(-size, + size, + -size / aspect, + size / aspect, + -size - 100.0f, + size + 100.0f, + dest); +} + +#endif /*cglm_ortho_lh_zo_h*/ diff --git a/external/cglm/clipspace/ortho_rh_no.h b/external/cglm/clipspace/ortho_rh_no.h new file mode 100644 index 0000000..aa7a906 --- /dev/null +++ b/external/cglm/clipspace/ortho_rh_no.h @@ -0,0 +1,183 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_ortho_rh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) + CGLM_INLINE void glm_ortho_aabb_rh_no(vec3 box[2], mat4 dest) + CGLM_INLINE void glm_ortho_aabb_p_rh_no(vec3 box[2], + float padding, + mat4 dest) + CGLM_INLINE void glm_ortho_aabb_pz_rh_no(vec3 box[2], + float padding, + mat4 dest) + CGLM_INLINE void glm_ortho_default_rh_no(float aspect, + mat4 dest) + CGLM_INLINE void glm_ortho_default_s_rh_no(float aspect, + float size, + mat4 dest) + */ + +#ifndef cglm_ortho_rh_no_h +#define cglm_ortho_rh_no_h + +#include "../common.h" +#include "../plane.h" +#include "../mat4.h" + +/*! + * @brief set up orthographic projection matrix + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_rh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) { + float rl, tb, fn; + + glm_mat4_zero(dest); + + rl = 1.0f / (right - left); + tb = 1.0f / (top - bottom); + fn =-1.0f / (farZ - nearZ); + + dest[0][0] = 2.0f * rl; + dest[1][1] = 2.0f * tb; + dest[2][2] = 2.0f * fn; + dest[3][0] =-(right + left) * rl; + dest[3][1] =-(top + bottom) * tb; + dest[3][2] = (farZ + nearZ) * fn; + dest[3][3] = 1.0f; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb_rh_no(vec3 box[2], mat4 dest) { + glm_ortho_rh_no(box[0][0], box[1][0], + box[0][1], box[1][1], + -box[1][2], -box[0][2], + dest); +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb_p_rh_no(vec3 box[2], float padding, mat4 dest) { + glm_ortho_rh_no(box[0][0] - padding, box[1][0] + padding, + box[0][1] - padding, box[1][1] + padding, + -(box[1][2] + padding), -(box[0][2] - padding), + dest); +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding for near and far + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb_pz_rh_no(vec3 box[2], float padding, mat4 dest) { + glm_ortho_rh_no(box[0][0], box[1][0], + box[0][1], box[1][1], + -(box[1][2] + padding), -(box[0][2] - padding), + dest); +} + +/*! + * @brief set up unit orthographic projection matrix + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] aspect aspect ration ( width / height ) + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_default_rh_no(float aspect, mat4 dest) { + if (aspect >= 1.0f) { + glm_ortho_rh_no(-aspect, aspect, -1.0f, 1.0f, -100.0f, 100.0f, dest); + return; + } + + aspect = 1.0f / aspect; + + glm_ortho_rh_no(-1.0f, 1.0f, -aspect, aspect, -100.0f, 100.0f, dest); +} + +/*! + * @brief set up orthographic projection matrix with given CUBE size + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] size cube size + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_default_s_rh_no(float aspect, float size, mat4 dest) { + if (aspect >= 1.0f) { + glm_ortho_rh_no(-size * aspect, + size * aspect, + -size, + size, + -size - 100.0f, + size + 100.0f, + dest); + return; + } + + glm_ortho_rh_no(-size, + size, + -size / aspect, + size / aspect, + -size - 100.0f, + size + 100.0f, + dest); +} + +#endif /*cglm_ortho_rh_no_h*/ diff --git a/external/cglm/clipspace/ortho_rh_zo.h b/external/cglm/clipspace/ortho_rh_zo.h new file mode 100644 index 0000000..7a0876c --- /dev/null +++ b/external/cglm/clipspace/ortho_rh_zo.h @@ -0,0 +1,181 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_ortho_rh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) + CGLM_INLINE void glm_ortho_aabb_rh_zo(vec3 box[2], mat4 dest) + CGLM_INLINE void glm_ortho_aabb_p_rh_zo(vec3 box[2], + float padding, + mat4 dest) + CGLM_INLINE void glm_ortho_aabb_pz_rh_zo(vec3 box[2], + float padding, + mat4 dest) + CGLM_INLINE void glm_ortho_default_rh_zo(float aspect, + mat4 dest) + CGLM_INLINE void glm_ortho_default_s_rh_zo(float aspect, + float size, + mat4 dest) + */ + +#ifndef cglm_ortho_rh_zo_h +#define cglm_ortho_rh_zo_h + +#include "../common.h" +#include "../plane.h" +#include "../mat4.h" + +/*! + * @brief set up orthographic projection matrix with a right-hand coordinate + * system and a clip-space of [0, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_rh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) { + float rl, tb, fn; + + glm_mat4_zero(dest); + + rl = 1.0f / (right - left); + tb = 1.0f / (top - bottom); + fn =-1.0f / (farZ - nearZ); + + dest[0][0] = 2.0f * rl; + dest[1][1] = 2.0f * tb; + dest[2][2] = fn; + dest[3][0] =-(right + left) * rl; + dest[3][1] =-(top + bottom) * tb; + dest[3][2] = nearZ * fn; + dest[3][3] = 1.0f; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a right-hand coordinate system and a clip-space with depth + * values from zero to one. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb_rh_zo(vec3 box[2], mat4 dest) { + glm_ortho_rh_zo(box[0][0], box[1][0], + box[0][1], box[1][1], + -box[1][2], -box[0][2], + dest); +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a right-hand coordinate system and a clip-space with depth + * values from zero to one. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb_p_rh_zo(vec3 box[2], float padding, mat4 dest) { + glm_ortho_rh_zo(box[0][0] - padding, box[1][0] + padding, + box[0][1] - padding, box[1][1] + padding, + -(box[1][2] + padding), -(box[0][2] - padding), + dest); +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a right-hand coordinate system and a clip-space with depth + * values from zero to one. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding for near and far + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_aabb_pz_rh_zo(vec3 box[2], float padding, mat4 dest) { + glm_ortho_rh_zo(box[0][0], box[1][0], + box[0][1], box[1][1], + -(box[1][2] + padding), -(box[0][2] - padding), + dest); +} + +/*! + * @brief set up unit orthographic projection matrix with a right-hand + * coordinate system and a clip-space of [0, 1]. + * + * @param[in] aspect aspect ration ( width / height ) + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_default_rh_zo(float aspect, mat4 dest) { + if (aspect >= 1.0f) { + glm_ortho_rh_zo(-aspect, aspect, -1.0f, 1.0f, -100.0f, 100.0f, dest); + return; + } + + aspect = 1.0f / aspect; + + glm_ortho_rh_zo(-1.0f, 1.0f, -aspect, aspect, -100.0f, 100.0f, dest); +} + +/*! + * @brief set up orthographic projection matrix with given CUBE size + * with a right-hand coordinate system and a clip-space with depth + * values from zero to one. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] size cube size + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_ortho_default_s_rh_zo(float aspect, float size, mat4 dest) { + if (aspect >= 1.0f) { + glm_ortho_rh_zo(-size * aspect, + size * aspect, + -size, + size, + -size - 100.0f, + size + 100.0f, + dest); + return; + } + + glm_ortho_rh_zo(-size, + size, + -size / aspect, + size / aspect, + -size - 100.0f, + size + 100.0f, + dest); +} + +#endif /*cglm_ortho_rh_zo_h*/ diff --git a/external/cglm/clipspace/persp.h b/external/cglm/clipspace/persp.h new file mode 100644 index 0000000..15aa715 --- /dev/null +++ b/external/cglm/clipspace/persp.h @@ -0,0 +1,48 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_persp_decomp_far(mat4 proj, float *farZ) + CGLM_INLINE float glm_persp_fovy(mat4 proj) + CGLM_INLINE float glm_persp_aspect(mat4 proj) + CGLM_INLINE void glm_persp_sizes(mat4 proj, float fovy, vec4 dest) + */ + +#ifndef cglm_persp_h +#define cglm_persp_h + +#include "../common.h" +#include "../plane.h" +#include "../mat4.h" + +/*! + * @brief returns field of view angle along the Y-axis (in radians) + * + * if you need to degrees, use glm_deg to convert it or use this: + * fovy_deg = glm_deg(glm_persp_fovy(projMatrix)) + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glm_persp_fovy(mat4 proj) { + return 2.0f * atanf(1.0f / proj[1][1]); +} + +/*! + * @brief returns aspect ratio of perspective projection + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glm_persp_aspect(mat4 proj) { + return proj[1][1] / proj[0][0]; +} + +#endif /* cglm_persp_h */ diff --git a/external/cglm/clipspace/persp_lh_no.h b/external/cglm/clipspace/persp_lh_no.h new file mode 100644 index 0000000..d28923a --- /dev/null +++ b/external/cglm/clipspace/persp_lh_no.h @@ -0,0 +1,395 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_frustum_lh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) + CGLM_INLINE void glm_perspective_lh_no(float fovy, + float aspect, + float nearZ, + float farZ, + mat4 dest) + CGLM_INLINE void glm_perspective_default_lh_no(float aspect, mat4 dest) + CGLM_INLINE void glm_perspective_resize_lh_no(float aspect, mat4 proj) + CGLM_INLINE void glm_persp_move_far_lh_no(mat4 proj, + float deltaFar) + CGLM_INLINE void glm_persp_decomp_lh_no(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ, + float * __restrict top, + float * __restrict bottom, + float * __restrict left, + float * __restrict right) + CGLM_INLINE void glm_persp_decompv_lh_no(mat4 proj, + float dest[6]) + CGLM_INLINE void glm_persp_decomp_x_lh_no(mat4 proj, + float * __restrict left, + float * __restrict right) + CGLM_INLINE void glm_persp_decomp_y_lh_no(mat4 proj, + float * __restrict top, + float * __restrict bottom) + CGLM_INLINE void glm_persp_decomp_z_lh_no(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ) + CGLM_INLINE void glm_persp_decomp_far_lh_no(mat4 proj, float * __restrict farZ) + CGLM_INLINE void glm_persp_decomp_near_lh_no(mat4 proj, float * __restrict nearZ) + CGLM_INLINE void glm_persp_sizes_lh_no(mat4 proj, float fovy, vec4 dest) + */ + +#ifndef cglm_persp_lh_no_h +#define cglm_persp_lh_no_h + +#include "../common.h" +#include "persp.h" + +/*! + * @brief set up perspective peprojection matrix + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_frustum_lh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) { + float rl, tb, fn, nv; + + glm_mat4_zero(dest); + + rl = 1.0f / (right - left); + tb = 1.0f / (top - bottom); + fn =-1.0f / (farZ - nearZ); + nv = 2.0f * nearZ; + + dest[0][0] = nv * rl; + dest[1][1] = nv * tb; + dest[2][0] = (right + left) * rl; + dest[2][1] = (top + bottom) * tb; + dest[2][2] =-(farZ + nearZ) * fn; + dest[2][3] = 1.0f; + dest[3][2] = farZ * nv * fn; +} + +/*! + * @brief set up perspective projection matrix + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] fovy field of view angle + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping planes + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_perspective_lh_no(float fovy, + float aspect, + float nearZ, + float farZ, + mat4 dest) { + float f, fn; + + glm_mat4_zero(dest); + + f = 1.0f / tanf(fovy * 0.5f); + fn = 1.0f / (nearZ - farZ); + + dest[0][0] = f / aspect; + dest[1][1] = f; + dest[2][2] =-(nearZ + farZ) * fn; + dest[2][3] = 1.0f; + dest[3][2] = 2.0f * nearZ * farZ * fn; + +} + +/*! + * @brief set up perspective projection matrix with default near/far + * and angle values with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_perspective_default_lh_no(float aspect, mat4 dest) { + glm_perspective_lh_no(GLM_PI_4f, aspect, 0.01f, 100.0f, dest); +} + +/*! + * @brief resize perspective matrix by aspect ratio ( width / height ) + * this makes very easy to resize proj matrix when window /viewport + * resized with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in, out] proj perspective projection matrix + */ +CGLM_INLINE +void +glm_perspective_resize_lh_no(float aspect, mat4 proj) { + if (proj[0][0] == 0.0f) + return; + + proj[0][0] = proj[1][1] / aspect; +} + +/*! + * @brief extend perspective projection matrix's far distance + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * this function does not guarantee far >= near, be aware of that! + * + * @param[in, out] proj projection matrix to extend + * @param[in] deltaFar distance from existing far (negative to shink) + */ +CGLM_INLINE +void +glm_persp_move_far_lh_no(mat4 proj, float deltaFar) { + float fn, farZ, nearZ, p22, p32; + + p22 = -proj[2][2]; + p32 = proj[3][2]; + + nearZ = p32 / (p22 - 1.0f); + farZ = p32 / (p22 + 1.0f) + deltaFar; + fn = 1.0f / (nearZ - farZ); + + proj[2][2] = -(farZ + nearZ) * fn; + proj[3][2] = 2.0f * nearZ * farZ * fn; +} + +/*! + * @brief decomposes frustum values of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + * @param[out] top top + * @param[out] bottom bottom + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glm_persp_decomp_lh_no(mat4 proj, + float * __restrict nearZ, float * __restrict farZ, + float * __restrict top, float * __restrict bottom, + float * __restrict left, float * __restrict right) { + float m00, m11, m20, m21, m22, m32, n, f; + float n_m11, n_m00; + + m00 = proj[0][0]; + m11 = proj[1][1]; + m20 = proj[2][0]; + m21 = proj[2][1]; + m22 =-proj[2][2]; + m32 = proj[3][2]; + + n = m32 / (m22 - 1.0f); + f = m32 / (m22 + 1.0f); + + n_m11 = n / m11; + n_m00 = n / m00; + + *nearZ = n; + *farZ = f; + *bottom = n_m11 * (m21 - 1.0f); + *top = n_m11 * (m21 + 1.0f); + *left = n_m00 * (m20 - 1.0f); + *right = n_m00 * (m20 + 1.0f); +} + +/*! + * @brief decomposes frustum values of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * this makes easy to get all values at once + * + * @param[in] proj perspective projection matrix + * @param[out] dest array + */ +CGLM_INLINE +void +glm_persp_decompv_lh_no(mat4 proj, float dest[6]) { + glm_persp_decomp_lh_no(proj, &dest[0], &dest[1], &dest[2], + &dest[3], &dest[4], &dest[5]); +} + +/*! + * @brief decomposes left and right values of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * x stands for x axis (left / right axis) + * + * @param[in] proj perspective projection matrix + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glm_persp_decomp_x_lh_no(mat4 proj, + float * __restrict left, + float * __restrict right) { + float nearZ, m20, m00, m22; + + m00 = proj[0][0]; + m20 = proj[2][0]; + m22 =-proj[2][2]; + + nearZ = proj[3][2] / (m22 - 1.0f); + *left = nearZ * (m20 - 1.0f) / m00; + *right = nearZ * (m20 + 1.0f) / m00; +} + +/*! + * @brief decomposes top and bottom values of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * y stands for y axis (top / bottom axis) + * + * @param[in] proj perspective projection matrix + * @param[out] top top + * @param[out] bottom bottom + */ +CGLM_INLINE +void +glm_persp_decomp_y_lh_no(mat4 proj, + float * __restrict top, + float * __restrict bottom) { + float nearZ, m21, m11, m22; + + m21 = proj[2][1]; + m11 = proj[1][1]; + m22 =-proj[2][2]; + + nearZ = proj[3][2] / (m22 - 1.0f); + *bottom = nearZ * (m21 - 1.0f) / m11; + *top = nearZ * (m21 + 1.0f) / m11; +} + +/*! + * @brief decomposes near and far values of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * z stands for z axis (near / far axis) + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + */ +CGLM_INLINE +void +glm_persp_decomp_z_lh_no(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ) { + float m32, m22; + + m32 = proj[3][2]; + m22 =-proj[2][2]; + + *nearZ = m32 / (m22 - 1.0f); + *farZ = m32 / (m22 + 1.0f); +} + +/*! + * @brief decomposes far value of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] farZ far + */ +CGLM_INLINE +void +glm_persp_decomp_far_lh_no(mat4 proj, float * __restrict farZ) { + *farZ = proj[3][2] / (-proj[2][2] + 1.0f); +} + +/*! + * @brief decomposes near value of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + */ +CGLM_INLINE +void +glm_persp_decomp_near_lh_no(mat4 proj, float * __restrict nearZ) { + *nearZ = proj[3][2] / (-proj[2][2] - 1.0f); +} + +/*! + * @brief returns sizes of near and far planes of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[in] fovy fovy (see brief) + * @param[out] dest sizes order: [Wnear, Hnear, Wfar, Hfar] + */ +CGLM_INLINE +void +glm_persp_sizes_lh_no(mat4 proj, float fovy, vec4 dest) { + float t, a, nearZ, farZ; + + t = 2.0f * tanf(fovy * 0.5f); + a = glm_persp_aspect(proj); + + glm_persp_decomp_z_lh_no(proj, &nearZ, &farZ); + + dest[1] = t * nearZ; + dest[3] = t * farZ; + dest[0] = a * dest[1]; + dest[2] = a * dest[3]; +} + +/*! + * @brief returns field of view angle along the Y-axis (in radians) + * with a left-hand coordinate system and a clip-space of [-1, 1]. + * + * if you need to degrees, use glm_deg to convert it or use this: + * fovy_deg = glm_deg(glm_persp_fovy(projMatrix)) + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glm_persp_fovy_lh_no(mat4 proj) { + return glm_persp_fovy(proj); +} + +/*! + * @brief returns aspect ratio of perspective projection + * with a left-hand coordinate system and a clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glm_persp_aspect_lh_no(mat4 proj) { + return glm_persp_aspect(proj); +} + +#endif /*cglm_cam_lh_no_h*/ diff --git a/external/cglm/clipspace/persp_lh_zo.h b/external/cglm/clipspace/persp_lh_zo.h new file mode 100644 index 0000000..de89643 --- /dev/null +++ b/external/cglm/clipspace/persp_lh_zo.h @@ -0,0 +1,387 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_frustum_lh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) + CGLM_INLINE void glm_perspective_lh_zo(float fovy, + float aspect, + float nearZ, + float farZ, + mat4 dest) + CGLM_INLINE void glm_perspective_default_lh_zo(float aspect, mat4 dest) + CGLM_INLINE void glm_perspective_resize_lh_zo(float aspect, mat4 proj) + CGLM_INLINE void glm_persp_move_far_lh_zo(mat4 proj, + float deltaFar) + CGLM_INLINE void glm_persp_decomp_lh_zo(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ, + float * __restrict top, + float * __restrict bottom, + float * __restrict left, + float * __restrict right) + CGLM_INLINE void glm_persp_decompv_lh_zo(mat4 proj, + float dest[6]) + CGLM_INLINE void glm_persp_decomp_x_lh_zo(mat4 proj, + float * __restrict left, + float * __restrict right) + CGLM_INLINE void glm_persp_decomp_y_lh_zo(mat4 proj, + float * __restrict top, + float * __restrict bottom) + CGLM_INLINE void glm_persp_decomp_z_lh_zo(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ) + CGLM_INLINE void glm_persp_decomp_far_lh_zo(mat4 proj, float * __restrict farZ) + CGLM_INLINE void glm_persp_decomp_near_lh_zo(mat4 proj, float * __restrict nearZ) + CGLM_INLINE void glm_persp_sizes_lh_zo(mat4 proj, float fovy, vec4 dest) + */ + +#ifndef cglm_persp_lh_zo_h +#define cglm_persp_lh_zo_h + +#include "../common.h" +#include "persp.h" + +/*! + * @brief set up perspective peprojection matrix with a left-hand coordinate + * system and a clip-space of [0, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_frustum_lh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) { + float rl, tb, fn, nv; + + glm_mat4_zero(dest); + + rl = 1.0f / (right - left); + tb = 1.0f / (top - bottom); + fn =-1.0f / (farZ - nearZ); + nv = 2.0f * nearZ; + + dest[0][0] = nv * rl; + dest[1][1] = nv * tb; + dest[2][0] = (right + left) * rl; + dest[2][1] = (top + bottom) * tb; + dest[2][2] =-farZ * fn; + dest[2][3] = 1.0f; + dest[3][2] = farZ * nearZ * fn; +} + +/*! + * @brief set up perspective projection matrix with a left-hand coordinate + * system and a clip-space of [0, 1]. + * + * @param[in] fovy field of view angle + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping planes + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_perspective_lh_zo(float fovy, + float aspect, + float nearZ, + float farZ, + mat4 dest) { + float f, fn; + + glm_mat4_zero(dest); + + f = 1.0f / tanf(fovy * 0.5f); + fn = 1.0f / (nearZ - farZ); + + dest[0][0] = f / aspect; + dest[1][1] = f; + dest[2][2] =-farZ * fn; + dest[2][3] = 1.0f; + dest[3][2] = nearZ * farZ * fn; +} + +/*! + * @brief extend perspective projection matrix's far distance with a + * left-hand coordinate system and a clip-space with depth values + * from zero to one. + * + * this function does not guarantee far >= near, be aware of that! + * + * @param[in, out] proj projection matrix to extend + * @param[in] deltaFar distance from existing far (negative to shink) + */ +CGLM_INLINE +void +glm_persp_move_far_lh_zo(mat4 proj, float deltaFar) { + float fn, farZ, nearZ, p22, p32; + + p22 = -proj[2][2]; + p32 = proj[3][2]; + + nearZ = p32 / p22; + farZ = p32 / (p22 + 1.0f) + deltaFar; + fn = 1.0f / (nearZ - farZ); + + proj[2][2] = -farZ * fn; + proj[3][2] = nearZ * farZ * fn; +} + +/*! + * @brief set up perspective projection matrix with default near/far + * and angle values with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_perspective_default_lh_zo(float aspect, mat4 dest) { + glm_perspective_lh_zo(GLM_PI_4f, aspect, 0.01f, 100.0f, dest); +} + +/*! + * @brief resize perspective matrix by aspect ratio ( width / height ) + * this makes very easy to resize proj matrix when window /viewport + * reized + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in, out] proj perspective projection matrix + */ +CGLM_INLINE +void +glm_perspective_resize_lh_zo(float aspect, mat4 proj) { + if (proj[0][0] == 0.0f) + return; + + proj[0][0] = proj[1][1] / aspect; +} + +/*! + * @brief decomposes frustum values of perspective projection + * with angle values with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + * @param[out] top top + * @param[out] bottom bottom + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glm_persp_decomp_lh_zo(mat4 proj, + float * __restrict nearZ, float * __restrict farZ, + float * __restrict top, float * __restrict bottom, + float * __restrict left, float * __restrict right) { + float m00, m11, m20, m21, m22, m32, n, f; + float n_m11, n_m00; + + m00 = proj[0][0]; + m11 = proj[1][1]; + m20 = proj[2][0]; + m21 = proj[2][1]; + m22 =-proj[2][2]; + m32 = proj[3][2]; + + n = m32 / m22; + f = m32 / (m22 + 1.0f); + + n_m11 = n / m11; + n_m00 = n / m00; + + *nearZ = n; + *farZ = f; + *bottom = n_m11 * (m21 - 1.0f); + *top = n_m11 * (m21 + 1.0f); + *left = n_m00 * (m20 - 1.0f); + *right = n_m00 * (m20 + 1.0f); +} + +/*! + * @brief decomposes frustum values of perspective projection + * with angle values with a left-hand coordinate system and a + * clip-space of [0, 1]. + * this makes easy to get all values at once + * + * @param[in] proj perspective projection matrix + * @param[out] dest array + */ +CGLM_INLINE +void +glm_persp_decompv_lh_zo(mat4 proj, float dest[6]) { + glm_persp_decomp_lh_zo(proj, &dest[0], &dest[1], &dest[2], + &dest[3], &dest[4], &dest[5]); +} + +/*! + * @brief decomposes left and right values of perspective projection (ZO). + * x stands for x axis (left / right axis) + * + * @param[in] proj perspective projection matrix + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glm_persp_decomp_x_lh_zo(mat4 proj, + float * __restrict left, + float * __restrict right) { + float nearZ, m20, m00; + + m00 = proj[0][0]; + m20 = proj[2][0]; + + nearZ = proj[3][2] / (proj[3][3]); + *left = nearZ * (m20 - 1.0f) / m00; + *right = nearZ * (m20 + 1.0f) / m00; +} + +/*! + * @brief decomposes top and bottom values of perspective projection + * with angle values with a left-hand coordinate system and a + * clip-space of [0, 1]. + * y stands for y axis (top / bottom axis) + * + * @param[in] proj perspective projection matrix + * @param[out] top top + * @param[out] bottom bottom + */ +CGLM_INLINE +void +glm_persp_decomp_y_lh_zo(mat4 proj, + float * __restrict top, + float * __restrict bottom) { + float nearZ, m21, m11; + + m21 = proj[2][1]; + m11 = proj[1][1]; + + nearZ = proj[3][2] / (proj[3][3]); + *bottom = nearZ * (m21 - 1) / m11; + *top = nearZ * (m21 + 1) / m11; +} + +/*! + * @brief decomposes near and far values of perspective projection + * with angle values with a left-hand coordinate system and a + * clip-space of [0, 1]. + * z stands for z axis (near / far axis) + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + */ +CGLM_INLINE +void +glm_persp_decomp_z_lh_zo(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ) { + float m32, m22; + + m32 = proj[3][2]; + m22 = -proj[2][2]; + + *nearZ = m32 / m22; + *farZ = m32 / (m22 + 1.0f); +} + +/*! + * @brief decomposes far value of perspective projection + * with angle values with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] farZ far + */ +CGLM_INLINE +void +glm_persp_decomp_far_lh_zo(mat4 proj, float * __restrict farZ) { + *farZ = proj[3][2] / (-proj[2][2] + 1.0f); +} + +/*! + * @brief decomposes near value of perspective projection + * with angle values with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + */ +CGLM_INLINE +void +glm_persp_decomp_near_lh_zo(mat4 proj, float * __restrict nearZ) { + *nearZ = proj[3][2] / -proj[2][2]; +} + +/*! + * @brief returns sizes of near and far planes of perspective projection + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[in] fovy fovy (see brief) + * @param[out] dest sizes order: [Wnear, Hnear, Wfar, Hfar] + */ +CGLM_INLINE +void +glm_persp_sizes_lh_zo(mat4 proj, float fovy, vec4 dest) { + float t, a, nearZ, farZ; + + t = 2.0f * tanf(fovy * 0.5f); + a = glm_persp_aspect(proj); + + glm_persp_decomp_z_lh_zo(proj, &nearZ, &farZ); + + dest[1] = t * nearZ; + dest[3] = t * farZ; + dest[0] = a * dest[1]; + dest[2] = a * dest[3]; +} + +/*! + * @brief returns field of view angle along the Y-axis (in radians) + * with a left-hand coordinate system and a clip-space of [0, 1]. + * + * if you need to degrees, use glm_deg to convert it or use this: + * fovy_deg = glm_deg(glm_persp_fovy(projMatrix)) + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glm_persp_fovy_lh_zo(mat4 proj) { + return glm_persp_fovy(proj); +} + +/*! + * @brief returns aspect ratio of perspective projection + * with a left-hand coordinate system and a clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glm_persp_aspect_lh_zo(mat4 proj) { + return glm_persp_aspect(proj); +} + +#endif /*cglm_persp_lh_zo_h*/ diff --git a/external/cglm/clipspace/persp_rh_no.h b/external/cglm/clipspace/persp_rh_no.h new file mode 100644 index 0000000..9252332 --- /dev/null +++ b/external/cglm/clipspace/persp_rh_no.h @@ -0,0 +1,395 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_frustum_rh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) + CGLM_INLINE void glm_perspective_rh_no(float fovy, + float aspect, + float nearZ, + float farZ, + mat4 dest) + CGLM_INLINE void glm_perspective_default_rh_no(float aspect, mat4 dest) + CGLM_INLINE void glm_perspective_resize_rh_no(float aspect, mat4 proj) + CGLM_INLINE void glm_persp_move_far_rh_no(mat4 proj, + float deltaFar) + CGLM_INLINE void glm_persp_decomp_rh_no(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ, + float * __restrict top, + float * __restrict bottom, + float * __restrict left, + float * __restrict right) + CGLM_INLINE void glm_persp_decompv_rh_no(mat4 proj, + float dest[6]) + CGLM_INLINE void glm_persp_decomp_x_rh_no(mat4 proj, + float * __restrict left, + float * __restrict right) + CGLM_INLINE void glm_persp_decomp_y_rh_no(mat4 proj, + float * __restrict top, + float * __restrict bottom) + CGLM_INLINE void glm_persp_decomp_z_rh_no(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ) + CGLM_INLINE void glm_persp_decomp_far_rh_no(mat4 proj, float * __restrict farZ) + CGLM_INLINE void glm_persp_decomp_near_rh_no(mat4 proj, float * __restrict nearZ) + CGLM_INLINE void glm_persp_sizes_rh_no(mat4 proj, float fovy, vec4 dest) + */ + +#ifndef cglm_persp_rh_no_h +#define cglm_persp_rh_no_h + +#include "../common.h" +#include "persp.h" + +/*! + * @brief set up perspective peprojection matrix + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_frustum_rh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) { + float rl, tb, fn, nv; + + glm_mat4_zero(dest); + + rl = 1.0f / (right - left); + tb = 1.0f / (top - bottom); + fn =-1.0f / (farZ - nearZ); + nv = 2.0f * nearZ; + + dest[0][0] = nv * rl; + dest[1][1] = nv * tb; + dest[2][0] = (right + left) * rl; + dest[2][1] = (top + bottom) * tb; + dest[2][2] = (farZ + nearZ) * fn; + dest[2][3] =-1.0f; + dest[3][2] = farZ * nv * fn; +} + +/*! + * @brief set up perspective projection matrix + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] fovy field of view angle + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping planes + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_perspective_rh_no(float fovy, + float aspect, + float nearZ, + float farZ, + mat4 dest) { + float f, fn; + + glm_mat4_zero(dest); + + f = 1.0f / tanf(fovy * 0.5f); + fn = 1.0f / (nearZ - farZ); + + dest[0][0] = f / aspect; + dest[1][1] = f; + dest[2][2] = (nearZ + farZ) * fn; + dest[2][3] =-1.0f; + dest[3][2] = 2.0f * nearZ * farZ * fn; + +} + +/*! + * @brief set up perspective projection matrix with default near/far + * and angle values with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_perspective_default_rh_no(float aspect, mat4 dest) { + glm_perspective_rh_no(GLM_PI_4f, aspect, 0.01f, 100.0f, dest); +} + +/*! + * @brief resize perspective matrix by aspect ratio ( width / height ) + * this makes very easy to resize proj matrix when window /viewport + * resized with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in, out] proj perspective projection matrix + */ +CGLM_INLINE +void +glm_perspective_resize_rh_no(float aspect, mat4 proj) { + if (proj[0][0] == 0.0f) + return; + + proj[0][0] = proj[1][1] / aspect; +} + +/*! + * @brief extend perspective projection matrix's far distance + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * this function does not guarantee far >= near, be aware of that! + * + * @param[in, out] proj projection matrix to extend + * @param[in] deltaFar distance from existing far (negative to shink) + */ +CGLM_INLINE +void +glm_persp_move_far_rh_no(mat4 proj, float deltaFar) { + float fn, farZ, nearZ, p22, p32; + + p22 = proj[2][2]; + p32 = proj[3][2]; + + nearZ = p32 / (p22 - 1.0f); + farZ = p32 / (p22 + 1.0f) + deltaFar; + fn = 1.0f / (nearZ - farZ); + + proj[2][2] = (farZ + nearZ) * fn; + proj[3][2] = 2.0f * nearZ * farZ * fn; +} + +/*! + * @brief decomposes frustum values of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + * @param[out] top top + * @param[out] bottom bottom + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glm_persp_decomp_rh_no(mat4 proj, + float * __restrict nearZ, float * __restrict farZ, + float * __restrict top, float * __restrict bottom, + float * __restrict left, float * __restrict right) { + float m00, m11, m20, m21, m22, m32, n, f; + float n_m11, n_m00; + + m00 = proj[0][0]; + m11 = proj[1][1]; + m20 = proj[2][0]; + m21 = proj[2][1]; + m22 = proj[2][2]; + m32 = proj[3][2]; + + n = m32 / (m22 - 1.0f); + f = m32 / (m22 + 1.0f); + + n_m11 = n / m11; + n_m00 = n / m00; + + *nearZ = n; + *farZ = f; + *bottom = n_m11 * (m21 - 1.0f); + *top = n_m11 * (m21 + 1.0f); + *left = n_m00 * (m20 - 1.0f); + *right = n_m00 * (m20 + 1.0f); +} + +/*! + * @brief decomposes frustum values of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * this makes easy to get all values at once + * + * @param[in] proj perspective projection matrix + * @param[out] dest array + */ +CGLM_INLINE +void +glm_persp_decompv_rh_no(mat4 proj, float dest[6]) { + glm_persp_decomp_rh_no(proj, &dest[0], &dest[1], &dest[2], + &dest[3], &dest[4], &dest[5]); +} + +/*! + * @brief decomposes left and right values of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * x stands for x axis (left / right axis) + * + * @param[in] proj perspective projection matrix + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glm_persp_decomp_x_rh_no(mat4 proj, + float * __restrict left, + float * __restrict right) { + float nearZ, m20, m00, m22; + + m00 = proj[0][0]; + m20 = proj[2][0]; + m22 = proj[2][2]; + + nearZ = proj[3][2] / (m22 - 1.0f); + *left = nearZ * (m20 - 1.0f) / m00; + *right = nearZ * (m20 + 1.0f) / m00; +} + +/*! + * @brief decomposes top and bottom values of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * y stands for y axis (top / bottom axis) + * + * @param[in] proj perspective projection matrix + * @param[out] top top + * @param[out] bottom bottom + */ +CGLM_INLINE +void +glm_persp_decomp_y_rh_no(mat4 proj, + float * __restrict top, + float * __restrict bottom) { + float nearZ, m21, m11, m22; + + m21 = proj[2][1]; + m11 = proj[1][1]; + m22 = proj[2][2]; + + nearZ = proj[3][2] / (m22 - 1.0f); + *bottom = nearZ * (m21 - 1.0f) / m11; + *top = nearZ * (m21 + 1.0f) / m11; +} + +/*! + * @brief decomposes near and far values of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * z stands for z axis (near / far axis) + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + */ +CGLM_INLINE +void +glm_persp_decomp_z_rh_no(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ) { + float m32, m22; + + m32 = proj[3][2]; + m22 = proj[2][2]; + + *nearZ = m32 / (m22 - 1.0f); + *farZ = m32 / (m22 + 1.0f); +} + +/*! + * @brief decomposes far value of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] farZ far + */ +CGLM_INLINE +void +glm_persp_decomp_far_rh_no(mat4 proj, float * __restrict farZ) { + *farZ = proj[3][2] / (proj[2][2] + 1.0f); +} + +/*! + * @brief decomposes near value of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + */ +CGLM_INLINE +void +glm_persp_decomp_near_rh_no(mat4 proj, float * __restrict nearZ) { + *nearZ = proj[3][2] / (proj[2][2] - 1.0f); +} + +/*! + * @brief returns sizes of near and far planes of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[in] fovy fovy (see brief) + * @param[out] dest sizes order: [Wnear, Hnear, Wfar, Hfar] + */ +CGLM_INLINE +void +glm_persp_sizes_rh_no(mat4 proj, float fovy, vec4 dest) { + float t, a, nearZ, farZ; + + t = 2.0f * tanf(fovy * 0.5f); + a = glm_persp_aspect(proj); + + glm_persp_decomp_z_rh_no(proj, &nearZ, &farZ); + + dest[1] = t * nearZ; + dest[3] = t * farZ; + dest[0] = a * dest[1]; + dest[2] = a * dest[3]; +} + +/*! + * @brief returns field of view angle along the Y-axis (in radians) + * with a right-hand coordinate system and a clip-space of [-1, 1]. + * + * if you need to degrees, use glm_deg to convert it or use this: + * fovy_deg = glm_deg(glm_persp_fovy(projMatrix)) + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glm_persp_fovy_rh_no(mat4 proj) { + return glm_persp_fovy(proj); +} + +/*! + * @brief returns aspect ratio of perspective projection + * with a right-hand coordinate system and a clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glm_persp_aspect_rh_no(mat4 proj) { + return glm_persp_aspect(proj); +} + +#endif /*cglm_cam_rh_no_h*/ diff --git a/external/cglm/clipspace/persp_rh_zo.h b/external/cglm/clipspace/persp_rh_zo.h new file mode 100644 index 0000000..ce632b3 --- /dev/null +++ b/external/cglm/clipspace/persp_rh_zo.h @@ -0,0 +1,389 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_frustum_rh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) + CGLM_INLINE void glm_perspective_rh_zo(float fovy, + float aspect, + float nearZ, + float farZ, + mat4 dest) + CGLM_INLINE void glm_perspective_default_rh_zo(float aspect, mat4 dest) + CGLM_INLINE void glm_perspective_resize_rh_zo(float aspect, mat4 proj) + CGLM_INLINE void glm_persp_move_far_rh_zo(mat4 proj, + float deltaFar) + CGLM_INLINE void glm_persp_decomp_rh_zo(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ, + float * __restrict top, + float * __restrict bottom, + float * __restrict left, + float * __restrict right) + CGLM_INLINE void glm_persp_decompv_rh_zo(mat4 proj, + float dest[6]) + CGLM_INLINE void glm_persp_decomp_x_rh_zo(mat4 proj, + float * __restrict left, + float * __restrict right) + CGLM_INLINE void glm_persp_decomp_y_rh_zo(mat4 proj, + float * __restrict top, + float * __restrict bottom) + CGLM_INLINE void glm_persp_decomp_z_rh_zo(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ) + CGLM_INLINE void glm_persp_decomp_far_rh_zo(mat4 proj, float * __restrict farZ) + CGLM_INLINE void glm_persp_decomp_near_rh_zo(mat4 proj, float * __restrict nearZ) + CGLM_INLINE void glm_persp_sizes_rh_zo(mat4 proj, float fovy, vec4 dest) + */ + +#ifndef cglm_persp_rh_zo_h +#define cglm_persp_rh_zo_h + +#include "../common.h" +#include "persp.h" + +/*! + * @brief set up perspective peprojection matrix with a right-hand coordinate + * system and a clip-space of [0, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_frustum_rh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ, + mat4 dest) { + float rl, tb, fn, nv; + + glm_mat4_zero(dest); + + rl = 1.0f / (right - left); + tb = 1.0f / (top - bottom); + fn =-1.0f / (farZ - nearZ); + nv = 2.0f * nearZ; + + dest[0][0] = nv * rl; + dest[1][1] = nv * tb; + dest[2][0] = (right + left) * rl; + dest[2][1] = (top + bottom) * tb; + dest[2][2] = farZ * fn; + dest[2][3] =-1.0f; + dest[3][2] = farZ * nearZ * fn; +} + +/*! + * @brief set up perspective projection matrix with a right-hand coordinate + * system and a clip-space of [0, 1]. + * + * @param[in] fovy field of view angle + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping planes + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_perspective_rh_zo(float fovy, + float aspect, + float nearZ, + float farZ, + mat4 dest) { + float f, fn; + + glm_mat4_zero(dest); + + f = 1.0f / tanf(fovy * 0.5f); + fn = 1.0f / (nearZ - farZ); + + dest[0][0] = f / aspect; + dest[1][1] = f; + dest[2][2] = farZ * fn; + dest[2][3] =-1.0f; + dest[3][2] = nearZ * farZ * fn; +} + +/*! + * @brief set up perspective projection matrix with default near/far + * and angle values with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_perspective_default_rh_zo(float aspect, mat4 dest) { + glm_perspective_rh_zo(GLM_PI_4f, aspect, 0.01f, 100.0f, dest); +} + +/*! + * @brief resize perspective matrix by aspect ratio ( width / height ) + * this makes very easy to resize proj matrix when window /viewport + * resized with a right-hand coordinate system and a clip-space of + * [0, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in, out] proj perspective projection matrix + */ +CGLM_INLINE +void +glm_perspective_resize_rh_zo(float aspect, mat4 proj) { + if (proj[0][0] == 0.0f) + return; + + proj[0][0] = proj[1][1] / aspect; +} + +/*! + * @brief extend perspective projection matrix's far distance with a + * right-hand coordinate system and a clip-space of [0, 1]. + * + * this function does not guarantee far >= near, be aware of that! + * + * @param[in, out] proj projection matrix to extend + * @param[in] deltaFar distance from existing far (negative to shink) + */ +CGLM_INLINE +void +glm_persp_move_far_rh_zo(mat4 proj, float deltaFar) { + float fn, farZ, nearZ, p22, p32; + + p22 = proj[2][2]; + p32 = proj[3][2]; + + nearZ = p32 / p22; + farZ = p32 / (p22 + 1.0f) + deltaFar; + fn = 1.0f / (nearZ - farZ); + + proj[2][2] = farZ * fn; + proj[3][2] = nearZ * farZ * fn; +} + +/*! + * @brief decomposes frustum values of perspective projection + * with angle values with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + * @param[out] top top + * @param[out] bottom bottom + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glm_persp_decomp_rh_zo(mat4 proj, + float * __restrict nearZ, float * __restrict farZ, + float * __restrict top, float * __restrict bottom, + float * __restrict left, float * __restrict right) { + float m00, m11, m20, m21, m22, m32, n, f; + float n_m11, n_m00; + + m00 = proj[0][0]; + m11 = proj[1][1]; + m20 = proj[2][0]; + m21 = proj[2][1]; + m22 = proj[2][2]; + m32 = proj[3][2]; + + n = m32 / m22; + f = m32 / (m22 + 1.0f); + + n_m11 = n / m11; + n_m00 = n / m00; + + *nearZ = n; + *farZ = f; + *bottom = n_m11 * (m21 - 1.0f); + *top = n_m11 * (m21 + 1.0f); + *left = n_m00 * (m20 - 1.0f); + *right = n_m00 * (m20 + 1.0f); +} + +/*! + * @brief decomposes frustum values of perspective projection + * with angle values with a right-hand coordinate system and a + * clip-space of [0, 1]. + * this makes easy to get all values at once + * + * @param[in] proj perspective projection matrix + * @param[out] dest array + */ +CGLM_INLINE +void +glm_persp_decompv_rh_zo(mat4 proj, float dest[6]) { + glm_persp_decomp_rh_zo(proj, &dest[0], &dest[1], &dest[2], + &dest[3], &dest[4], &dest[5]); +} + +/*! + * @brief decomposes left and right values of perspective projection (ZO). + * x stands for x axis (left / right axis) + * + * @param[in] proj perspective projection matrix + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glm_persp_decomp_x_rh_zo(mat4 proj, + float * __restrict left, + float * __restrict right) { + float nearZ, m20, m00, m22; + + m00 = proj[0][0]; + m20 = proj[2][0]; + m22 = proj[2][2]; + + nearZ = proj[3][2] / m22; + *left = nearZ * (m20 - 1.0f) / m00; + *right = nearZ * (m20 + 1.0f) / m00; +} + +/*! + * @brief decomposes top and bottom values of perspective projection + * with angle values with a right-hand coordinate system and a + * clip-space of [0, 1]. + * y stands for y axis (top / bottom axis) + * + * @param[in] proj perspective projection matrix + * @param[out] top top + * @param[out] bottom bottom + */ +CGLM_INLINE +void +glm_persp_decomp_y_rh_zo(mat4 proj, + float * __restrict top, + float * __restrict bottom) { + float nearZ, m21, m11, m22; + + m21 = proj[2][1]; + m11 = proj[1][1]; + m22 = proj[2][2]; + + nearZ = proj[3][2] / m22; + *bottom = nearZ * (m21 - 1) / m11; + *top = nearZ * (m21 + 1) / m11; +} + +/*! + * @brief decomposes near and far values of perspective projection + * with angle values with a right-hand coordinate system and a + * clip-space of [0, 1]. + * z stands for z axis (near / far axis) + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + */ +CGLM_INLINE +void +glm_persp_decomp_z_rh_zo(mat4 proj, + float * __restrict nearZ, + float * __restrict farZ) { + float m32, m22; + + m32 = proj[3][2]; + m22 = proj[2][2]; + + *nearZ = m32 / m22; + *farZ = m32 / (m22 + 1.0f); +} + +/*! + * @brief decomposes far value of perspective projection + * with angle values with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] farZ far + */ +CGLM_INLINE +void +glm_persp_decomp_far_rh_zo(mat4 proj, float * __restrict farZ) { + *farZ = proj[3][2] / (proj[2][2] + 1.0f); +} + +/*! + * @brief decomposes near value of perspective projection + * with angle values with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + */ +CGLM_INLINE +void +glm_persp_decomp_near_rh_zo(mat4 proj, float * __restrict nearZ) { + *nearZ = proj[3][2] / proj[2][2]; +} + +/*! + * @brief returns sizes of near and far planes of perspective projection + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[in] fovy fovy (see brief) + * @param[out] dest sizes order: [Wnear, Hnear, Wfar, Hfar] + */ +CGLM_INLINE +void +glm_persp_sizes_rh_zo(mat4 proj, float fovy, vec4 dest) { + float t, a, nearZ, farZ; + + t = 2.0f * tanf(fovy * 0.5f); + a = glm_persp_aspect(proj); + + glm_persp_decomp_z_rh_zo(proj, &nearZ, &farZ); + + dest[1] = t * nearZ; + dest[3] = t * farZ; + dest[0] = a * dest[1]; + dest[2] = a * dest[3]; +} + +/*! + * @brief returns field of view angle along the Y-axis (in radians) + * with a right-hand coordinate system and a clip-space of [0, 1]. + * + * if you need to degrees, use glm_deg to convert it or use this: + * fovy_deg = glm_deg(glm_persp_fovy(projMatrix)) + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glm_persp_fovy_rh_zo(mat4 proj) { + return glm_persp_fovy(proj); +} + +/*! + * @brief returns aspect ratio of perspective projection + * with a right-hand coordinate system and a clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glm_persp_aspect_rh_zo(mat4 proj) { + return glm_persp_aspect(proj); +} + +#endif /*cglm_persp_rh_zo_h*/ diff --git a/external/cglm/clipspace/project_no.h b/external/cglm/clipspace/project_no.h new file mode 100644 index 0000000..71fbc52 --- /dev/null +++ b/external/cglm/clipspace/project_no.h @@ -0,0 +1,109 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_project_no_h +#define cglm_project_no_h + +#include "../common.h" +#include "../vec3.h" +#include "../vec4.h" +#include "../mat4.h" + +/*! + * @brief maps the specified viewport coordinates into specified space [1] + * the matrix should contain projection matrix. + * + * if you don't have ( and don't want to have ) an inverse matrix then use + * glm_unproject version. You may use existing inverse of matrix in somewhere + * else, this is why glm_unprojecti exists to save save inversion cost + * + * [1] space: + * 1- if m = invProj: View Space + * 2- if m = invViewProj: World Space + * 3- if m = invMVP: Object Space + * + * You probably want to map the coordinates into object space + * so use invMVP as m + * + * Computing viewProj: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * glm_mat4_inv(viewProj, invMVP); + * + * @param[in] pos point/position in viewport coordinates + * @param[in] invMat matrix (see brief) + * @param[in] vp viewport as [x, y, width, height] + * @param[out] dest unprojected coordinates + */ +CGLM_INLINE +void +glm_unprojecti_no(vec3 pos, mat4 invMat, vec4 vp, vec3 dest) { + vec4 v; + + v[0] = 2.0f * (pos[0] - vp[0]) / vp[2] - 1.0f; + v[1] = 2.0f * (pos[1] - vp[1]) / vp[3] - 1.0f; + v[2] = 2.0f * pos[2] - 1.0f; + v[3] = 1.0f; + + glm_mat4_mulv(invMat, v, v); + glm_vec4_scale(v, 1.0f / v[3], v); + glm_vec3(v, dest); +} + +/*! + * @brief map object coordinates to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] pos object coordinates + * @param[in] m MVP matrix + * @param[in] vp viewport as [x, y, width, height] + * @param[out] dest projected coordinates + */ +CGLM_INLINE +void +glm_project_no(vec3 pos, mat4 m, vec4 vp, vec3 dest) { + CGLM_ALIGN(16) vec4 pos4; + + glm_vec4(pos, 1.0f, pos4); + + glm_mat4_mulv(m, pos4, pos4); + glm_vec4_scale(pos4, 1.0f / pos4[3], pos4); /* pos = pos / pos.w */ + glm_vec4_scale(pos4, 0.5f, pos4); + glm_vec4_adds(pos4, 0.5f, pos4); + + dest[0] = pos4[0] * vp[2] + vp[0]; + dest[1] = pos4[1] * vp[3] + vp[1]; + dest[2] = pos4[2]; +} + +/*! + * @brief map object's z coordinate to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] v object coordinates + * @param[in] m MVP matrix + * + * @returns projected z coordinate + */ +CGLM_INLINE +float +glm_project_z_no(vec3 v, mat4 m) { + float z, w; + + z = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2]; + w = m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3]; + + return 0.5f * (z / w) + 0.5f; +} + +#endif /* cglm_project_no_h */ diff --git a/external/cglm/clipspace/project_zo.h b/external/cglm/clipspace/project_zo.h new file mode 100644 index 0000000..dc32078 --- /dev/null +++ b/external/cglm/clipspace/project_zo.h @@ -0,0 +1,111 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_project_zo_h +#define cglm_project_zo_h + +#include "../common.h" +#include "../vec3.h" +#include "../vec4.h" +#include "../mat4.h" + +/*! + * @brief maps the specified viewport coordinates into specified space [1] + * the matrix should contain projection matrix. + * + * if you don't have ( and don't want to have ) an inverse matrix then use + * glm_unproject version. You may use existing inverse of matrix in somewhere + * else, this is why glm_unprojecti exists to save save inversion cost + * + * [1] space: + * 1- if m = invProj: View Space + * 2- if m = invViewProj: World Space + * 3- if m = invMVP: Object Space + * + * You probably want to map the coordinates into object space + * so use invMVP as m + * + * Computing viewProj: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * glm_mat4_inv(viewProj, invMVP); + * + * @param[in] pos point/position in viewport coordinates + * @param[in] invMat matrix (see brief) + * @param[in] vp viewport as [x, y, width, height] + * @param[out] dest unprojected coordinates + */ +CGLM_INLINE +void +glm_unprojecti_zo(vec3 pos, mat4 invMat, vec4 vp, vec3 dest) { + vec4 v; + + v[0] = 2.0f * (pos[0] - vp[0]) / vp[2] - 1.0f; + v[1] = 2.0f * (pos[1] - vp[1]) / vp[3] - 1.0f; + v[2] = pos[2]; + v[3] = 1.0f; + + glm_mat4_mulv(invMat, v, v); + glm_vec4_scale(v, 1.0f / v[3], v); + glm_vec3(v, dest); +} + +/*! + * @brief map object coordinates to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] pos object coordinates + * @param[in] m MVP matrix + * @param[in] vp viewport as [x, y, width, height] + * @param[out] dest projected coordinates + */ +CGLM_INLINE +void +glm_project_zo(vec3 pos, mat4 m, vec4 vp, vec3 dest) { + CGLM_ALIGN(16) vec4 pos4; + + glm_vec4(pos, 1.0f, pos4); + + glm_mat4_mulv(m, pos4, pos4); + glm_vec4_scale(pos4, 1.0f / pos4[3], pos4); /* pos = pos / pos.w */ + + dest[2] = pos4[2]; + + glm_vec4_scale(pos4, 0.5f, pos4); + glm_vec4_adds(pos4, 0.5f, pos4); + + dest[0] = pos4[0] * vp[2] + vp[0]; + dest[1] = pos4[1] * vp[3] + vp[1]; +} + +/*! + * @brief map object's z coordinate to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] v object coordinates + * @param[in] m MVP matrix + * + * @returns projected z coordinate + */ +CGLM_INLINE +float +glm_project_z_zo(vec3 v, mat4 m) { + float z, w; + + z = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2]; + w = m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3]; + + return z / w; +} + +#endif /* cglm_project_zo_h */ diff --git a/external/cglm/clipspace/view_lh.h b/external/cglm/clipspace/view_lh.h new file mode 100644 index 0000000..5667694 --- /dev/null +++ b/external/cglm/clipspace/view_lh.h @@ -0,0 +1,99 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_lookat_lh(vec3 eye, vec3 center, vec3 up, mat4 dest) + CGLM_INLINE void glm_look_lh(vec3 eye, vec3 dir, vec3 up, mat4 dest) + CGLM_INLINE void glm_look_anyup_lh(vec3 eye, vec3 dir, mat4 dest) + */ + +#ifndef cglm_view_lh_h +#define cglm_view_lh_h + +#include "../common.h" +#include "../plane.h" + +/*! + * @brief set up view matrix (LH) + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] center center vector + * @param[in] up up vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_lookat_lh(vec3 eye, vec3 center, vec3 up, mat4 dest) { + CGLM_ALIGN(8) vec3 f, u, s; + + glm_vec3_sub(center, eye, f); + glm_vec3_normalize(f); + + glm_vec3_crossn(up, f, s); + glm_vec3_cross(f, s, u); + + dest[0][0] = s[0]; + dest[0][1] = u[0]; + dest[0][2] = f[0]; + dest[1][0] = s[1]; + dest[1][1] = u[1]; + dest[1][2] = f[1]; + dest[2][0] = s[2]; + dest[2][1] = u[2]; + dest[2][2] = f[2]; + dest[3][0] =-glm_vec3_dot(s, eye); + dest[3][1] =-glm_vec3_dot(u, eye); + dest[3][2] =-glm_vec3_dot(f, eye); + dest[0][3] = dest[1][3] = dest[2][3] = 0.0f; + dest[3][3] = 1.0f; +} + +/*! + * @brief set up view matrix with left handed coordinate system + * + * convenient wrapper for lookat: if you only have direction not target self + * then this might be useful. Because you need to get target from direction. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[in] up up vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_look_lh(vec3 eye, vec3 dir, vec3 up, mat4 dest) { + CGLM_ALIGN(8) vec3 target; + glm_vec3_add(eye, dir, target); + glm_lookat_lh(eye, target, up, dest); +} + +/*! + * @brief set up view matrix with left handed coordinate system + * + * convenient wrapper for look: if you only have direction and if you don't + * care what UP vector is then this might be useful to create view matrix + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_look_anyup_lh(vec3 eye, vec3 dir, mat4 dest) { + CGLM_ALIGN(8) vec3 up; + glm_vec3_ortho(dir, up); + glm_look_lh(eye, dir, up, dest); +} + +#endif /*cglm_view_lh_h*/ diff --git a/external/cglm/clipspace/view_lh_no.h b/external/cglm/clipspace/view_lh_no.h new file mode 100644 index 0000000..454d903 --- /dev/null +++ b/external/cglm/clipspace/view_lh_no.h @@ -0,0 +1,74 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_lookat_lh_no(vec3 eye, vec3 center, vec3 up, mat4 dest) + CGLM_INLINE void glm_look_lh_no(vec3 eye, vec3 dir, vec3 up, mat4 dest) + CGLM_INLINE void glm_look_anyup_lh_no(vec3 eye, vec3 dir, mat4 dest) + */ + +#ifndef cglm_view_lh_no_h +#define cglm_view_lh_no_h + +#include "../common.h" +#include "view_lh.h" + +/*! + * @brief set up view matrix with left handed coordinate system. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] center center vector + * @param[in] up up vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_lookat_lh_no(vec3 eye, vec3 center, vec3 up, mat4 dest) { + glm_lookat_lh(eye, center, up, dest); +} + +/*! + * @brief set up view matrix with left handed coordinate system. + * + * convenient wrapper for lookat: if you only have direction not target self + * then this might be useful. Because you need to get target from direction. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[in] up up vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_look_lh_no(vec3 eye, vec3 dir, vec3 up, mat4 dest) { + glm_look_lh(eye, dir, up, dest); +} + +/*! + * @brief set up view matrix with left handed coordinate system. + * + * convenient wrapper for look: if you only have direction and if you don't + * care what UP vector is then this might be useful to create view matrix + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_look_anyup_lh_no(vec3 eye, vec3 dir, mat4 dest) { + glm_look_anyup_lh(eye, dir, dest); +} + +#endif /*cglm_view_lh_no_h*/ diff --git a/external/cglm/clipspace/view_lh_zo.h b/external/cglm/clipspace/view_lh_zo.h new file mode 100644 index 0000000..6b0c4d1 --- /dev/null +++ b/external/cglm/clipspace/view_lh_zo.h @@ -0,0 +1,74 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_lookat_lh_zo(vec3 eye, vec3 center, vec3 up, mat4 dest) + CGLM_INLINE void glm_look_lh_zo(vec3 eye, vec3 dir, vec3 up, mat4 dest) + CGLM_INLINE void glm_look_anyup_lh_zo(vec3 eye, vec3 dir, mat4 dest) + */ + +#ifndef cglm_view_lh_zo_h +#define cglm_view_lh_zo_h + +#include "../common.h" +#include "view_lh.h" + +/*! + * @brief set up view matrix with left handed coordinate system. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] center center vector + * @param[in] up up vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_lookat_lh_zo(vec3 eye, vec3 center, vec3 up, mat4 dest) { + glm_lookat_lh(eye, center, up, dest); +} + +/*! + * @brief set up view matrix with left handed coordinate system. + * + * convenient wrapper for lookat: if you only have direction not target self + * then this might be useful. Because you need to get target from direction. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[in] up up vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_look_lh_zo(vec3 eye, vec3 dir, vec3 up, mat4 dest) { + glm_look_lh(eye, dir, up, dest); +} + +/*! + * @brief set up view matrix with left handed coordinate system. + * + * convenient wrapper for look: if you only have direction and if you don't + * care what UP vector is then this might be useful to create view matrix + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_look_anyup_lh_zo(vec3 eye, vec3 dir, mat4 dest) { + glm_look_anyup_lh(eye, dir, dest); +} + +#endif /*cglm_view_lh_zo_h*/ diff --git a/external/cglm/clipspace/view_rh.h b/external/cglm/clipspace/view_rh.h new file mode 100644 index 0000000..51ec916 --- /dev/null +++ b/external/cglm/clipspace/view_rh.h @@ -0,0 +1,99 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_lookat_rh(vec3 eye, vec3 center, vec3 up, mat4 dest) + CGLM_INLINE void glm_look_rh(vec3 eye, vec3 dir, vec3 up, mat4 dest) + CGLM_INLINE void glm_look_anyup_rh(vec3 eye, vec3 dir, mat4 dest) + */ + +#ifndef cglm_view_rh_h +#define cglm_view_rh_h + +#include "../common.h" +#include "../plane.h" + +/*! + * @brief set up view matrix with right handed coordinate system. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] center center vector + * @param[in] up up vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_lookat_rh(vec3 eye, vec3 center, vec3 up, mat4 dest) { + CGLM_ALIGN(8) vec3 f, u, s; + + glm_vec3_sub(center, eye, f); + glm_vec3_normalize(f); + + glm_vec3_crossn(f, up, s); + glm_vec3_cross(s, f, u); + + dest[0][0] = s[0]; + dest[0][1] = u[0]; + dest[0][2] =-f[0]; + dest[1][0] = s[1]; + dest[1][1] = u[1]; + dest[1][2] =-f[1]; + dest[2][0] = s[2]; + dest[2][1] = u[2]; + dest[2][2] =-f[2]; + dest[3][0] =-glm_vec3_dot(s, eye); + dest[3][1] =-glm_vec3_dot(u, eye); + dest[3][2] = glm_vec3_dot(f, eye); + dest[0][3] = dest[1][3] = dest[2][3] = 0.0f; + dest[3][3] = 1.0f; +} + +/*! + * @brief set up view matrix with right handed coordinate system. + * + * convenient wrapper for lookat: if you only have direction not target self + * then this might be useful. Because you need to get target from direction. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[in] up up vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_look_rh(vec3 eye, vec3 dir, vec3 up, mat4 dest) { + CGLM_ALIGN(8) vec3 target; + glm_vec3_add(eye, dir, target); + glm_lookat_rh(eye, target, up, dest); +} + +/*! + * @brief set up view matrix with right handed coordinate system. + * + * convenient wrapper for look: if you only have direction and if you don't + * care what UP vector is then this might be useful to create view matrix + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_look_anyup_rh(vec3 eye, vec3 dir, mat4 dest) { + CGLM_ALIGN(8) vec3 up; + glm_vec3_ortho(dir, up); + glm_look_rh(eye, dir, up, dest); +} + +#endif /*cglm_view_rh_h*/ diff --git a/external/cglm/clipspace/view_rh_no.h b/external/cglm/clipspace/view_rh_no.h new file mode 100644 index 0000000..ca36d30 --- /dev/null +++ b/external/cglm/clipspace/view_rh_no.h @@ -0,0 +1,74 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_lookat_rh_no(vec3 eye, vec3 center, vec3 up, mat4 dest) + CGLM_INLINE void glm_look_rh_no(vec3 eye, vec3 dir, vec3 up, mat4 dest) + CGLM_INLINE void glm_look_anyup_rh_no(vec3 eye, vec3 dir, mat4 dest) + */ + +#ifndef cglm_view_rh_no_h +#define cglm_view_rh_no_h + +#include "../common.h" +#include "view_rh.h" + +/*! + * @brief set up view matrix with right handed coordinate system. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] center center vector + * @param[in] up up vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_lookat_rh_no(vec3 eye, vec3 center, vec3 up, mat4 dest) { + glm_lookat_rh(eye, center, up, dest); +} + +/*! + * @brief set up view matrix with right handed coordinate system. + * + * convenient wrapper for lookat: if you only have direction not target self + * then this might be useful. Because you need to get target from direction. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[in] up up vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_look_rh_no(vec3 eye, vec3 dir, vec3 up, mat4 dest) { + glm_look_rh(eye, dir, up, dest); +} + +/*! + * @brief set up view matrix with right handed coordinate system. + * + * convenient wrapper for look: if you only have direction and if you don't + * care what UP vector is then this might be useful to create view matrix + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_look_anyup_rh_no(vec3 eye, vec3 dir, mat4 dest) { + glm_look_anyup_rh(eye, dir, dest); +} + +#endif /*cglm_view_rh_no_h*/ diff --git a/external/cglm/clipspace/view_rh_zo.h b/external/cglm/clipspace/view_rh_zo.h new file mode 100644 index 0000000..1ad5c91 --- /dev/null +++ b/external/cglm/clipspace/view_rh_zo.h @@ -0,0 +1,74 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_lookat_rh_zo(vec3 eye, vec3 center, vec3 up, mat4 dest) + CGLM_INLINE void glm_look_rh_zo(vec3 eye, vec3 dir, vec3 up, mat4 dest) + CGLM_INLINE void glm_look_anyup_rh_zo(vec3 eye, vec3 dir, mat4 dest) + */ + +#ifndef cglm_view_rh_zo_h +#define cglm_view_rh_zo_h + +#include "../common.h" +#include "view_rh.h" + +/*! + * @brief set up view matrix with right handed coordinate system. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] center center vector + * @param[in] up up vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_lookat_rh_zo(vec3 eye, vec3 center, vec3 up, mat4 dest) { + glm_lookat_rh(eye, center, up, dest); +} + +/*! + * @brief set up view matrix with right handed coordinate system. + * + * convenient wrapper for lookat: if you only have direction not target self + * then this might be useful. Because you need to get target from direction. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[in] up up vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_look_rh_zo(vec3 eye, vec3 dir, vec3 up, mat4 dest) { + glm_look_rh(eye, dir, up, dest); +} + +/*! + * @brief set up view matrix with right handed coordinate system. + * + * convenient wrapper for look: if you only have direction and if you don't + * care what UP vector is then this might be useful to create view matrix + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_look_anyup_rh_zo(vec3 eye, vec3 dir, mat4 dest) { + glm_look_anyup_rh(eye, dir, dest); +} + +#endif /*cglm_view_rh_zo_h*/ diff --git a/external/cglm/color.h b/external/cglm/color.h new file mode 100644 index 0000000..69566ad --- /dev/null +++ b/external/cglm/color.h @@ -0,0 +1,26 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_color_h +#define cglm_color_h + +#include "common.h" +#include "vec3.h" + +/*! + * @brief averages the color channels into one value + * + * @param[in] rgb RGB color + */ +CGLM_INLINE +float +glm_luminance(vec3 rgb) { + vec3 l = {0.212671f, 0.715160f, 0.072169f}; + return glm_dot(rgb, l); +} + +#endif /* cglm_color_h */ diff --git a/external/cglm/common.h b/external/cglm/common.h new file mode 100644 index 0000000..1af754d --- /dev/null +++ b/external/cglm/common.h @@ -0,0 +1,130 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_common_h +#define cglm_common_h + +#define __cglm__ 1 + +#ifndef _USE_MATH_DEFINES +# define _USE_MATH_DEFINES /* for windows */ +#endif + +#ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS /* for windows */ +#endif + +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) +# ifdef CGLM_STATIC +# define CGLM_EXPORT +# elif defined(CGLM_EXPORTS) +# define CGLM_EXPORT __declspec(dllexport) +# else +# define CGLM_EXPORT __declspec(dllimport) +# endif +# define CGLM_INLINE __forceinline +#else +# define CGLM_EXPORT __attribute__((visibility("default"))) +# define CGLM_INLINE static inline __attribute((always_inline)) +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define CGLM_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +# define CGLM_LIKELY(expr) __builtin_expect(!!(expr), 1) +#else +# define CGLM_UNLIKELY(expr) (expr) +# define CGLM_LIKELY(expr) (expr) +#endif + +#if defined(_M_FP_FAST) || defined(__FAST_MATH__) +# define CGLM_FAST_MATH +#endif + +#define GLM_SHUFFLE4(z, y, x, w) (((z) << 6) | ((y) << 4) | ((x) << 2) | (w)) +#define GLM_SHUFFLE3(z, y, x) (((z) << 4) | ((y) << 2) | (x)) +#define GLM_SHUFFLE2(y, x) (((y) << 2) | (x)) + +#include "types.h" +#include "simd/intrin.h" + +#ifndef CGLM_USE_DEFAULT_EPSILON +# ifndef GLM_FLT_EPSILON +# define GLM_FLT_EPSILON 1e-5f +# endif +#else +# define GLM_FLT_EPSILON FLT_EPSILON +#endif + +/* + * Clip control: define CGLM_FORCE_DEPTH_ZERO_TO_ONE before including + * CGLM to use a clip space between 0 to 1. + * Coordinate system: define CGLM_FORCE_LEFT_HANDED before including + * CGLM to use the left handed coordinate system by default. + */ + +#define CGLM_CLIP_CONTROL_ZO_BIT (1 << 0) /* ZERO_TO_ONE */ +#define CGLM_CLIP_CONTROL_NO_BIT (1 << 1) /* NEGATIVE_ONE_TO_ONE */ +#define CGLM_CLIP_CONTROL_LH_BIT (1 << 2) /* LEFT_HANDED, For DirectX, Metal, Vulkan */ +#define CGLM_CLIP_CONTROL_RH_BIT (1 << 3) /* RIGHT_HANDED, For OpenGL, default in GLM */ + +#define CGLM_CLIP_CONTROL_LH_ZO (CGLM_CLIP_CONTROL_LH_BIT | CGLM_CLIP_CONTROL_ZO_BIT) +#define CGLM_CLIP_CONTROL_LH_NO (CGLM_CLIP_CONTROL_LH_BIT | CGLM_CLIP_CONTROL_NO_BIT) +#define CGLM_CLIP_CONTROL_RH_ZO (CGLM_CLIP_CONTROL_RH_BIT | CGLM_CLIP_CONTROL_ZO_BIT) +#define CGLM_CLIP_CONTROL_RH_NO (CGLM_CLIP_CONTROL_RH_BIT | CGLM_CLIP_CONTROL_NO_BIT) + +#ifdef CGLM_FORCE_DEPTH_ZERO_TO_ONE +# ifdef CGLM_FORCE_LEFT_HANDED +# define CGLM_CONFIG_CLIP_CONTROL CGLM_CLIP_CONTROL_LH_ZO +# else +# define CGLM_CONFIG_CLIP_CONTROL CGLM_CLIP_CONTROL_RH_ZO +# endif +#else +# ifdef CGLM_FORCE_LEFT_HANDED +# define CGLM_CONFIG_CLIP_CONTROL CGLM_CLIP_CONTROL_LH_NO +# else +# define CGLM_CONFIG_CLIP_CONTROL CGLM_CLIP_CONTROL_RH_NO +# endif +#endif + +/* struct API configurator */ +/* TODO: move struct/common.h? */ +/* WARN: dont use concant helpers outside cglm headers, because they may be changed */ + +#define CGLM_MACRO_CONCAT_HELPER(A, B, C, D, E, ...) A ## B ## C ## D ## E ## __VA_ARGS__ +#define CGLM_MACRO_CONCAT(A, B, C, D, E, ...) CGLM_MACRO_CONCAT_HELPER(A, B, C, D, E,__VA_ARGS__) + +#ifndef CGLM_OMIT_NS_FROM_STRUCT_API +# ifndef CGLM_STRUCT_API_NS +# define CGLM_STRUCT_API_NS glms +# endif +# ifndef CGLM_STRUCT_API_NS_SEPERATOR +# define CGLM_STRUCT_API_NS_SEPERATOR _ +# endif +#else +# define CGLM_STRUCT_API_NS +# define CGLM_STRUCT_API_NS_SEPERATOR +#endif + +#ifndef CGLM_STRUCT_API_NAME_SUFFIX +# define CGLM_STRUCT_API_NAME_SUFFIX +#endif + +#define CGLM_STRUCTAPI(A, ...) CGLM_MACRO_CONCAT(CGLM_STRUCT_API_NS, \ + CGLM_STRUCT_API_NS_SEPERATOR, \ + A, \ + CGLM_STRUCT_API_NAME_SUFFIX, \ + _, \ + __VA_ARGS__) + +#endif /* cglm_common_h */ diff --git a/external/cglm/curve.h b/external/cglm/curve.h new file mode 100644 index 0000000..5033be5 --- /dev/null +++ b/external/cglm/curve.h @@ -0,0 +1,40 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_curve_h +#define cglm_curve_h + +#include "common.h" +#include "vec4.h" +#include "mat4.h" + +/*! + * @brief helper function to calculate S*M*C multiplication for curves + * + * This function does not encourage you to use SMC, + * instead it is a helper if you use SMC. + * + * if you want to specify S as vector then use more generic glm_mat4_rmc() func. + * + * Example usage: + * B(s) = glm_smc(s, GLM_BEZIER_MAT, (vec4){p0, c0, c1, p1}) + * + * @param[in] s parameter between 0 and 1 (this will be [s3, s2, s, 1]) + * @param[in] m basis matrix + * @param[in] c position/control vector + * + * @return B(s) + */ +CGLM_INLINE +float +glm_smc(float s, mat4 m, vec4 c) { + vec4 vs; + glm_vec4_cubic(s, vs); + return glm_mat4_rmc(vs, m, c); +} + +#endif /* cglm_curve_h */ diff --git a/external/cglm/ease.h b/external/cglm/ease.h new file mode 100644 index 0000000..e26b48c --- /dev/null +++ b/external/cglm/ease.h @@ -0,0 +1,317 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_ease_h +#define cglm_ease_h + +#include "common.h" + +CGLM_INLINE +float +glm_ease_linear(float t) { + return t; +} + +CGLM_INLINE +float +glm_ease_sine_in(float t) { + return sinf((t - 1.0f) * GLM_PI_2f) + 1.0f; +} + +CGLM_INLINE +float +glm_ease_sine_out(float t) { + return sinf(t * GLM_PI_2f); +} + +CGLM_INLINE +float +glm_ease_sine_inout(float t) { + return 0.5f * (1.0f - cosf(t * GLM_PIf)); +} + +CGLM_INLINE +float +glm_ease_quad_in(float t) { + return t * t; +} + +CGLM_INLINE +float +glm_ease_quad_out(float t) { + return -(t * (t - 2.0f)); +} + +CGLM_INLINE +float +glm_ease_quad_inout(float t) { + float tt; + + tt = t * t; + if (t < 0.5f) + return 2.0f * tt; + + return (-2.0f * tt) + (4.0f * t) - 1.0f; +} + +CGLM_INLINE +float +glm_ease_cubic_in(float t) { + return t * t * t; +} + +CGLM_INLINE +float +glm_ease_cubic_out(float t) { + float f; + f = t - 1.0f; + return f * f * f + 1.0f; +} + +CGLM_INLINE +float +glm_ease_cubic_inout(float t) { + float f; + + if (t < 0.5f) + return 4.0f * t * t * t; + + f = 2.0f * t - 2.0f; + + return 0.5f * f * f * f + 1.0f; +} + +CGLM_INLINE +float +glm_ease_quart_in(float t) { + float f; + f = t * t; + return f * f; +} + +CGLM_INLINE +float +glm_ease_quart_out(float t) { + float f; + + f = t - 1.0f; + + return f * f * f * (1.0f - t) + 1.0f; +} + +CGLM_INLINE +float +glm_ease_quart_inout(float t) { + float f, g; + + if (t < 0.5f) { + f = t * t; + return 8.0f * f * f; + } + + f = t - 1.0f; + g = f * f; + + return -8.0f * g * g + 1.0f; +} + +CGLM_INLINE +float +glm_ease_quint_in(float t) { + float f; + f = t * t; + return f * f * t; +} + +CGLM_INLINE +float +glm_ease_quint_out(float t) { + float f, g; + + f = t - 1.0f; + g = f * f; + + return g * g * f + 1.0f; +} + +CGLM_INLINE +float +glm_ease_quint_inout(float t) { + float f, g; + + if (t < 0.5f) { + f = t * t; + return 16.0f * f * f * t; + } + + f = 2.0f * t - 2.0f; + g = f * f; + + return 0.5f * g * g * f + 1.0f; +} + +CGLM_INLINE +float +glm_ease_exp_in(float t) { + if (t == 0.0f) + return t; + + return powf(2.0f, 10.0f * (t - 1.0f)); +} + +CGLM_INLINE +float +glm_ease_exp_out(float t) { + if (t == 1.0f) + return t; + + return 1.0f - powf(2.0f, -10.0f * t); +} + +CGLM_INLINE +float +glm_ease_exp_inout(float t) { + if (t == 0.0f || t == 1.0f) + return t; + + if (t < 0.5f) + return 0.5f * powf(2.0f, (20.0f * t) - 10.0f); + + return -0.5f * powf(2.0f, (-20.0f * t) + 10.0f) + 1.0f; +} + +CGLM_INLINE +float +glm_ease_circ_in(float t) { + return 1.0f - sqrtf(1.0f - (t * t)); +} + +CGLM_INLINE +float +glm_ease_circ_out(float t) { + return sqrtf((2.0f - t) * t); +} + +CGLM_INLINE +float +glm_ease_circ_inout(float t) { + if (t < 0.5f) + return 0.5f * (1.0f - sqrtf(1.0f - 4.0f * (t * t))); + + return 0.5f * (sqrtf(-((2.0f * t) - 3.0f) * ((2.0f * t) - 1.0f)) + 1.0f); +} + +CGLM_INLINE +float +glm_ease_back_in(float t) { + float o, z; + + o = 1.70158f; + z = ((o + 1.0f) * t) - o; + + return t * t * z; +} + +CGLM_INLINE +float +glm_ease_back_out(float t) { + float o, z, n; + + o = 1.70158f; + n = t - 1.0f; + z = (o + 1.0f) * n + o; + + return n * n * z + 1.0f; +} + +CGLM_INLINE +float +glm_ease_back_inout(float t) { + float o, z, n, m, s, x; + + o = 1.70158f; + s = o * 1.525f; + x = 0.5f; + n = t / 0.5f; + + if (n < 1.0f) { + z = (s + 1) * n - s; + m = n * n * z; + return x * m; + } + + n -= 2.0f; + z = (s + 1.0f) * n + s; + m = (n * n * z) + 2; + + return x * m; +} + +CGLM_INLINE +float +glm_ease_elast_in(float t) { + return sinf(13.0f * GLM_PI_2f * t) * powf(2.0f, 10.0f * (t - 1.0f)); +} + +CGLM_INLINE +float +glm_ease_elast_out(float t) { + return sinf(-13.0f * GLM_PI_2f * (t + 1.0f)) * powf(2.0f, -10.0f * t) + 1.0f; +} + +CGLM_INLINE +float +glm_ease_elast_inout(float t) { + float a; + + a = 2.0f * t; + + if (t < 0.5f) + return 0.5f * sinf(13.0f * GLM_PI_2f * a) + * powf(2.0f, 10.0f * (a - 1.0f)); + + return 0.5f * (sinf(-13.0f * GLM_PI_2f * a) + * powf(2.0f, -10.0f * (a - 1.0f)) + 2.0f); +} + +CGLM_INLINE +float +glm_ease_bounce_out(float t) { + float tt; + + tt = t * t; + + if (t < (4.0f / 11.0f)) + return (121.0f * tt) / 16.0f; + + if (t < 8.0f / 11.0f) + return ((363.0f / 40.0f) * tt) - ((99.0f / 10.0f) * t) + (17.0f / 5.0f); + + if (t < (9.0f / 10.0f)) + return (4356.0f / 361.0f) * tt + - (35442.0f / 1805.0f) * t + + (16061.0f / 1805.0f); + + return ((54.0f / 5.0f) * tt) - ((513.0f / 25.0f) * t) + (268.0f / 25.0f); +} + +CGLM_INLINE +float +glm_ease_bounce_in(float t) { + return 1.0f - glm_ease_bounce_out(1.0f - t); +} + +CGLM_INLINE +float +glm_ease_bounce_inout(float t) { + if (t < 0.5f) + return 0.5f * (1.0f - glm_ease_bounce_out(t * 2.0f)); + + return 0.5f * glm_ease_bounce_out(t * 2.0f - 1.0f) + 0.5f; +} + +#endif /* cglm_ease_h */ diff --git a/external/cglm/euler.h b/external/cglm/euler.h new file mode 100644 index 0000000..8fae039 --- /dev/null +++ b/external/cglm/euler.h @@ -0,0 +1,601 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + NOTE: + angles must be passed as [X-Angle, Y-Angle, Z-angle] order + For instance you don't pass angles as [Z-Angle, X-Angle, Y-angle] to + glm_euler_zxy function, All RELATED functions accept angles same order + which is [X, Y, Z]. + */ + +/* + Types: + enum glm_euler_seq + + Functions: + CGLM_INLINE glm_euler_seq glm_euler_order(int newOrder[3]); + CGLM_INLINE void glm_euler_angles(mat4 m, vec3 dest); + CGLM_INLINE void glm_euler(vec3 angles, mat4 dest); + CGLM_INLINE void glm_euler_xyz(vec3 angles, mat4 dest); + CGLM_INLINE void glm_euler_zyx(vec3 angles, mat4 dest); + CGLM_INLINE void glm_euler_zxy(vec3 angles, mat4 dest); + CGLM_INLINE void glm_euler_xzy(vec3 angles, mat4 dest); + CGLM_INLINE void glm_euler_yzx(vec3 angles, mat4 dest); + CGLM_INLINE void glm_euler_yxz(vec3 angles, mat4 dest); + CGLM_INLINE void glm_euler_by_order(vec3 angles, + glm_euler_seq ord, + mat4 dest); + CGLM_INLINE void glm_euler_xyz_quat(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_xzy_quat(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_yxz_quat(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_yzx_quat(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_zxy_quat(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_zyx_quat(vec3 angles, versor dest); + */ + +#ifndef cglm_euler_h +#define cglm_euler_h + +#include "common.h" + +#ifdef CGLM_FORCE_LEFT_HANDED +# include "handed/euler_to_quat_lh.h" +#else +# include "handed/euler_to_quat_rh.h" +#endif + + +#ifndef CGLM_CLIPSPACE_INCLUDE_ALL +# if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO +# include "clipspace/ortho_lh_zo.h" +# include "clipspace/persp_lh_zo.h" +# include "clipspace/view_lh_zo.h" +# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO +# include "clipspace/ortho_lh_no.h" +# include "clipspace/persp_lh_no.h" +# include "clipspace/view_lh_no.h" +# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO +# include "clipspace/ortho_rh_zo.h" +# include "clipspace/persp_rh_zo.h" +# include "clipspace/view_rh_zo.h" +# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO +# include "clipspace/ortho_rh_no.h" +# include "clipspace/persp_rh_no.h" +# include "clipspace/view_rh_no.h" +# endif +#else +# include "clipspace/ortho_lh_zo.h" +# include "clipspace/persp_lh_zo.h" +# include "clipspace/ortho_lh_no.h" +# include "clipspace/persp_lh_no.h" +# include "clipspace/ortho_rh_zo.h" +# include "clipspace/persp_rh_zo.h" +# include "clipspace/ortho_rh_no.h" +# include "clipspace/persp_rh_no.h" +# include "clipspace/view_lh_zo.h" +# include "clipspace/view_lh_no.h" +# include "clipspace/view_rh_zo.h" +# include "clipspace/view_rh_no.h" +#endif + + +/*! + * if you have axis order like vec3 orderVec = [0, 1, 2] or [0, 2, 1]... + * vector then you can convert it to this enum by doing this: + * @code + * glm_euler_seq order; + * order = orderVec[0] | orderVec[1] << 2 | orderVec[2] << 4; + * @endcode + * you may need to explicit cast if required + */ +typedef enum glm_euler_seq { + GLM_EULER_XYZ = 0 << 0 | 1 << 2 | 2 << 4, + GLM_EULER_XZY = 0 << 0 | 2 << 2 | 1 << 4, + GLM_EULER_YZX = 1 << 0 | 2 << 2 | 0 << 4, + GLM_EULER_YXZ = 1 << 0 | 0 << 2 | 2 << 4, + GLM_EULER_ZXY = 2 << 0 | 0 << 2 | 1 << 4, + GLM_EULER_ZYX = 2 << 0 | 1 << 2 | 0 << 4 +} glm_euler_seq; + +CGLM_INLINE +glm_euler_seq +glm_euler_order(int ord[3]) { + return (glm_euler_seq)(ord[0] << 0 | ord[1] << 2 | ord[2] << 4); +} + +/*! + * @brief extract euler angles (in radians) using xyz order + * + * @param[in] m affine transform + * @param[out] dest angles vector [x, y, z] + */ +CGLM_INLINE +void +glm_euler_angles(mat4 m, vec3 dest) { + float m00, m01, m10, m11, m20, m21, m22; + float thetaX, thetaY, thetaZ; + + m00 = m[0][0]; m10 = m[1][0]; m20 = m[2][0]; + m01 = m[0][1]; m11 = m[1][1]; m21 = m[2][1]; + m22 = m[2][2]; + + if (m20 < 1.0f) { + if (m20 > -1.0f) { + thetaY = asinf(m20); + thetaX = atan2f(-m21, m22); + thetaZ = atan2f(-m10, m00); + } else { /* m20 == -1 */ + /* Not a unique solution */ + thetaY = -GLM_PI_2f; + thetaX = -atan2f(m01, m11); + thetaZ = 0.0f; + } + } else { /* m20 == +1 */ + thetaY = GLM_PI_2f; + thetaX = atan2f(m01, m11); + thetaZ = 0.0f; + } + + dest[0] = thetaX; + dest[1] = thetaY; + dest[2] = thetaZ; +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @param[out] dest rotation matrix + */ +CGLM_INLINE +void +glm_euler_xyz(vec3 angles, mat4 dest) { + float cx, cy, cz, + sx, sy, sz, czsx, cxcz, sysz; + + sx = sinf(angles[0]); cx = cosf(angles[0]); + sy = sinf(angles[1]); cy = cosf(angles[1]); + sz = sinf(angles[2]); cz = cosf(angles[2]); + + czsx = cz * sx; + cxcz = cx * cz; + sysz = sy * sz; + + dest[0][0] = cy * cz; + dest[0][1] = czsx * sy + cx * sz; + dest[0][2] = -cxcz * sy + sx * sz; + dest[1][0] = -cy * sz; + dest[1][1] = cxcz - sx * sysz; + dest[1][2] = czsx + cx * sysz; + dest[2][0] = sy; + dest[2][1] = -cy * sx; + dest[2][2] = cx * cy; + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @param[out] dest rotation matrix + */ +CGLM_INLINE +void +glm_euler(vec3 angles, mat4 dest) { + glm_euler_xyz(angles, dest); +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @param[out] dest rotation matrix + */ +CGLM_INLINE +void +glm_euler_xzy(vec3 angles, mat4 dest) { + float cx, cy, cz, + sx, sy, sz, sxsy, cysx, cxsy, cxcy; + + sx = sinf(angles[0]); cx = cosf(angles[0]); + sy = sinf(angles[1]); cy = cosf(angles[1]); + sz = sinf(angles[2]); cz = cosf(angles[2]); + + sxsy = sx * sy; + cysx = cy * sx; + cxsy = cx * sy; + cxcy = cx * cy; + + dest[0][0] = cy * cz; + dest[0][1] = sxsy + cxcy * sz; + dest[0][2] = -cxsy + cysx * sz; + dest[1][0] = -sz; + dest[1][1] = cx * cz; + dest[1][2] = cz * sx; + dest[2][0] = cz * sy; + dest[2][1] = -cysx + cxsy * sz; + dest[2][2] = cxcy + sxsy * sz; + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @param[out] dest rotation matrix + */ +CGLM_INLINE +void +glm_euler_yxz(vec3 angles, mat4 dest) { + float cx, cy, cz, + sx, sy, sz, cycz, sysz, czsy, cysz; + + sx = sinf(angles[0]); cx = cosf(angles[0]); + sy = sinf(angles[1]); cy = cosf(angles[1]); + sz = sinf(angles[2]); cz = cosf(angles[2]); + + cycz = cy * cz; + sysz = sy * sz; + czsy = cz * sy; + cysz = cy * sz; + + dest[0][0] = cycz + sx * sysz; + dest[0][1] = cx * sz; + dest[0][2] = -czsy + cysz * sx; + dest[1][0] = -cysz + czsy * sx; + dest[1][1] = cx * cz; + dest[1][2] = cycz * sx + sysz; + dest[2][0] = cx * sy; + dest[2][1] = -sx; + dest[2][2] = cx * cy; + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @param[out] dest rotation matrix + */ +CGLM_INLINE +void +glm_euler_yzx(vec3 angles, mat4 dest) { + float cx, cy, cz, + sx, sy, sz, sxsy, cxcy, cysx, cxsy; + + sx = sinf(angles[0]); cx = cosf(angles[0]); + sy = sinf(angles[1]); cy = cosf(angles[1]); + sz = sinf(angles[2]); cz = cosf(angles[2]); + + sxsy = sx * sy; + cxcy = cx * cy; + cysx = cy * sx; + cxsy = cx * sy; + + dest[0][0] = cy * cz; + dest[0][1] = sz; + dest[0][2] = -cz * sy; + dest[1][0] = sxsy - cxcy * sz; + dest[1][1] = cx * cz; + dest[1][2] = cysx + cxsy * sz; + dest[2][0] = cxsy + cysx * sz; + dest[2][1] = -cz * sx; + dest[2][2] = cxcy - sxsy * sz; + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @param[out] dest rotation matrix + */ +CGLM_INLINE +void +glm_euler_zxy(vec3 angles, mat4 dest) { + float cx, cy, cz, + sx, sy, sz, cycz, sxsy, cysz; + + sx = sinf(angles[0]); cx = cosf(angles[0]); + sy = sinf(angles[1]); cy = cosf(angles[1]); + sz = sinf(angles[2]); cz = cosf(angles[2]); + + cycz = cy * cz; + sxsy = sx * sy; + cysz = cy * sz; + + dest[0][0] = cycz - sxsy * sz; + dest[0][1] = cz * sxsy + cysz; + dest[0][2] = -cx * sy; + dest[1][0] = -cx * sz; + dest[1][1] = cx * cz; + dest[1][2] = sx; + dest[2][0] = cz * sy + cysz * sx; + dest[2][1] = -cycz * sx + sy * sz; + dest[2][2] = cx * cy; + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @param[out] dest rotation matrix + */ +CGLM_INLINE +void +glm_euler_zyx(vec3 angles, mat4 dest) { + float cx, cy, cz, + sx, sy, sz, czsx, cxcz, sysz; + + sx = sinf(angles[0]); cx = cosf(angles[0]); + sy = sinf(angles[1]); cy = cosf(angles[1]); + sz = sinf(angles[2]); cz = cosf(angles[2]); + + czsx = cz * sx; + cxcz = cx * cz; + sysz = sy * sz; + + dest[0][0] = cy * cz; + dest[0][1] = cy * sz; + dest[0][2] = -sy; + dest[1][0] = czsx * sy - cx * sz; + dest[1][1] = cxcz + sx * sysz; + dest[1][2] = cy * sx; + dest[2][0] = cxcz * sy + sx * sz; + dest[2][1] = -czsx + cx * sysz; + dest[2][2] = cx * cy; + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @param[in] ord euler order + * @param[out] dest rotation matrix + */ +CGLM_INLINE +void +glm_euler_by_order(vec3 angles, glm_euler_seq ord, mat4 dest) { + float cx, cy, cz, + sx, sy, sz; + + float cycz, cysz, cysx, cxcy, + czsy, cxcz, czsx, cxsz, + sysz; + + sx = sinf(angles[0]); cx = cosf(angles[0]); + sy = sinf(angles[1]); cy = cosf(angles[1]); + sz = sinf(angles[2]); cz = cosf(angles[2]); + + cycz = cy * cz; cysz = cy * sz; + cysx = cy * sx; cxcy = cx * cy; + czsy = cz * sy; cxcz = cx * cz; + czsx = cz * sx; cxsz = cx * sz; + sysz = sy * sz; + + switch (ord) { + case GLM_EULER_XZY: + dest[0][0] = cycz; + dest[0][1] = sx * sy + cx * cysz; + dest[0][2] = -cx * sy + cysx * sz; + dest[1][0] = -sz; + dest[1][1] = cxcz; + dest[1][2] = czsx; + dest[2][0] = czsy; + dest[2][1] = -cysx + cx * sysz; + dest[2][2] = cxcy + sx * sysz; + break; + case GLM_EULER_XYZ: + dest[0][0] = cycz; + dest[0][1] = czsx * sy + cxsz; + dest[0][2] = -cx * czsy + sx * sz; + dest[1][0] = -cysz; + dest[1][1] = cxcz - sx * sysz; + dest[1][2] = czsx + cx * sysz; + dest[2][0] = sy; + dest[2][1] = -cysx; + dest[2][2] = cxcy; + break; + case GLM_EULER_YXZ: + dest[0][0] = cycz + sx * sysz; + dest[0][1] = cxsz; + dest[0][2] = -czsy + cysx * sz; + dest[1][0] = czsx * sy - cysz; + dest[1][1] = cxcz; + dest[1][2] = cycz * sx + sysz; + dest[2][0] = cx * sy; + dest[2][1] = -sx; + dest[2][2] = cxcy; + break; + case GLM_EULER_YZX: + dest[0][0] = cycz; + dest[0][1] = sz; + dest[0][2] = -czsy; + dest[1][0] = sx * sy - cx * cysz; + dest[1][1] = cxcz; + dest[1][2] = cysx + cx * sysz; + dest[2][0] = cx * sy + cysx * sz; + dest[2][1] = -czsx; + dest[2][2] = cxcy - sx * sysz; + break; + case GLM_EULER_ZXY: + dest[0][0] = cycz - sx * sysz; + dest[0][1] = czsx * sy + cysz; + dest[0][2] = -cx * sy; + dest[1][0] = -cxsz; + dest[1][1] = cxcz; + dest[1][2] = sx; + dest[2][0] = czsy + cysx * sz; + dest[2][1] = -cycz * sx + sysz; + dest[2][2] = cxcy; + break; + case GLM_EULER_ZYX: + dest[0][0] = cycz; + dest[0][1] = cysz; + dest[0][2] = -sy; + dest[1][0] = czsx * sy - cxsz; + dest[1][1] = cxcz + sx * sysz; + dest[1][2] = cysx; + dest[2][0] = cx * czsy + sx * sz; + dest[2][1] = -czsx + cx * sysz; + dest[2][2] = cxcy; + break; + } + + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; +} + + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x y z order (roll pitch yaw) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_xyz_quat(vec3 angles, versor dest) { +#ifdef CGLM_FORCE_LEFT_HANDED + glm_euler_xyz_quat_lh(angles, dest); +#else + glm_euler_xyz_quat_rh(angles, dest); +#endif +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x z y order (roll yaw pitch) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_xzy_quat(vec3 angles, versor dest) { +#ifdef CGLM_FORCE_LEFT_HANDED + glm_euler_xzy_quat_lh(angles, dest); +#else + glm_euler_xzy_quat_rh(angles, dest); +#endif +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y x z order (pitch roll yaw) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_yxz_quat(vec3 angles, versor dest) { +#ifdef CGLM_FORCE_LEFT_HANDED + glm_euler_yxz_quat_lh(angles, dest); +#else + glm_euler_yxz_quat_rh(angles, dest); +#endif +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y z x order (pitch yaw roll) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_yzx_quat(vec3 angles, versor dest) { +#ifdef CGLM_FORCE_LEFT_HANDED + glm_euler_yzx_quat_lh(angles, dest); +#else + glm_euler_yzx_quat_rh(angles, dest); +#endif +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z x y order (yaw roll pitch) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_zxy_quat(vec3 angles, versor dest) { +#ifdef CGLM_FORCE_LEFT_HANDED + glm_euler_zxy_quat_lh(angles, dest); +#else + glm_euler_zxy_quat_rh(angles, dest); +#endif +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z y x order (yaw pitch roll) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_zyx_quat(vec3 angles, versor dest) { +#ifdef CGLM_FORCE_LEFT_HANDED + glm_euler_zyx_quat_lh(angles, dest); +#else + glm_euler_zyx_quat_rh(angles, dest); +#endif +} + + +#endif /* cglm_euler_h */ diff --git a/external/cglm/frustum.h b/external/cglm/frustum.h new file mode 100644 index 0000000..5aa3c17 --- /dev/null +++ b/external/cglm/frustum.h @@ -0,0 +1,255 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_frustum_h +#define cglm_frustum_h + +#include "common.h" +#include "plane.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" + +#define GLM_LBN 0 /* left bottom near */ +#define GLM_LTN 1 /* left top near */ +#define GLM_RTN 2 /* right top near */ +#define GLM_RBN 3 /* right bottom near */ + +#define GLM_LBF 4 /* left bottom far */ +#define GLM_LTF 5 /* left top far */ +#define GLM_RTF 6 /* right top far */ +#define GLM_RBF 7 /* right bottom far */ + +#define GLM_LEFT 0 +#define GLM_RIGHT 1 +#define GLM_BOTTOM 2 +#define GLM_TOP 3 +#define GLM_NEAR 4 +#define GLM_FAR 5 + +/* you can override clip space coords + but you have to provide all with same name + e.g.: define GLM_CSCOORD_LBN {0.0f, 0.0f, 1.0f, 1.0f} */ +#ifndef GLM_CUSTOM_CLIPSPACE + +/* near */ +#define GLM_CSCOORD_LBN {-1.0f, -1.0f, -1.0f, 1.0f} +#define GLM_CSCOORD_LTN {-1.0f, 1.0f, -1.0f, 1.0f} +#define GLM_CSCOORD_RTN { 1.0f, 1.0f, -1.0f, 1.0f} +#define GLM_CSCOORD_RBN { 1.0f, -1.0f, -1.0f, 1.0f} + +/* far */ +#define GLM_CSCOORD_LBF {-1.0f, -1.0f, 1.0f, 1.0f} +#define GLM_CSCOORD_LTF {-1.0f, 1.0f, 1.0f, 1.0f} +#define GLM_CSCOORD_RTF { 1.0f, 1.0f, 1.0f, 1.0f} +#define GLM_CSCOORD_RBF { 1.0f, -1.0f, 1.0f, 1.0f} + +#endif + +/*! + * @brief extracts view frustum planes + * + * planes' space: + * 1- if m = proj: View Space + * 2- if m = viewProj: World Space + * 3- if m = MVP: Object Space + * + * You probably want to extract planes in world space so use viewProj as m + * Computing viewProj: + * glm_mat4_mul(proj, view, viewProj); + * + * Exracted planes order: [left, right, bottom, top, near, far] + * + * @param[in] m matrix (see brief) + * @param[out] dest extracted view frustum planes (see brief) + */ +CGLM_INLINE +void +glm_frustum_planes(mat4 m, vec4 dest[6]) { + mat4 t; + + glm_mat4_transpose_to(m, t); + + glm_vec4_add(t[3], t[0], dest[0]); /* left */ + glm_vec4_sub(t[3], t[0], dest[1]); /* right */ + glm_vec4_add(t[3], t[1], dest[2]); /* bottom */ + glm_vec4_sub(t[3], t[1], dest[3]); /* top */ + glm_vec4_add(t[3], t[2], dest[4]); /* near */ + glm_vec4_sub(t[3], t[2], dest[5]); /* far */ + + glm_plane_normalize(dest[0]); + glm_plane_normalize(dest[1]); + glm_plane_normalize(dest[2]); + glm_plane_normalize(dest[3]); + glm_plane_normalize(dest[4]); + glm_plane_normalize(dest[5]); +} + +/*! + * @brief extracts view frustum corners using clip-space coordinates + * + * corners' space: + * 1- if m = invViewProj: World Space + * 2- if m = invMVP: Object Space + * + * You probably want to extract corners in world space so use invViewProj + * Computing invViewProj: + * glm_mat4_mul(proj, view, viewProj); + * ... + * glm_mat4_inv(viewProj, invViewProj); + * + * if you have a near coord at i index, you can get it's far coord by i + 4 + * + * Find center coordinates: + * for (j = 0; j < 4; j++) { + * glm_vec3_center(corners[i], corners[i + 4], centerCorners[i]); + * } + * + * @param[in] invMat matrix (see brief) + * @param[out] dest exracted view frustum corners (see brief) + */ +CGLM_INLINE +void +glm_frustum_corners(mat4 invMat, vec4 dest[8]) { + vec4 c[8]; + + /* indexOf(nearCoord) = indexOf(farCoord) + 4 */ + vec4 csCoords[8] = { + GLM_CSCOORD_LBN, + GLM_CSCOORD_LTN, + GLM_CSCOORD_RTN, + GLM_CSCOORD_RBN, + + GLM_CSCOORD_LBF, + GLM_CSCOORD_LTF, + GLM_CSCOORD_RTF, + GLM_CSCOORD_RBF + }; + + glm_mat4_mulv(invMat, csCoords[0], c[0]); + glm_mat4_mulv(invMat, csCoords[1], c[1]); + glm_mat4_mulv(invMat, csCoords[2], c[2]); + glm_mat4_mulv(invMat, csCoords[3], c[3]); + glm_mat4_mulv(invMat, csCoords[4], c[4]); + glm_mat4_mulv(invMat, csCoords[5], c[5]); + glm_mat4_mulv(invMat, csCoords[6], c[6]); + glm_mat4_mulv(invMat, csCoords[7], c[7]); + + glm_vec4_scale(c[0], 1.0f / c[0][3], dest[0]); + glm_vec4_scale(c[1], 1.0f / c[1][3], dest[1]); + glm_vec4_scale(c[2], 1.0f / c[2][3], dest[2]); + glm_vec4_scale(c[3], 1.0f / c[3][3], dest[3]); + glm_vec4_scale(c[4], 1.0f / c[4][3], dest[4]); + glm_vec4_scale(c[5], 1.0f / c[5][3], dest[5]); + glm_vec4_scale(c[6], 1.0f / c[6][3], dest[6]); + glm_vec4_scale(c[7], 1.0f / c[7][3], dest[7]); +} + +/*! + * @brief finds center of view frustum + * + * @param[in] corners view frustum corners + * @param[out] dest view frustum center + */ +CGLM_INLINE +void +glm_frustum_center(vec4 corners[8], vec4 dest) { + vec4 center; + + glm_vec4_copy(corners[0], center); + + glm_vec4_add(corners[1], center, center); + glm_vec4_add(corners[2], center, center); + glm_vec4_add(corners[3], center, center); + glm_vec4_add(corners[4], center, center); + glm_vec4_add(corners[5], center, center); + glm_vec4_add(corners[6], center, center); + glm_vec4_add(corners[7], center, center); + + glm_vec4_scale(center, 0.125f, dest); +} + +/*! + * @brief finds bounding box of frustum relative to given matrix e.g. view mat + * + * @param[in] corners view frustum corners + * @param[in] m matrix to convert existing conners + * @param[out] box bounding box as array [min, max] + */ +CGLM_INLINE +void +glm_frustum_box(vec4 corners[8], mat4 m, vec3 box[2]) { + vec4 v; + vec3 min, max; + int i; + + glm_vec3_broadcast(FLT_MAX, min); + glm_vec3_broadcast(-FLT_MAX, max); + + for (i = 0; i < 8; i++) { + glm_mat4_mulv(m, corners[i], v); + + min[0] = glm_min(min[0], v[0]); + min[1] = glm_min(min[1], v[1]); + min[2] = glm_min(min[2], v[2]); + + max[0] = glm_max(max[0], v[0]); + max[1] = glm_max(max[1], v[1]); + max[2] = glm_max(max[2], v[2]); + } + + glm_vec3_copy(min, box[0]); + glm_vec3_copy(max, box[1]); +} + +/*! + * @brief finds planes corners which is between near and far planes (parallel) + * + * this will be helpful if you want to split a frustum e.g. CSM/PSSM. This will + * find planes' corners but you will need to one more plane. + * Actually you have it, it is near, far or created previously with this func ;) + * + * @param[in] corners view frustum corners + * @param[in] splitDist split distance + * @param[in] farDist far distance (zFar) + * @param[out] planeCorners plane corners [LB, LT, RT, RB] + */ +CGLM_INLINE +void +glm_frustum_corners_at(vec4 corners[8], + float splitDist, + float farDist, + vec4 planeCorners[4]) { + vec4 corner; + float dist, sc; + + /* because distance and scale is same for all */ + dist = glm_vec3_distance(corners[GLM_RTF], corners[GLM_RTN]); + sc = dist * (splitDist / farDist); + + /* left bottom */ + glm_vec4_sub(corners[GLM_LBF], corners[GLM_LBN], corner); + glm_vec4_scale_as(corner, sc, corner); + glm_vec4_add(corners[GLM_LBN], corner, planeCorners[0]); + + /* left top */ + glm_vec4_sub(corners[GLM_LTF], corners[GLM_LTN], corner); + glm_vec4_scale_as(corner, sc, corner); + glm_vec4_add(corners[GLM_LTN], corner, planeCorners[1]); + + /* right top */ + glm_vec4_sub(corners[GLM_RTF], corners[GLM_RTN], corner); + glm_vec4_scale_as(corner, sc, corner); + glm_vec4_add(corners[GLM_RTN], corner, planeCorners[2]); + + /* right bottom */ + glm_vec4_sub(corners[GLM_RBF], corners[GLM_RBN], corner); + glm_vec4_scale_as(corner, sc, corner); + glm_vec4_add(corners[GLM_RBN], corner, planeCorners[3]); +} + +#endif /* cglm_frustum_h */ diff --git a/external/cglm/handed/euler_to_quat_lh.h b/external/cglm/handed/euler_to_quat_lh.h new file mode 100644 index 0000000..1bb350b --- /dev/null +++ b/external/cglm/handed/euler_to_quat_lh.h @@ -0,0 +1,167 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_euler_xyz_quat_lh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_xzy_quat_lh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_yxz_quat_lh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_yzx_quat_lh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_zxy_quat_lh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_zyx_quat_lh(vec3 angles, versor dest); + */ + +/* + Things to note: + The only difference between euler to quat rh vs lh is that the zsin part is negative + */ + +#ifndef cglm_euler_to_quat_lh_h +#define cglm_euler_to_quat_lh_h + +#include "../common.h" + + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x y z order in left hand (roll pitch yaw) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_xyz_quat_lh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = -sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = xc * ys * zs + xs * yc * zc; + dest[1] = xc * ys * zc - xs * yc * zs; + dest[2] = xc * yc * zs + xs * ys * zc; + dest[3] = xc * yc * zc - xs * ys * zs; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x z y order in left hand (roll yaw pitch) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_xzy_quat_lh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = -sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = -xc * zs * ys + xs * zc * yc; + dest[1] = xc * zc * ys - xs * zs * yc; + dest[2] = xc * zs * yc + xs * zc * ys; + dest[3] = xc * zc * yc + xs * zs * ys; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y x z order in left hand (pitch roll yaw) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_yxz_quat_lh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = -sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = yc * xs * zc + ys * xc * zs; + dest[1] = -yc * xs * zs + ys * xc * zc; + dest[2] = yc * xc * zs - ys * xs * zc; + dest[3] = yc * xc * zc + ys * xs * zs; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y z x order in left hand (pitch yaw roll) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_yzx_quat_lh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = -sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = yc * zc * xs + ys * zs * xc; + dest[1] = yc * zs * xs + ys * zc * xc; + dest[2] = yc * zs * xc - ys * zc * xs; + dest[3] = yc * zc * xc - ys * zs * xs; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z x y order in left hand (yaw roll pitch) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_zxy_quat_lh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = -sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = zc * xs * yc - zs * xc * ys; + dest[1] = zc * xc * ys + zs * xs * yc; + dest[2] = zc * xs * ys + zs * xc * yc; + dest[3] = zc * xc * yc - zs * xs * ys; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z y x order in left hand (yaw pitch roll) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_zyx_quat_lh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = -sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = zc * yc * xs - zs * ys * xc; + dest[1] = zc * ys * xc + zs * yc * xs; + dest[2] = -zc * ys * xs + zs * yc * xc; + dest[3] = zc * yc * xc + zs * ys * xs; +} + +#endif /*cglm_euler_to_quat_lh_h*/ diff --git a/external/cglm/handed/euler_to_quat_rh.h b/external/cglm/handed/euler_to_quat_rh.h new file mode 100644 index 0000000..aeb6f81 --- /dev/null +++ b/external/cglm/handed/euler_to_quat_rh.h @@ -0,0 +1,170 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_euler_xyz_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_xzy_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_yxz_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_yzx_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_zxy_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glm_euler_zyx_quat_rh(vec3 angles, versor dest); + */ + +/* + Things to note: + The only difference between euler to quat rh vs lh is that the zsin part is negative + */ + +#ifndef cglm_euler_to_quat_rh_h +#define cglm_euler_to_quat_rh_h + +#include "../common.h" + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x y z order in right hand (roll pitch yaw) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_xyz_quat_rh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = xc * ys * zs + xs * yc * zc; + dest[1] = xc * ys * zc - xs * yc * zs; + dest[2] = xc * yc * zs + xs * ys * zc; + dest[3] = xc * yc * zc - xs * ys * zs; + +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x z y order in right hand (roll yaw pitch) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_xzy_quat_rh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = -xc * zs * ys + xs * zc * yc; + dest[1] = xc * zc * ys - xs * zs * yc; + dest[2] = xc * zs * yc + xs * zc * ys; + dest[3] = xc * zc * yc + xs * zs * ys; + +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y x z order in right hand (pitch roll yaw) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_yxz_quat_rh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = yc * xs * zc + ys * xc * zs; + dest[1] = -yc * xs * zs + ys * xc * zc; + dest[2] = yc * xc * zs - ys * xs * zc; + dest[3] = yc * xc * zc + ys * xs * zs; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y z x order in right hand (pitch yaw roll) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_yzx_quat_rh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = yc * zc * xs + ys * zs * xc; + dest[1] = yc * zs * xs + ys * zc * xc; + dest[2] = yc * zs * xc - ys * zc * xs; + dest[3] = yc * zc * xc - ys * zs * xs; + +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z x y order in right hand (yaw roll pitch) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_zxy_quat_rh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = zc * xs * yc - zs * xc * ys; + dest[1] = zc * xc * ys + zs * xs * yc; + dest[2] = zc * xs * ys + zs * xc * yc; + dest[3] = zc * xc * yc - zs * xs * ys; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z y x order in right hand (yaw pitch roll) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_euler_zyx_quat_rh(vec3 angles, versor dest) { + float xc, yc, zc, + xs, ys, zs; + + xs = sinf(angles[0] * 0.5f); xc = cosf(angles[0] * 0.5f); + ys = sinf(angles[1] * 0.5f); yc = cosf(angles[1] * 0.5f); + zs = sinf(angles[2] * 0.5f); zc = cosf(angles[2] * 0.5f); + + dest[0] = zc * yc * xs - zs * ys * xc; + dest[1] = zc * ys * xc + zs * yc * xs; + dest[2] = -zc * ys * xs + zs * yc * xc; + dest[3] = zc * yc * xc + zs * ys * xs; +} + + +#endif /*cglm_euler_to_quat_rh_h*/ diff --git a/external/cglm/io.h b/external/cglm/io.h new file mode 100644 index 0000000..baa80f1 --- /dev/null +++ b/external/cglm/io.h @@ -0,0 +1,440 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_mat4_print(mat4 matrix, FILE *ostream); + CGLM_INLINE void glm_mat3_print(mat3 matrix, FILE *ostream); + CGLM_INLINE void glm_vec4_print(vec4 vec, FILE *ostream); + CGLM_INLINE void glm_ivec4_print(ivec4 vec, FILE *ostream); + CGLM_INLINE void glm_vec3_print(vec3 vec, FILE *ostream); + CGLM_INLINE void glm_ivec3_print(ivec3 vec, FILE *ostream); + CGLM_INLINE void glm_vec2_print(vec2 vec, FILE *ostream); + CGLM_INLINE void glm_ivec2_print(ivec2 vec, FILE *ostream); + CGLM_INLINE void glm_versor_print(versor vec, FILE *ostream); + CGLM_INLINE void glm_arch_print(FILE *ostream); + */ + +/* + cglm tried to enable print functions in debug mode and disable them in + release/production mode to eliminate printing costs. + + if you need to force enable then define CGLM_DEFINE_PRINTS macro not DEBUG one + + Print functions are enabled if: + + - DEBUG or _DEBUG macro is defined (mostly defined automatically in debugging) + - CGLM_DEFINE_PRINTS macro is defined including release/production + which makes enabled printing always + - glmc_ calls for io are always prints + + */ + +/* DEPRECATED: CGLM_NO_PRINTS_NOOP (use CGLM_DEFINE_PRINTS) */ + +#ifndef cglm_io_h +#define cglm_io_h +#if !defined(NDEBUG) \ + || defined(CGLM_DEFINE_PRINTS) || defined(CGLM_LIB_SRC) \ + || defined(CGLM_NO_PRINTS_NOOP) + +#include "common.h" +#include "util.h" + +#include +#include + +#ifndef CGLM_PRINT_PRECISION +# define CGLM_PRINT_PRECISION 5 +#endif + +#ifndef CGLM_PRINT_MAX_TO_SHORT +# define CGLM_PRINT_MAX_TO_SHORT 1e5f +#endif + +#ifndef GLM_TESTS_NO_COLORFUL_OUTPUT +# ifndef CGLM_PRINT_COLOR +# define CGLM_PRINT_COLOR "\033[36m" +# endif +# ifndef CGLM_PRINT_COLOR_RESET +# define CGLM_PRINT_COLOR_RESET "\033[0m" +# endif +#else +# ifndef CGLM_PRINT_COLOR +# define CGLM_PRINT_COLOR +# endif +# ifndef CGLM_PRINT_COLOR_RESET +# define CGLM_PRINT_COLOR_RESET +# endif +#endif + +/*! + * @brief prints current SIMD path in general + * + * @param[in] ostream stream to print e.g. stdout, stderr, FILE ... + */ +CGLM_INLINE +void +glm_arch_print(FILE* __restrict ostream) { + fprintf(ostream, CGLM_PRINT_COLOR "arch: " +#if defined(CGLM_SIMD_WASM) + "wasm SIMD128" +#elif defined(CGLM_SIMD_x86) + "x86 SSE* " +# ifdef __AVX__ + " AVX" +# endif +#elif defined(CGLM_SIMD_ARM) + "arm" +# ifndef __ARM_NEON_FP + " NEON_FP" +# endif +# ifdef CGLM_ARM64 + " ARM64" +# endif +#else + "uncommon" +#endif + CGLM_PRINT_COLOR_RESET); +} + +/*! + * @brief prints current SIMD path in general + * + * @param[in] ostream stream to print e.g. stdout, stderr, FILE ... + */ +CGLM_INLINE +void +glm_arch_print_name(FILE* __restrict ostream) { + fprintf(ostream, CGLM_PRINT_COLOR "\ncglm "); + glm_arch_print(ostream); + fprintf(ostream, "\n\n" CGLM_PRINT_COLOR_RESET); +} + +CGLM_INLINE +void +glm_mat4_print(mat4 matrix, + FILE * __restrict ostream) { + char buff[16]; + int i, j, cw[4], cwi; + +#define m 4 +#define n 4 + + fprintf(ostream, "Matrix (float%dx%d): " CGLM_PRINT_COLOR "\n" , m, n); + + cw[0] = cw[1] = cw[2] = cw[3] = 0; + + for (i = 0; i < m; i++) { + for (j = 0; j < n; j++) { + if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT) + cwi = snprintf(buff, sizeof(buff), "% .*f", CGLM_PRINT_PRECISION, (double)matrix[i][j]); + else + cwi = snprintf(buff, sizeof(buff), "% g", (double)matrix[i][j]); + cw[i] = GLM_MAX(cw[i], cwi); + } + } + + for (i = 0; i < m; i++) { + fprintf(ostream, " |"); + + for (j = 0; j < n; j++) + if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT) + fprintf(ostream, " % *.*f", cw[j], CGLM_PRINT_PRECISION, (double)matrix[j][i]); + else + fprintf(ostream, " % *g", cw[j], (double)matrix[j][i]); + + fprintf(ostream, " |\n"); + } + + fprintf(ostream, CGLM_PRINT_COLOR_RESET "\n"); + +#undef m +#undef n +} + + +CGLM_INLINE +void +glm_mat3_print(mat3 matrix, + FILE * __restrict ostream) { + char buff[16]; + int i, j, cw[4], cwi; + +#define m 3 +#define n 3 + + fprintf(ostream, "Matrix (float%dx%d): " CGLM_PRINT_COLOR "\n", m, n); + + cw[0] = cw[1] = cw[2] = 0; + + for (i = 0; i < m; i++) { + for (j = 0; j < n; j++) { + if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT) + cwi = snprintf(buff, sizeof(buff), "% .*f", CGLM_PRINT_PRECISION, (double)matrix[i][j]); + else + cwi = snprintf(buff, sizeof(buff), "% g", (double)matrix[i][j]); + cw[i] = GLM_MAX(cw[i], cwi); + } + } + + for (i = 0; i < m; i++) { + fprintf(ostream, " |"); + + for (j = 0; j < n; j++) + if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT) + fprintf(ostream, " % *.*f", cw[j], CGLM_PRINT_PRECISION, (double)matrix[j][i]); + else + fprintf(ostream, " % *g", cw[j], (double)matrix[j][i]); + + fprintf(ostream, " |\n"); + } + + fprintf(ostream, CGLM_PRINT_COLOR_RESET "\n"); + +#undef m +#undef n +} + +CGLM_INLINE +void +glm_mat2_print(mat2 matrix, + FILE * __restrict ostream) { + char buff[16]; + int i, j, cw[4], cwi; + +#define m 2 +#define n 2 + + fprintf(ostream, "Matrix (float%dx%d): " CGLM_PRINT_COLOR "\n", m, n); + + cw[0] = cw[1] = 0; + + for (i = 0; i < m; i++) { + for (j = 0; j < n; j++) { + if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT) + cwi = snprintf(buff, sizeof(buff), "% .*f", CGLM_PRINT_PRECISION, (double)matrix[i][j]); + else + cwi = snprintf(buff, sizeof(buff), "% g", (double)matrix[i][j]); + cw[i] = GLM_MAX(cw[i], cwi); + } + } + + for (i = 0; i < m; i++) { + fprintf(ostream, " |"); + + for (j = 0; j < n; j++) + if (matrix[i][j] < CGLM_PRINT_MAX_TO_SHORT) + fprintf(ostream, " % *.*f", cw[j], CGLM_PRINT_PRECISION, (double)matrix[j][i]); + else + fprintf(ostream, " % *g", cw[j], (double)matrix[j][i]); + + fprintf(ostream, " |\n"); + } + + fprintf(ostream, CGLM_PRINT_COLOR_RESET "\n"); + +#undef m +#undef n +} + +CGLM_INLINE +void +glm_vec4_print(vec4 vec, + FILE * __restrict ostream) { + int i; + +#define m 4 + + fprintf(ostream, "Vector (float%d): " CGLM_PRINT_COLOR "\n (", m); + + for (i = 0; i < m; i++) { + if (vec[i] < CGLM_PRINT_MAX_TO_SHORT) + fprintf(ostream, " % .*f", CGLM_PRINT_PRECISION, (double)vec[i]); + else + fprintf(ostream, " % g", (double)vec[i]); + } + + fprintf(ostream, " )" CGLM_PRINT_COLOR_RESET "\n\n"); + +#undef m +} + +CGLM_INLINE +void +glm_ivec4_print(ivec4 vec, + FILE * __restrict ostream) { + int i; + +#define m 4 + + fprintf(ostream, "Vector (int%d): " CGLM_PRINT_COLOR "\n (", m); + + for (i = 0; i < m; i++) + fprintf(ostream, " % d", vec[i]); + + fprintf(ostream, " )" CGLM_PRINT_COLOR_RESET "\n\n"); + +#undef m +} + +CGLM_INLINE +void +glm_vec3_print(vec3 vec, + FILE * __restrict ostream) { + int i; + +#define m 3 + + fprintf(ostream, "Vector (float%d): " CGLM_PRINT_COLOR "\n (", m); + + for (i = 0; i < m; i++) { + if (vec[i] < CGLM_PRINT_MAX_TO_SHORT) + fprintf(ostream, " % .*f", CGLM_PRINT_PRECISION, (double)vec[i]); + else + fprintf(ostream, " % g", (double)vec[i]); + } + + fprintf(ostream, " )" CGLM_PRINT_COLOR_RESET "\n\n"); + +#undef m +} + +CGLM_INLINE +void +glm_ivec3_print(ivec3 vec, + FILE * __restrict ostream) { + int i; + +#define m 3 + + fprintf(ostream, "Vector (int%d): " CGLM_PRINT_COLOR "\n (", m); + + for (i = 0; i < m; i++) + fprintf(ostream, " % d", vec[i]); + + fprintf(ostream, " )" CGLM_PRINT_COLOR_RESET "\n\n"); + +#undef m +} + +CGLM_INLINE +void +glm_vec2_print(vec2 vec, + FILE * __restrict ostream) { + int i; + +#define m 2 + + fprintf(ostream, "Vector (float%d): " CGLM_PRINT_COLOR "\n (", m); + + for (i = 0; i < m; i++) { + if (vec[i] < CGLM_PRINT_MAX_TO_SHORT) + fprintf(ostream, " % .*f", CGLM_PRINT_PRECISION, (double)vec[i]); + else + fprintf(ostream, " % g", (double)vec[i]); + } + + fprintf(ostream, " )" CGLM_PRINT_COLOR_RESET "\n\n"); + +#undef m +} + +CGLM_INLINE +void +glm_ivec2_print(ivec2 vec, + FILE * __restrict ostream) { + int i; + +#define m 2 + + fprintf(ostream, "Vector (int%d): " CGLM_PRINT_COLOR "\n (", m); + + for (i = 0; i < m; i++) + fprintf(ostream, " % d", vec[i]); + + fprintf(ostream, " )" CGLM_PRINT_COLOR_RESET "\n\n"); + +#undef m +} + +CGLM_INLINE +void +glm_versor_print(versor vec, + FILE * __restrict ostream) { + int i; + +#define m 4 + + fprintf(ostream, "Quaternion (float%d): " CGLM_PRINT_COLOR "\n (", m); + + for (i = 0; i < m; i++) { + if (vec[i] < CGLM_PRINT_MAX_TO_SHORT) + fprintf(ostream, " % .*f", CGLM_PRINT_PRECISION, (double)vec[i]); + else + fprintf(ostream, " % g", (double)vec[i]); + } + + + fprintf(ostream, " )" CGLM_PRINT_COLOR_RESET "\n\n"); + +#undef m +} + +CGLM_INLINE +void +glm_aabb_print(vec3 bbox[2], + const char * __restrict tag, + FILE * __restrict ostream) { + int i, j; + +#define m 3 + + fprintf(ostream, "AABB (%s): " CGLM_PRINT_COLOR "\n", tag ? tag: "float"); + + for (i = 0; i < 2; i++) { + fprintf(ostream, " ("); + + for (j = 0; j < m; j++) { + if (bbox[i][j] < CGLM_PRINT_MAX_TO_SHORT) + fprintf(ostream, " % .*f", CGLM_PRINT_PRECISION, (double)bbox[i][j]); + else + fprintf(ostream, " % g", (double)bbox[i][j]); + } + + fprintf(ostream, " )\n"); + } + + fprintf(ostream, CGLM_PRINT_COLOR_RESET "\n"); + +#undef m +} + +#else + +#include "common.h" + +#include +#include + +/* NOOP: Remove print from DEBUG */ +#define glm_mat4_print(v, s) (void)v; (void)s; +#define glm_mat3_print(v, s) (void)v; (void)s; +#define glm_mat2_print(v, s) (void)v; (void)s; +#define glm_vec4_print(v, s) (void)v; (void)s; +#define glm_ivec4_print(v, s) (void)v; (void)s; +#define glm_vec3_print(v, s) (void)v; (void)s; +#define glm_ivec3_print(v, s) (void)v; (void)s; +#define glm_vec2_print(v, s) (void)v; (void)s; +#define glm_ivec2_print(v, s) (void)v; (void)s; +#define glm_versor_print(v, s) (void)v; (void)s; +#define glm_aabb_print(v, t, s) (void)v; (void)t; (void)s; +#define glm_arch_print(s) (void)s; +#define glm_arch_print_name(s) (void)s; + +#endif +#endif /* cglm_io_h */ diff --git a/external/cglm/ivec2.h b/external/cglm/ivec2.h new file mode 100644 index 0000000..8d5ad88 --- /dev/null +++ b/external/cglm/ivec2.h @@ -0,0 +1,659 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_IVEC2_ONE_INIT + GLM_IVEC2_ZERO_INIT + GLM_IVEC2_ONE + GLM_IVEC2_ZERO + + Functions: + CGLM_INLINE void glm_ivec2(int * __restrict v, ivec2 dest) + CGLM_INLINE void glm_ivec2_copy(ivec2 a, ivec2 dest) + CGLM_INLINE void glm_ivec2_zero(ivec2 v) + CGLM_INLINE void glm_ivec2_one(ivec2 v) + CGLM_INLINE int glm_ivec2_dot(ivec2 a, ivec2 b) + CGLM_INLINE int glm_ivec2_cross(ivec2 a, ivec2 b) + CGLM_INLINE void glm_ivec2_add(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_adds(ivec2 v, int s, ivec2 dest) + CGLM_INLINE void glm_ivec2_sub(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_subs(ivec2 v, int s, ivec2 dest) + CGLM_INLINE void glm_ivec2_mul(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_scale(ivec2 v, int s, ivec2 dest) + CGLM_INLINE void glm_ivec2_div(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_divs(ivec2 v, int s, ivec2 dest) + CGLM_INLINE void glm_ivec2_mod(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_addadd(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_addadds(ivec2 a, int s, ivec2 dest) + CGLM_INLINE void glm_ivec2_subadd(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_subadds(ivec2 a, int s, ivec2 dest) + CGLM_INLINE void glm_ivec2_muladd(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_muladds(ivec2 a, int s, ivec2 dest) + CGLM_INLINE void glm_ivec2_maxadd(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_minadd(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_subsub(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_subsubs(ivec2 a, int s, ivec2 dest) + CGLM_INLINE void glm_ivec2_addsub(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_addsubs(ivec2 a, int s, ivec2 dest) + CGLM_INLINE void glm_ivec2_mulsub(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_mulsubs(ivec2 a, int s, ivec2 dest) + CGLM_INLINE void glm_ivec2_maxsub(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_minsub(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE int glm_ivec2_distance2(ivec2 a, ivec2 b) + CGLM_INLINE float glm_ivec2_distance(ivec2 a, ivec2 b) + CGLM_INLINE void glm_ivec2_fill(ivec2 v, int val); + CGLM_INLINE bool glm_ivec2_eq(ivec2 v, int val); + CGLM_INLINE bool glm_ivec2_eqv(ivec2 a, ivec2 b); + CGLM_INLINE void glm_ivec2_maxv(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_minv(ivec2 a, ivec2 b, ivec2 dest) + CGLM_INLINE void glm_ivec2_clamp(ivec2 v, int minVal, int maxVal) + CGLM_INLINE void glm_ivec2_abs(ivec2 v, ivec2 dest) + */ + +#ifndef cglm_ivec2_h +#define cglm_ivec2_h + +#include "common.h" +#include "util.h" + +#define GLM_IVEC2_ONE_INIT {1, 1} +#define GLM_IVEC2_ZERO_INIT {0, 0} + +#define GLM_IVEC2_ONE ((ivec2)GLM_IVEC2_ONE_INIT) +#define GLM_IVEC2_ZERO ((ivec2)GLM_IVEC2_ZERO_INIT) + +/*! + * @brief init ivec2 using vec3 or vec4 + * + * @param[in] v vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec2(int * __restrict v, ivec2 dest) { + dest[0] = v[0]; + dest[1] = v[1]; +} + +/*! + * @brief copy all members of [a] to [dest] + * + * @param[in] a source vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec2_copy(ivec2 a, ivec2 dest) { + dest[0] = a[0]; + dest[1] = a[1]; +} + +/*! + * @brief set all members of [v] to zero + * + * @param[out] v vector + */ +CGLM_INLINE +void +glm_ivec2_zero(ivec2 v) { + v[0] = v[1] = 0; +} + +/*! + * @brief set all members of [v] to one + * + * @param[out] v vector + */ +CGLM_INLINE +void +glm_ivec2_one(ivec2 v) { + v[0] = v[1] = 1; +} + +/*! + * @brief ivec2 dot product + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return dot product + */ +CGLM_INLINE +int +glm_ivec2_dot(ivec2 a, ivec2 b) { + return a[0] * b[0] + a[1] * b[1]; +} + +/*! + * @brief ivec2 cross product + * + * REF: http://allenchou.net/2013/07/cross-product-of-2d-vectors/ + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return Z component of cross product + */ +CGLM_INLINE +int +glm_ivec2_cross(ivec2 a, ivec2 b) { + return a[0] * b[1] - a[1] * b[0]; +} + +/*! + * @brief add vector [a] to vector [b] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec2_add(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] = a[0] + b[0]; + dest[1] = a[1] + b[1]; +} + +/*! + * @brief add scalar s to vector [v] and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec2_adds(ivec2 v, int s, ivec2 dest) { + dest[0] = v[0] + s; + dest[1] = v[1] + s; +} + +/*! + * @brief subtract vector [b] from vector [a] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec2_sub(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] = a[0] - b[0]; + dest[1] = a[1] - b[1]; +} + +/*! + * @brief subtract scalar s from vector [v] and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec2_subs(ivec2 v, int s, ivec2 dest) { + dest[0] = v[0] - s; + dest[1] = v[1] - s; +} + +/*! + * @brief multiply vector [a] with vector [b] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec2_mul(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] = a[0] * b[0]; + dest[1] = a[1] * b[1]; +} + +/*! + * @brief multiply vector [a] with scalar s and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec2_scale(ivec2 v, int s, ivec2 dest) { + dest[0] = v[0] * s; + dest[1] = v[1] * s; +} + +/*! + * @brief div vector with another component-wise division: d = a / b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest result = (a[0]/b[0], a[1]/b[1]) + */ +CGLM_INLINE +void +glm_ivec2_div(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] = a[0] / b[0]; + dest[1] = a[1] / b[1]; +} + +/*! + * @brief div vector with scalar: d = v / s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest result = (a[0]/s, a[1]/s) + */ +CGLM_INLINE +void +glm_ivec2_divs(ivec2 v, int s, ivec2 dest) { + dest[0] = v[0] / s; + dest[1] = v[1] / s; +} + +/*! + * @brief mod vector with another component-wise modulo: d = a % b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest result = (a[0]%b[0], a[1]%b[1]) + */ +CGLM_INLINE +void +glm_ivec2_mod(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] = a[0] % b[0]; + dest[1] = a[1] % b[1]; +} + +/*! + * @brief add vector [a] with vector [b] and add result to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += (a + b) + */ +CGLM_INLINE +void +glm_ivec2_addadd(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] += a[0] + b[0]; + dest[1] += a[1] + b[1]; +} + +/*! + * @brief add scalar [s] onto vector [a] and add result to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest += (a + s) + */ +CGLM_INLINE +void +glm_ivec2_addadds(ivec2 a, int s, ivec2 dest) { + dest[0] += a[0] + s; + dest[1] += a[1] + s; +} + +/*! + * @brief subtract vector [a] from vector [b] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += (a - b) + */ +CGLM_INLINE +void +glm_ivec2_subadd(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] += a[0] - b[0]; + dest[1] += a[1] - b[1]; +} + +/*! + * @brief subtract scalar [s] from vector [a] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first + * @param[in] s scalar + * @param[out] dest dest += (a - s) + */ +CGLM_INLINE +void +glm_ivec2_subadds(ivec2 a, int s, ivec2 dest) { + dest[0] += a[0] - s; + dest[1] += a[1] - s; +} + +/*! + * @brief multiply vector [a] with vector [b] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_ivec2_muladd(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] += a[0] * b[0]; + dest[1] += a[1] * b[1]; +} + +/*! + * @brief multiply vector [a] with scalar [s] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest += (a * s) + */ +CGLM_INLINE +void +glm_ivec2_muladds(ivec2 a, int s, ivec2 dest) { + dest[0] += a[0] * s; + dest[1] += a[1] * s; +} + +/*! + * @brief add maximum of vector [a] and vector [b] to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += max(a, b) + */ +CGLM_INLINE +void +glm_ivec2_maxadd(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] += glm_imax(a[0], b[0]); + dest[1] += glm_imax(a[1], b[1]); +} + +/*! + * @brief add minimum of vector [a] and vector [b] to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += min(a, b) + */ +CGLM_INLINE +void +glm_ivec2_minadd(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] += glm_imin(a[0], b[0]); + dest[1] += glm_imin(a[1], b[1]); +} + +/*! + * @brief subtract vector [a] from vector [b] and subtract result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest -= (a - b) + */ +CGLM_INLINE +void +glm_ivec2_subsub(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] -= a[0] - b[0]; + dest[1] -= a[1] - b[1]; +} + +/*! + * @brief subtract scalar [s] from vector [a] and subtract result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest -= (a - s) + */ +CGLM_INLINE +void +glm_ivec2_subsubs(ivec2 a, int s, ivec2 dest) { + dest[0] -= a[0] - s; + dest[1] -= a[1] - s; +} + +/*! + * @brief add vector [a] to vector [b] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] b scalar + * @param[out] dest dest -= (a + b) + */ +CGLM_INLINE +void +glm_ivec2_addsub(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] -= a[0] + b[0]; + dest[1] -= a[1] + b[1]; +} + +/*! + * @brief add scalar [s] to vector [a] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest -= (a + b) + */ +CGLM_INLINE +void +glm_ivec2_addsubs(ivec2 a, int s, ivec2 dest) { + dest[0] -= a[0] + s; + dest[1] -= a[1] + s; +} + +/*! + * @brief multiply vector [a] and vector [b] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] b scalar + * @param[out] dest dest -= (a * b) + */ +CGLM_INLINE +void +glm_ivec2_mulsub(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] -= a[0] * b[0]; + dest[1] -= a[1] * b[1]; +} + +/*! + * @brief multiply vector [a] with scalar [s] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest -= (a * s) + */ +CGLM_INLINE +void +glm_ivec2_mulsubs(ivec2 a, int s, ivec2 dest) { + dest[0] -= a[0] * s; + dest[1] -= a[1] * s; +} + +/*! + * @brief subtract maximum of vector [a] and vector [b] from vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest -= max(a, b) + */ +CGLM_INLINE +void +glm_ivec2_maxsub(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] -= glm_imax(a[0], b[0]); + dest[1] -= glm_imax(a[1], b[1]); +} + +/*! + * @brief subtract minimum of vector [a] and vector [b] from vector [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest -= min(a, b) + */ +CGLM_INLINE +void +glm_ivec2_minsub(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] -= glm_imin(a[0], b[0]); + dest[1] -= glm_imin(a[1], b[1]); +} + +/*! + * @brief squared distance between two vectors + * + * @param[in] a first vector + * @param[in] b second vector + * @return returns squared distance (distance * distance) + */ +CGLM_INLINE +int +glm_ivec2_distance2(ivec2 a, ivec2 b) { + int xd, yd; + xd = a[0] - b[0]; + yd = a[1] - b[1]; + return xd * xd + yd * yd; +} + +/*! + * @brief distance between two vectors + * + * @param[in] a first vector + * @param[in] b second vector + * @return returns distance + */ +CGLM_INLINE +float +glm_ivec2_distance(ivec2 a, ivec2 b) { + return sqrtf((float)glm_ivec2_distance2(a, b)); +} + + +/*! + * @brief fill a vector with specified value + * + * @param[out] v dest + * @param[in] val value + */ +CGLM_INLINE +void +glm_ivec2_fill(ivec2 v, int val) { + v[0] = v[1] = val; +} + +/*! + * @brief check if vector is equal to value + * + * @param[in] v vector + * @param[in] val value + */ +CGLM_INLINE +bool +glm_ivec2_eq(ivec2 v, int val) { + return v[0] == val && v[0] == v[1]; +} + +/*! + * @brief check if vector is equal to another + * + * @param[in] a vector + * @param[in] b vector + */ +CGLM_INLINE +bool +glm_ivec2_eqv(ivec2 a, ivec2 b) { + return a[0] == b[0] + && a[1] == b[1]; +} + +/*! + * @brief set each member of dest to greater of vector a and b + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec2_maxv(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] = a[0] > b[0] ? a[0] : b[0]; + dest[1] = a[1] > b[1] ? a[1] : b[1]; +} + +/*! + * @brief set each member of dest to lesser of vector a and b + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec2_minv(ivec2 a, ivec2 b, ivec2 dest) { + dest[0] = a[0] < b[0] ? a[0] : b[0]; + dest[1] = a[1] < b[1] ? a[1] : b[1]; +} + +/*! + * @brief clamp each member of [v] between minVal and maxVal (inclusive) + * + * @param[in, out] v vector + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + */ +CGLM_INLINE +void +glm_ivec2_clamp(ivec2 v, int minVal, int maxVal) { + if (v[0] < minVal) + v[0] = minVal; + else if(v[0] > maxVal) + v[0] = maxVal; + + if (v[1] < minVal) + v[1] = minVal; + else if(v[1] > maxVal) + v[1] = maxVal; +} + +/*! + * @brief absolute value of v + * + * @param[in] v vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec2_abs(ivec2 v, ivec2 dest) { + dest[0] = abs(v[0]); + dest[1] = abs(v[1]); +} + +#endif /* cglm_ivec2_h */ diff --git a/external/cglm/ivec3.h b/external/cglm/ivec3.h new file mode 100644 index 0000000..67eaa22 --- /dev/null +++ b/external/cglm/ivec3.h @@ -0,0 +1,713 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_IVEC3_ONE_INIT + GLM_IVEC3_ZERO_INIT + GLM_IVEC3_ONE + GLM_IVEC3_ZERO + + Functions: + CGLM_INLINE void glm_ivec3(ivec4 v4, ivec3 dest) + CGLM_INLINE void glm_ivec3_copy(ivec3 a, ivec3 dest) + CGLM_INLINE void glm_ivec3_zero(ivec3 v) + CGLM_INLINE void glm_ivec3_one(ivec3 v) + CGLM_INLINE int glm_ivec3_dot(ivec3 a, ivec3 b) + CGLM_INLINE int glm_ivec3_norm2(ivec3 v) + CGLM_INLINE int glm_ivec3_norm(ivec3 v) + CGLM_INLINE void glm_ivec3_add(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_adds(ivec3 v, int s, ivec3 dest) + CGLM_INLINE void glm_ivec3_sub(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_subs(ivec3 v, int s, ivec3 dest) + CGLM_INLINE void glm_ivec3_mul(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_scale(ivec3 v, int s, ivec3 dest) + CGLM_INLINE void glm_ivec3_div(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_divs(ivec3 v, int s, ivec3 dest) + CGLM_INLINE void glm_ivec3_mod(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_addadd(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_addadds(ivec3 a, int s, ivec3 dest) + CGLM_INLINE void glm_ivec3_subadd(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_subadds(ivec3 a, int s, ivec3 dest) + CGLM_INLINE void glm_ivec3_muladd(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_muladds(ivec3 a, int s, ivec3 dest) + CGLM_INLINE void glm_ivec3_maxadd(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_minadd(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_subsub(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_subsubs(ivec3 a, int s, ivec3 dest) + CGLM_INLINE void glm_ivec3_addsub(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_addsubs(ivec3 a, int s, ivec3 dest) + CGLM_INLINE void glm_ivec3_mulsub(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_mulsubs(ivec3 a, int s, ivec3 dest) + CGLM_INLINE void glm_ivec3_maxsub(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_minsub(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE int glm_ivec3_distance2(ivec3 a, ivec3 b) + CGLM_INLINE float glm_ivec3_distance(ivec3 a, ivec3 b) + CGLM_INLINE void glm_ivec3_fill(ivec3 v, int val); + CGLM_INLINE bool glm_ivec3_eq(ivec3 v, int val); + CGLM_INLINE bool glm_ivec3_eqv(ivec3 a, ivec3 b); + CGLM_INLINE void glm_ivec3_maxv(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_minv(ivec3 a, ivec3 b, ivec3 dest) + CGLM_INLINE void glm_ivec3_clamp(ivec3 v, int minVal, int maxVal) + CGLM_INLINE void glm_ivec3_abs(ivec3 v, ivec3 dest) + */ + +#ifndef cglm_ivec3_h +#define cglm_ivec3_h + +#include "common.h" +#include "util.h" + +#define GLM_IVEC3_ONE_INIT {1, 1, 1} +#define GLM_IVEC3_ZERO_INIT {0, 0, 0} + +#define GLM_IVEC3_ONE ((ivec3)GLM_IVEC3_ONE_INIT) +#define GLM_IVEC3_ZERO ((ivec3)GLM_IVEC3_ZERO_INIT) + +/*! + * @brief init ivec3 using ivec4 + * + * @param[in] v4 vector4 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec3(ivec4 v4, ivec3 dest) { + dest[0] = v4[0]; + dest[1] = v4[1]; + dest[2] = v4[2]; +} + +/*! + * @brief copy all members of [a] to [dest] + * + * @param[in] a source vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec3_copy(ivec3 a, ivec3 dest) { + dest[0] = a[0]; + dest[1] = a[1]; + dest[2] = a[2]; +} + +/*! + * @brief set all members of [v] to zero + * + * @param[out] v vector + */ +CGLM_INLINE +void +glm_ivec3_zero(ivec3 v) { + v[0] = v[1] = v[2] = 0; +} + +/*! + * @brief set all members of [v] to one + * + * @param[out] v vector + */ +CGLM_INLINE +void +glm_ivec3_one(ivec3 v) { + v[0] = v[1] = v[2] = 1; +} + +/*! + * @brief ivec3 dot product + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return dot product + */ +CGLM_INLINE +int +glm_ivec3_dot(ivec3 a, ivec3 b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} + +/*! + * @brief norm * norm (magnitude) of vec + * + * we can use this func instead of calling norm * norm, because it would call + * sqrtf function twice but with this func we can avoid func call, maybe this is + * not good name for this func + * + * @param[in] v vector + * + * @return norm * norm + */ +CGLM_INLINE +int +glm_ivec3_norm2(ivec3 v) { + return glm_ivec3_dot(v, v); +} + +/*! + * @brief euclidean norm (magnitude), also called L2 norm + * this will give magnitude of vector in euclidean space + * + * @param[in] v vector + * + * @return norm + */ +CGLM_INLINE +int +glm_ivec3_norm(ivec3 v) { + return (int)sqrtf((float)glm_ivec3_norm2(v)); +} + +/*! + * @brief add vector [a] to vector [b] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec3_add(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] = a[0] + b[0]; + dest[1] = a[1] + b[1]; + dest[2] = a[2] + b[2]; +} + +/*! + * @brief add scalar s to vector [v] and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec3_adds(ivec3 v, int s, ivec3 dest) { + dest[0] = v[0] + s; + dest[1] = v[1] + s; + dest[2] = v[2] + s; +} + +/*! + * @brief subtract vector [b] from vector [a] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec3_sub(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] = a[0] - b[0]; + dest[1] = a[1] - b[1]; + dest[2] = a[2] - b[2]; +} + +/*! + * @brief subtract scalar s from vector [v] and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec3_subs(ivec3 v, int s, ivec3 dest) { + dest[0] = v[0] - s; + dest[1] = v[1] - s; + dest[2] = v[2] - s; +} + +/*! + * @brief multiply vector [a] with vector [b] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec3_mul(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] = a[0] * b[0]; + dest[1] = a[1] * b[1]; + dest[2] = a[2] * b[2]; +} + +/*! + * @brief multiply vector [a] with scalar s and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec3_scale(ivec3 v, int s, ivec3 dest) { + dest[0] = v[0] * s; + dest[1] = v[1] * s; + dest[2] = v[2] * s; +} + +/*! + * @brief div vector with another component-wise division: d = a / b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest result = (a[0]/b[0], a[1]/b[1], a[2]/b[2]) + */ +CGLM_INLINE +void +glm_ivec3_div(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] = a[0] / b[0]; + dest[1] = a[1] / b[1]; + dest[2] = a[2] / b[2]; +} + +/*! + * @brief div vector with scalar: d = v / s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest result = (a[0]/s, a[1]/s, a[2]/s) + */ +CGLM_INLINE +void +glm_ivec3_divs(ivec3 v, int s, ivec3 dest) { + dest[0] = v[0] / s; + dest[1] = v[1] / s; + dest[2] = v[2] / s; +} + +/*! + * @brief Element-wise modulo operation on ivec3 vectors: dest = a % b + * + * Performs element-wise modulo on each component of vectors `a` and `b`. + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest result = (a[0]%b[0], a[1]%b[1], a[2]%b[2]) + */ +CGLM_INLINE +void +glm_ivec3_mod(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] = a[0] % b[0]; + dest[1] = a[1] % b[1]; + dest[2] = a[2] % b[2]; +} + +/*! + * @brief add vector [a] with vector [b] and add result to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += (a + b) + */ +CGLM_INLINE +void +glm_ivec3_addadd(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] += a[0] + b[0]; + dest[1] += a[1] + b[1]; + dest[2] += a[2] + b[2]; +} + +/*! + * @brief add scalar [s] onto vector [a] and add result to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest += (a + s) + */ +CGLM_INLINE +void +glm_ivec3_addadds(ivec3 a, int s, ivec3 dest) { + dest[0] += a[0] + s; + dest[1] += a[1] + s; + dest[2] += a[2] + s; +} + +/*! + * @brief subtract vector [a] from vector [b] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += (a - b) + */ +CGLM_INLINE +void +glm_ivec3_subadd(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] += a[0] - b[0]; + dest[1] += a[1] - b[1]; + dest[2] += a[2] - b[2]; +} + +/*! + * @brief subtract scalar [s] from vector [a] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first + * @param[in] s scalar + * @param[out] dest dest += (a - s) + */ +CGLM_INLINE +void +glm_ivec3_subadds(ivec3 a, int s, ivec3 dest) { + dest[0] += a[0] - s; + dest[1] += a[1] - s; + dest[2] += a[2] - s; +} + +/*! + * @brief multiply vector [a] with vector [b] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_ivec3_muladd(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] += a[0] * b[0]; + dest[1] += a[1] * b[1]; + dest[2] += a[2] * b[2]; +} + +/*! + * @brief multiply vector [a] with scalar [s] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest += (a * s) + */ +CGLM_INLINE +void +glm_ivec3_muladds(ivec3 a, int s, ivec3 dest) { + dest[0] += a[0] * s; + dest[1] += a[1] * s; + dest[2] += a[2] * s; +} + +/*! + * @brief add maximum of vector [a] and vector [b] to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += max(a, b) + */ +CGLM_INLINE +void +glm_ivec3_maxadd(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] += glm_imax(a[0], b[0]); + dest[1] += glm_imax(a[1], b[1]); + dest[2] += glm_imax(a[2], b[2]); +} + +/*! + * @brief add minimum of vector [a] and vector [b] to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += min(a, b) + */ +CGLM_INLINE +void +glm_ivec3_minadd(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] += glm_imin(a[0], b[0]); + dest[1] += glm_imin(a[1], b[1]); + dest[2] += glm_imin(a[2], b[2]); +} + +/*! + * @brief subtract vector [a] from vector [b] and subtract result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest -= (a - b) + */ +CGLM_INLINE +void +glm_ivec3_subsub(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] -= a[0] - b[0]; + dest[1] -= a[1] - b[1]; + dest[2] -= a[2] - b[2]; +} + +/*! + * @brief subtract scalar [s] from vector [a] and subtract result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest -= (a - s) + */ +CGLM_INLINE +void +glm_ivec3_subsubs(ivec3 a, int s, ivec3 dest) { + dest[0] -= a[0] - s; + dest[1] -= a[1] - s; + dest[2] -= a[2] - s; +} + +/*! + * @brief add vector [a] to vector [b] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] b scalar + * @param[out] dest dest -= (a + b) + */ +CGLM_INLINE +void +glm_ivec3_addsub(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] -= a[0] + b[0]; + dest[1] -= a[1] + b[1]; + dest[2] -= a[2] + b[2]; +} + +/*! + * @brief add scalar [s] to vector [a] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest -= (a + b) + */ +CGLM_INLINE +void +glm_ivec3_addsubs(ivec3 a, int s, ivec3 dest) { + dest[0] -= a[0] + s; + dest[1] -= a[1] + s; + dest[2] -= a[2] + s; +} + +/*! + * @brief multiply vector [a] and vector [b] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] b scalar + * @param[out] dest dest -= (a * b) + */ +CGLM_INLINE +void +glm_ivec3_mulsub(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] -= a[0] * b[0]; + dest[1] -= a[1] * b[1]; + dest[2] -= a[2] * b[2]; +} + +/*! + * @brief multiply vector [a] with scalar [s] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest -= (a * s) + */ +CGLM_INLINE +void +glm_ivec3_mulsubs(ivec3 a, int s, ivec3 dest) { + dest[0] -= a[0] * s; + dest[1] -= a[1] * s; + dest[2] -= a[2] * s; +} + +/*! + * @brief subtract maximum of vector [a] and vector [b] from vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest -= max(a, b) + */ +CGLM_INLINE +void +glm_ivec3_maxsub(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] -= glm_imax(a[0], b[0]); + dest[1] -= glm_imax(a[1], b[1]); + dest[2] -= glm_imax(a[2], b[2]); +} + +/*! + * @brief subtract minimum of vector [a] and vector [b] from vector [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest -= min(a, b) + */ +CGLM_INLINE +void +glm_ivec3_minsub(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] -= glm_imin(a[0], b[0]); + dest[1] -= glm_imin(a[1], b[1]); + dest[2] -= glm_imin(a[2], b[2]); +} + +/*! + * @brief squared distance between two vectors + * + * @param[in] a first vector + * @param[in] b second vector + * @return returns squared distance (distance * distance) + */ +CGLM_INLINE +int +glm_ivec3_distance2(ivec3 a, ivec3 b) { + int xd, yd, zd; + xd = a[0] - b[0]; + yd = a[1] - b[1]; + zd = a[2] - b[2]; + return xd * xd + yd * yd + zd * zd; +} + +/*! + * @brief distance between two vectors + * + * @param[in] a first vector + * @param[in] b second vector + * @return returns distance + */ +CGLM_INLINE +float +glm_ivec3_distance(ivec3 a, ivec3 b) { + return sqrtf((float)glm_ivec3_distance2(a, b)); +} + +/*! + * @brief fill a vector with specified value + * + * @param[out] v dest + * @param[in] val value + */ +CGLM_INLINE +void +glm_ivec3_fill(ivec3 v, int val) { + v[0] = v[1] = v[2] = val; +} + +/*! + * @brief check if vector is equal to value + * + * @param[in] v vector + * @param[in] val value + */ +CGLM_INLINE +bool +glm_ivec3_eq(ivec3 v, int val) { + return v[0] == val && v[0] == v[1] && v[0] == v[2]; +} + +/*! + * @brief check if vector is equal to another + * + * @param[in] a vector + * @param[in] b vector + */ +CGLM_INLINE +bool +glm_ivec3_eqv(ivec3 a, ivec3 b) { + return a[0] == b[0] + && a[1] == b[1] + && a[2] == b[2]; +} + +/*! + * @brief set each member of dest to greater of vector a and b + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec3_maxv(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] = a[0] > b[0] ? a[0] : b[0]; + dest[1] = a[1] > b[1] ? a[1] : b[1]; + dest[2] = a[2] > b[2] ? a[2] : b[2]; +} + +/*! + * @brief set each member of dest to lesser of vector a and b + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec3_minv(ivec3 a, ivec3 b, ivec3 dest) { + dest[0] = a[0] < b[0] ? a[0] : b[0]; + dest[1] = a[1] < b[1] ? a[1] : b[1]; + dest[2] = a[2] < b[2] ? a[2] : b[2]; +} + +/*! + * @brief clamp each member of [v] between minVal and maxVal (inclusive) + * + * @param[in, out] v vector + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + */ +CGLM_INLINE +void +glm_ivec3_clamp(ivec3 v, int minVal, int maxVal) { + if (v[0] < minVal) + v[0] = minVal; + else if(v[0] > maxVal) + v[0] = maxVal; + + if (v[1] < minVal) + v[1] = minVal; + else if(v[1] > maxVal) + v[1] = maxVal; + + if (v[2] < minVal) + v[2] = minVal; + else if(v[2] > maxVal) + v[2] = maxVal; +} + +/*! + * @brief absolute value of v + * + * @param[in] v vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec3_abs(ivec3 v, ivec3 dest) { + dest[0] = abs(v[0]); + dest[1] = abs(v[1]); + dest[2] = abs(v[2]); +} + +#endif /* cglm_ivec3_h */ diff --git a/external/cglm/ivec4.h b/external/cglm/ivec4.h new file mode 100644 index 0000000..6357599 --- /dev/null +++ b/external/cglm/ivec4.h @@ -0,0 +1,608 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_IVEC4_ONE_INIT + GLM_IVEC4_ZERO_INIT + GLM_IVEC4_ONE + GLM_IVEC4_ZERO + + Functions: + CGLM_INLINE void glm_ivec4(ivec3 v3, int last, ivec4 dest) + CGLM_INLINE void glm_ivec4_copy(ivec4 a, ivec4 dest) + CGLM_INLINE void glm_ivec4_zero(ivec4 v) + CGLM_INLINE void glm_ivec4_one(ivec4 v) + CGLM_INLINE void glm_ivec4_add(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE void glm_ivec4_adds(ivec4 v, int s, ivec4 dest) + CGLM_INLINE void glm_ivec4_sub(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE void glm_ivec4_subs(ivec4 v, int s, ivec4 dest) + CGLM_INLINE void glm_ivec4_mul(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE void glm_ivec4_scale(ivec4 v, int s, ivec4 dest) + CGLM_INLINE void glm_ivec4_addadd(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE void glm_ivec4_addadds(ivec4 a, int s, ivec4 dest) + CGLM_INLINE void glm_ivec4_subadd(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE void glm_ivec4_subadds(ivec4 a, int s, ivec4 dest) + CGLM_INLINE void glm_ivec4_muladd(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE void glm_ivec4_muladds(ivec4 a, int s, ivec4 dest) + CGLM_INLINE void glm_ivec4_maxadd(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE void glm_ivec4_minadd(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE void glm_ivec4_subsub(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE void glm_ivec4_subsubs(ivec4 a, int s, ivec4 dest) + CGLM_INLINE void glm_ivec4_addsub(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE void glm_ivec4_addsubs(ivec4 a, int s, ivec4 dest) + CGLM_INLINE void glm_ivec4_mulsub(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE void glm_ivec4_mulsubs(ivec4 a, int s, ivec4 dest) + CGLM_INLINE void glm_ivec4_maxsub(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE void glm_ivec4_minsub(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE int glm_ivec4_distance2(ivec4 a, ivec4 b) + CGLM_INLINE float glm_ivec4_distance(ivec4 a, ivec4 b) + CGLM_INLINE void glm_ivec4_maxv(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE void glm_ivec4_minv(ivec4 a, ivec4 b, ivec4 dest) + CGLM_INLINE void glm_ivec4_clamp(ivec4 v, int minVal, int maxVal) + CGLM_INLINE void glm_ivec4_abs(ivec4 v, ivec4 dest) + */ + +#ifndef cglm_ivec4_h +#define cglm_ivec4_h + +#include "common.h" +#include "util.h" + +#define GLM_IVEC4_ONE_INIT {1, 1, 1, 1} +#define GLM_IVEC4_ZERO_INIT {0, 0, 0, 0} + +#define GLM_IVEC4_ONE ((ivec4)GLM_IVEC4_ONE_INIT) +#define GLM_IVEC4_ZERO ((ivec4)GLM_IVEC4_ZERO_INIT) + +/*! + * @brief init ivec4 using ivec3 + * + * @param[in] v3 vector3 + * @param[in] last last item + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec4(ivec3 v3, int last, ivec4 dest) { + dest[0] = v3[0]; + dest[1] = v3[1]; + dest[2] = v3[2]; + dest[3] = last; +} + +/*! + * @brief copy all members of [a] to [dest] + * + * @param[in] a source vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec4_copy(ivec4 a, ivec4 dest) { + dest[0] = a[0]; + dest[1] = a[1]; + dest[2] = a[2]; + dest[3] = a[3]; +} + +/*! + * @brief set all members of [v] to zero + * + * @param[out] v vector + */ +CGLM_INLINE +void +glm_ivec4_zero(ivec4 v) { + v[0] = v[1] = v[2] = v[3] = 0; +} + +/*! + * @brief set all members of [v] to one + * + * @param[out] v vector + */ +CGLM_INLINE +void +glm_ivec4_one(ivec4 v) { + v[0] = v[1] = v[2] = v[3] = 1; +} + +/*! + * @brief add vector [a] to vector [b] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec4_add(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] = a[0] + b[0]; + dest[1] = a[1] + b[1]; + dest[2] = a[2] + b[2]; + dest[3] = a[3] + b[3]; +} + +/*! + * @brief add scalar s to vector [v] and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec4_adds(ivec4 v, int s, ivec4 dest) { + dest[0] = v[0] + s; + dest[1] = v[1] + s; + dest[2] = v[2] + s; + dest[3] = v[3] + s; +} + +/*! + * @brief subtract vector [b] from vector [a] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec4_sub(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] = a[0] - b[0]; + dest[1] = a[1] - b[1]; + dest[2] = a[2] - b[2]; + dest[3] = a[3] - b[3]; +} + +/*! + * @brief subtract scalar s from vector [v] and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec4_subs(ivec4 v, int s, ivec4 dest) { + dest[0] = v[0] - s; + dest[1] = v[1] - s; + dest[2] = v[2] - s; + dest[3] = v[3] - s; +} + +/*! + * @brief multiply vector [a] with vector [b] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec4_mul(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] = a[0] * b[0]; + dest[1] = a[1] * b[1]; + dest[2] = a[2] * b[2]; + dest[3] = a[3] * b[3]; +} + +/*! + * @brief multiply vector [a] with scalar s and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec4_scale(ivec4 v, int s, ivec4 dest) { + dest[0] = v[0] * s; + dest[1] = v[1] * s; + dest[2] = v[2] * s; + dest[3] = v[3] * s; +} + +/*! + * @brief add vector [a] with vector [b] and add result to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += (a + b) + */ +CGLM_INLINE +void +glm_ivec4_addadd(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] += a[0] + b[0]; + dest[1] += a[1] + b[1]; + dest[2] += a[2] + b[2]; + dest[3] += a[3] + b[3]; +} + +/*! + * @brief add scalar [s] onto vector [a] and add result to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest += (a + s) + */ +CGLM_INLINE +void +glm_ivec4_addadds(ivec4 a, int s, ivec4 dest) { + dest[0] += a[0] + s; + dest[1] += a[1] + s; + dest[2] += a[2] + s; + dest[3] += a[3] + s; +} + +/*! + * @brief subtract vector [a] from vector [b] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += (a - b) + */ +CGLM_INLINE +void +glm_ivec4_subadd(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] += a[0] - b[0]; + dest[1] += a[1] - b[1]; + dest[2] += a[2] - b[2]; + dest[3] += a[3] - b[3]; +} + +/*! + * @brief subtract scalar [s] from vector [a] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first + * @param[in] s scalar + * @param[out] dest dest += (a - s) + */ +CGLM_INLINE +void +glm_ivec4_subadds(ivec4 a, int s, ivec4 dest) { + dest[0] += a[0] - s; + dest[1] += a[1] - s; + dest[2] += a[2] - s; + dest[3] += a[3] - s; +} + +/*! + * @brief multiply vector [a] with vector [b] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_ivec4_muladd(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] += a[0] * b[0]; + dest[1] += a[1] * b[1]; + dest[2] += a[2] * b[2]; + dest[3] += a[3] * b[3]; +} + +/*! + * @brief multiply vector [a] with scalar [s] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest += (a * s) + */ +CGLM_INLINE +void +glm_ivec4_muladds(ivec4 a, int s, ivec4 dest) { + dest[0] += a[0] * s; + dest[1] += a[1] * s; + dest[2] += a[2] * s; + dest[3] += a[3] * s; +} + +/*! + * @brief add maximum of vector [a] and vector [b] to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += max(a, b) + */ +CGLM_INLINE +void +glm_ivec4_maxadd(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] += glm_imax(a[0], b[0]); + dest[1] += glm_imax(a[1], b[1]); + dest[2] += glm_imax(a[2], b[2]); + dest[3] += glm_imax(a[3], b[3]); +} + +/*! + * @brief add minimum of vector [a] and vector [b] to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest += min(a, b) + */ +CGLM_INLINE +void +glm_ivec4_minadd(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] += glm_imin(a[0], b[0]); + dest[1] += glm_imin(a[1], b[1]); + dest[2] += glm_imin(a[2], b[2]); + dest[3] += glm_imin(a[3], b[3]); +} + +/*! + * @brief subtract vector [a] from vector [b] and subtract result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest -= (a - b) + */ +CGLM_INLINE +void +glm_ivec4_subsub(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] -= a[0] - b[0]; + dest[1] -= a[1] - b[1]; + dest[2] -= a[2] - b[2]; + dest[3] -= a[3] - b[3]; +} + +/*! + * @brief subtract scalar [s] from vector [a] and subtract result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest -= (a - s) + */ +CGLM_INLINE +void +glm_ivec4_subsubs(ivec4 a, int s, ivec4 dest) { + dest[0] -= a[0] - s; + dest[1] -= a[1] - s; + dest[2] -= a[2] - s; + dest[3] -= a[3] - s; +} + +/*! + * @brief add vector [a] to vector [b] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] b scalar + * @param[out] dest dest -= (a + b) + */ +CGLM_INLINE +void +glm_ivec4_addsub(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] -= a[0] + b[0]; + dest[1] -= a[1] + b[1]; + dest[2] -= a[2] + b[2]; + dest[3] -= a[3] + b[3]; +} + +/*! + * @brief add scalar [s] to vector [a] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest -= (a + b) + */ +CGLM_INLINE +void +glm_ivec4_addsubs(ivec4 a, int s, ivec4 dest) { + dest[0] -= a[0] + s; + dest[1] -= a[1] + s; + dest[2] -= a[2] + s; + dest[3] -= a[3] + s; +} + +/*! + * @brief multiply vector [a] and vector [b] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] b scalar + * @param[out] dest dest -= (a * b) + */ +CGLM_INLINE +void +glm_ivec4_mulsub(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] -= a[0] * b[0]; + dest[1] -= a[1] * b[1]; + dest[2] -= a[2] * b[2]; + dest[3] -= a[3] * b[3]; +} + +/*! + * @brief multiply vector [a] with scalar [s] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest -= (a * s) + */ +CGLM_INLINE +void +glm_ivec4_mulsubs(ivec4 a, int s, ivec4 dest) { + dest[0] -= a[0] * s; + dest[1] -= a[1] * s; + dest[2] -= a[2] * s; + dest[3] -= a[3] * s; +} + +/*! + * @brief subtract maximum of vector [a] and vector [b] from vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest -= max(a, b) + */ +CGLM_INLINE +void +glm_ivec4_maxsub(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] -= glm_imax(a[0], b[0]); + dest[1] -= glm_imax(a[1], b[1]); + dest[2] -= glm_imax(a[2], b[2]); + dest[3] -= glm_imax(a[3], b[3]); +} + +/*! + * @brief subtract minimum of vector [a] and vector [b] from vector [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest dest -= min(a, b) + */ +CGLM_INLINE +void +glm_ivec4_minsub(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] -= glm_imin(a[0], b[0]); + dest[1] -= glm_imin(a[1], b[1]); + dest[2] -= glm_imin(a[2], b[2]); + dest[3] -= glm_imin(a[3], b[3]); +} + +/*! + * @brief squared distance between two vectors + * + * @param[in] a first vector + * @param[in] b second vector + * @return returns squared distance (distance * distance) + */ +CGLM_INLINE +int +glm_ivec4_distance2(ivec4 a, ivec4 b) { + int xd, yd, zd, wd; + xd = a[0] - b[0]; + yd = a[1] - b[1]; + zd = a[2] - b[2]; + wd = a[3] - b[3]; + return xd * xd + yd * yd + zd * zd + wd * wd; +} + +/*! + * @brief distance between two vectors + * + * @param[in] a first vector + * @param[in] b second vector + * @return returns distance + */ +CGLM_INLINE +float +glm_ivec4_distance(ivec4 a, ivec4 b) { + return sqrtf((float)glm_ivec4_distance2(a, b)); +} + +/*! + * @brief set each member of dest to greater of vector a and b + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec4_maxv(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] = a[0] > b[0] ? a[0] : b[0]; + dest[1] = a[1] > b[1] ? a[1] : b[1]; + dest[2] = a[2] > b[2] ? a[2] : b[2]; + dest[3] = a[3] > b[3] ? a[3] : b[3]; +} + +/*! + * @brief set each member of dest to lesser of vector a and b + * + * @param[in] a first vector + * @param[in] b second vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec4_minv(ivec4 a, ivec4 b, ivec4 dest) { + dest[0] = a[0] < b[0] ? a[0] : b[0]; + dest[1] = a[1] < b[1] ? a[1] : b[1]; + dest[2] = a[2] < b[2] ? a[2] : b[2]; + dest[3] = a[3] < b[3] ? a[3] : b[3]; +} + +/*! + * @brief clamp each member of [v] between minVal and maxVal (inclusive) + * + * @param[in, out] v vector + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + */ +CGLM_INLINE +void +glm_ivec4_clamp(ivec4 v, int minVal, int maxVal) { + if (v[0] < minVal) + v[0] = minVal; + else if(v[0] > maxVal) + v[0] = maxVal; + + if (v[1] < minVal) + v[1] = minVal; + else if(v[1] > maxVal) + v[1] = maxVal; + + if (v[2] < minVal) + v[2] = minVal; + else if(v[2] > maxVal) + v[2] = maxVal; + + if (v[3] < minVal) + v[3] = minVal; + else if(v[3] > maxVal) + v[3] = maxVal; +} + +/*! + * @brief absolute value of v + * + * @param[in] v vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_ivec4_abs(ivec4 v, ivec4 dest) { + dest[0] = abs(v[0]); + dest[1] = abs(v[1]); + dest[2] = abs(v[2]); + dest[3] = abs(v[3]); +} + +#endif /* cglm_ivec4_h */ diff --git a/external/cglm/mat2.h b/external/cglm/mat2.h new file mode 100644 index 0000000..9248460 --- /dev/null +++ b/external/cglm/mat2.h @@ -0,0 +1,363 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_MAT2_IDENTITY_INIT + GLM_MAT2_ZERO_INIT + GLM_MAT2_IDENTITY + GLM_MAT2_ZERO + + Functions: + CGLM_INLINE void glm_mat2_make(float * restrict src, mat2 dest) + CGLM_INLINE void glm_mat2_copy(mat2 mat, mat2 dest) + CGLM_INLINE void glm_mat2_identity(mat2 m) + CGLM_INLINE void glm_mat2_identity_array(mat2 * restrict mats, size_t count) + CGLM_INLINE void glm_mat2_zero(mat2 m) + CGLM_INLINE void glm_mat2_mul(mat2 m1, mat2 m2, mat2 dest) + CGLM_INLINE void glm_mat2_mulv(mat2 m, vec2 v, vec2 dest) + CGLM_INLINE void glm_mat2_transpose_to(mat2 mat, mat2 dest) + CGLM_INLINE void glm_mat2_transpose(mat2 m) + CGLM_INLINE void glm_mat2_scale(mat2 m, float s) + CGLM_INLINE void glm_mat2_inv(mat2 mat, mat2 dest) + CGLM_INLINE void glm_mat2_swap_col(mat2 mat, int col1, int col2) + CGLM_INLINE void glm_mat2_swap_row(mat2 mat, int row1, int row2) + CGLM_INLINE float glm_mat2_det(mat2 m) + CGLM_INLINE float glm_mat2_trace(mat2 m) + CGLM_INLINE float glm_mat2_rmc(vec2 r, mat2 m, vec2 c) + */ + +#ifndef cglm_mat2_h +#define cglm_mat2_h + +#include "common.h" +#include "vec2.h" + +#ifdef CGLM_SSE_FP +# include "simd/sse2/mat2.h" +#endif + +#ifdef CGLM_NEON_FP +# include "simd/neon/mat2.h" +#endif + +#ifdef CGLM_SIMD_WASM +# include "simd/wasm/mat2.h" +#endif + +#define GLM_MAT2_IDENTITY_INIT {{1.0f, 0.0f}, {0.0f, 1.0f}} +#define GLM_MAT2_ZERO_INIT {{0.0f, 0.0f}, {0.0f, 0.0f}} + +/* for C only */ +#define GLM_MAT2_IDENTITY ((mat2)GLM_MAT2_IDENTITY_INIT) +#define GLM_MAT2_ZERO ((mat2)GLM_MAT2_ZERO_INIT) + +/*! + * @brief Create mat2 (dest) from pointer (src). + * + * @param[in] src pointer to an array of floats (left) + * @param[out] dest destination (result, mat2) + */ +CGLM_INLINE +void +glm_mat2_make(const float * __restrict src, mat2 dest) { + dest[0][0] = src[0]; + dest[0][1] = src[1]; + dest[1][0] = src[2]; + dest[1][1] = src[3]; +} + +/*! + * @brief Copy mat2 (mat) to mat2 (dest). + * + * @param[in] mat mat2 (left, src) + * @param[out] dest destination (result, mat2) + */ +CGLM_INLINE +void +glm_mat2_copy(mat2 mat, mat2 dest) { + glm_vec4_ucopy(mat[0], dest[0]); +} + +/*! + * @brief Copy a mat2 identity to mat2 (m), or makes mat2 (m) an identity. + * + * The same thing may be achieved with either of bellow methods, + * but it is more easy to do that with this func especially for members + * e.g. glm_mat2_identity(aStruct->aMatrix); + * + * @code + * glm_mat2_copy(GLM_MAT2_IDENTITY, mat); // C only + * + * // or + * mat2 mat = GLM_MAT2_IDENTITY_INIT; + * @endcode + * + * @param[in, out] m mat2 (src, dest) + */ +CGLM_INLINE +void +glm_mat2_identity(mat2 m) { + CGLM_ALIGN_MAT mat2 t = GLM_MAT2_IDENTITY_INIT; + glm_mat2_copy(t, m); +} + +/*! + * @brief Given an array of mat2’s (mats) make each matrix an identity matrix. + * + * @param[in, out] mats Array of mat2’s (must be aligned (16/32) if alignment is not disabled) + * @param[in] count Array size of mats or number of matrices + */ +CGLM_INLINE +void +glm_mat2_identity_array(mat2 * __restrict mats, size_t count) { + CGLM_ALIGN_MAT mat2 t = GLM_MAT2_IDENTITY_INIT; + size_t i; + + for (i = 0; i < count; i++) { + glm_mat2_copy(t, mats[i]); + } +} + +/*! + * @brief Zero out the mat2 (m). + * + * @param[in, out] m mat2 (src, dest) + */ +CGLM_INLINE +void +glm_mat2_zero(mat2 m) { + CGLM_ALIGN_MAT mat2 t = GLM_MAT2_ZERO_INIT; + glm_mat2_copy(t, m); +} + +/*! + * @brief Multiply mat2 (m1) by mat2 (m2) and store in mat2 (dest). + * + * m1, m2 and dest matrices can be same matrix, it is possible to write this: + * + * @code + * mat2 m = GLM_MAT2_IDENTITY_INIT; + * glm_mat2_mul(m, m, m); + * @endcode + * + * @param[in] m1 mat2 (left) + * @param[in] m2 mat2 (right) + * @param[out] dest destination (result, mat2) + */ +CGLM_INLINE +void +glm_mat2_mul(mat2 m1, mat2 m2, mat2 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_mat2_mul_wasm(m1, m2, dest); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glm_mat2_mul_sse2(m1, m2, dest); +#elif defined(CGLM_NEON_FP) + glm_mat2_mul_neon(m1, m2, dest); +#else + float a00 = m1[0][0], a01 = m1[0][1], + a10 = m1[1][0], a11 = m1[1][1], + b00 = m2[0][0], b01 = m2[0][1], + b10 = m2[1][0], b11 = m2[1][1]; + + dest[0][0] = a00 * b00 + a10 * b01; + dest[0][1] = a01 * b00 + a11 * b01; + dest[1][0] = a00 * b10 + a10 * b11; + dest[1][1] = a01 * b10 + a11 * b11; +#endif +} + +/*! + * @brief Multiply mat2 (m) by vec2 (v) and store in vec2 (dest). + * + * @param[in] m mat2 (left) + * @param[in] v vec2 (right, column vector) + * @param[out] dest destination (result, column vector) + */ +CGLM_INLINE +void +glm_mat2_mulv(mat2 m, vec2 v, vec2 dest) { + dest[0] = m[0][0] * v[0] + m[1][0] * v[1]; + dest[1] = m[0][1] * v[0] + m[1][1] * v[1]; +} + +/*! + * @brief Transpose mat2 (mat) and store in mat2 (dest). + * + * @param[in] mat mat2 (left, src) + * @param[out] dest destination (result, mat2) + */ +CGLM_INLINE +void +glm_mat2_transpose_to(mat2 mat, mat2 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_mat2_transp_wasm(mat, dest); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glm_mat2_transp_sse2(mat, dest); +#else + dest[0][0] = mat[0][0]; + dest[0][1] = mat[1][0]; + dest[1][0] = mat[0][1]; + dest[1][1] = mat[1][1]; +#endif +} + +/*! + * @brief Transpose mat2 (m) and store result in the same matrix. + * + * @param[in, out] m mat2 (src, dest) + */ +CGLM_INLINE +void +glm_mat2_transpose(mat2 m) { + float tmp; + tmp = m[0][1]; + m[0][1] = m[1][0]; + m[1][0] = tmp; +} + +/*! + * @brief Multiply mat2 (m) by scalar constant (s). + * + * @param[in, out] m mat2 (src, dest) + * @param[in] s float (scalar) + */ +CGLM_INLINE +void +glm_mat2_scale(mat2 m, float s) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(m[0], wasm_f32x4_mul(wasm_v128_load(m[0]), + wasm_f32x4_splat(s))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(m[0], _mm_mul_ps(_mm_loadu_ps(m[0]), glmm_set1(s))); +#elif defined(CGLM_NEON_FP) + vst1q_f32(m[0], vmulq_f32(vld1q_f32(m[0]), vdupq_n_f32(s))); +#else + m[0][0] = m[0][0] * s; + m[0][1] = m[0][1] * s; + m[1][0] = m[1][0] * s; + m[1][1] = m[1][1] * s; +#endif +} + +/*! + * @brief Inverse mat2 (mat) and store in mat2 (dest). + * + * @param[in] mat mat2 (left, src) + * @param[out] dest destination (result, inverse mat2) + */ +CGLM_INLINE +void +glm_mat2_inv(mat2 mat, mat2 dest) { + float det; + float a = mat[0][0], b = mat[0][1], + c = mat[1][0], d = mat[1][1]; + + det = 1.0f / (a * d - b * c); + + dest[0][0] = d * det; + dest[0][1] = -b * det; + dest[1][0] = -c * det; + dest[1][1] = a * det; +} + +/*! + * @brief Swap two columns in mat2 (mat) and store in same matrix. + * + * @param[in, out] mat mat2 (src, dest) + * @param[in] col1 Column 1 array index + * @param[in] col2 Column 2 array index + */ +CGLM_INLINE +void +glm_mat2_swap_col(mat2 mat, int col1, int col2) { + float a, b; + + a = mat[col1][0]; + b = mat[col1][1]; + + mat[col1][0] = mat[col2][0]; + mat[col1][1] = mat[col2][1]; + + mat[col2][0] = a; + mat[col2][1] = b; +} + +/*! + * @brief Swap two rows in mat2 (mat) and store in same matrix. + * + * @param[in, out] mat mat2 (src, dest) + * @param[in] row1 Row 1 array index + * @param[in] row2 Row 2 array index + */ +CGLM_INLINE +void +glm_mat2_swap_row(mat2 mat, int row1, int row2) { + float a, b; + + a = mat[0][row1]; + b = mat[1][row1]; + + mat[0][row1] = mat[0][row2]; + mat[1][row1] = mat[1][row2]; + + mat[0][row2] = a; + mat[1][row2] = b; +} + +/*! + * @brief Returns mat2 determinant. + * + * @param[in] m mat2 (src) + * + * @return[out] mat2 determinant (float) + */ +CGLM_INLINE +float +glm_mat2_det(mat2 m) { + return m[0][0] * m[1][1] - m[1][0] * m[0][1]; +} + +/*! + * @brief Returns trace of matrix. Which is: + * + * The sum of the elements on the main diagonal from + * upper left corner to the bottom right corner. + * + * @param[in] m mat2 (src) + * + * @return[out] mat2 trace (float) + */ +CGLM_INLINE +float +glm_mat2_trace(mat2 m) { + return m[0][0] + m[1][1]; +} + +/*! + * @brief Helper for R (row vector) * M (matrix) * C (column vector) + * + * rmc stands for Row * Matrix * Column + * + * the result is scalar because M * C = ResC (1x2, column vector), + * then if you take the dot_product(R (2x1), ResC (1x2)) = scalar value. + * + * @param[in] r vec2 (2x1, row vector) + * @param[in] m mat2 (2x2, matrix) + * @param[in] c vec2 (1x2, column vector) + * + * @return[out] Scalar value (float, 1x1) + */ +CGLM_INLINE +float +glm_mat2_rmc(vec2 r, mat2 m, vec2 c) { + vec2 tmp; + glm_mat2_mulv(m, c, tmp); + return glm_vec2_dot(r, tmp); +} + +#endif /* cglm_mat2_h */ diff --git a/external/cglm/mat2x3.h b/external/cglm/mat2x3.h new file mode 100644 index 0000000..0bb8d70 --- /dev/null +++ b/external/cglm/mat2x3.h @@ -0,0 +1,154 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_MAT2X3_ZERO_INIT + GLM_MAT2X3_ZERO + + Functions: + CGLM_INLINE void glm_mat2x3_copy(mat2x3 src, mat2x3 dest); + CGLM_INLINE void glm_mat2x3_zero(mat2x3 m); + CGLM_INLINE void glm_mat2x3_make(const float * __restrict src, mat2x3 dest); + CGLM_INLINE void glm_mat2x3_mul(mat2x3 m1, mat3x2 m2, mat3 dest); + CGLM_INLINE void glm_mat2x3_mulv(mat2x3 m, vec2 v, vec3 dest); + CGLM_INLINE void glm_mat2x3_transpose(mat2x3 src, mat3x2 dest); + CGLM_INLINE void glm_mat2x3_scale(mat2x3 m, float s); + */ + +#ifndef cglm_mat2x3_h +#define cglm_mat2x3_h + +#include "common.h" + +#define GLM_MAT2X3_ZERO_INIT {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}} + +/* for C only */ +#define GLM_MAT2X3_ZERO GLM_MAT2X3_ZERO_INIT + +/*! + * @brief Copy mat2x3 (src) to mat2x3 (dest). + * + * @param[in] src mat2x3 (left) + * @param[out] dest destination (result, mat2x3) + */ +CGLM_INLINE +void +glm_mat2x3_copy(mat2x3 src, mat2x3 dest) { + glm_vec3_copy(src[0], dest[0]); + glm_vec3_copy(src[1], dest[1]); +} + +/*! + * @brief Zero out the mat2x3 (m). + * + * @param[in, out] mat2x3 (src, dest) + */ +CGLM_INLINE +void +glm_mat2x3_zero(mat2x3 m) { + CGLM_ALIGN_MAT mat2x3 t = GLM_MAT2X3_ZERO_INIT; + glm_mat2x3_copy(t, m); +} + +/*! + * @brief Create mat2x3 (dest) from pointer (src). + * + * @param[in] src pointer to an array of floats (left) + * @param[out] dest destination (result, mat2x3) + */ +CGLM_INLINE +void +glm_mat2x3_make(const float * __restrict src, mat2x3 dest) { + dest[0][0] = src[0]; + dest[0][1] = src[1]; + dest[0][2] = src[2]; + + dest[1][0] = src[3]; + dest[1][1] = src[4]; + dest[1][2] = src[5]; +} + +/*! + * @brief Multiply mat2x3 (m1) by mat3x2 (m2) and store in mat3 (dest). + * + * @code + * glm_mat2x3_mul(mat2x3, mat3x2, mat3); + * @endcode + * + * @param[in] m1 mat2x3 (left) + * @param[in] m2 mat3x2 (right) + * @param[out] dest destination (result, mat3) + */ +CGLM_INLINE +void +glm_mat2x3_mul(mat2x3 m1, mat3x2 m2, mat3 dest) { + float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], + a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2], + + b00 = m2[0][0], b01 = m2[0][1], + b10 = m2[1][0], b11 = m2[1][1], + b20 = m2[2][0], b21 = m2[2][1]; + + dest[0][0] = a00 * b00 + a10 * b01; + dest[0][1] = a01 * b00 + a11 * b01; + dest[0][2] = a02 * b00 + a12 * b01; + + dest[1][0] = a00 * b10 + a10 * b11; + dest[1][1] = a01 * b10 + a11 * b11; + dest[1][2] = a02 * b10 + a12 * b11; + + dest[2][0] = a00 * b20 + a10 * b21; + dest[2][1] = a01 * b20 + a11 * b21; + dest[2][2] = a02 * b20 + a12 * b21; +} + +/*! + * @brief Multiply mat2x3 (m) by vec2 (v) and store in vec3 (dest). + * + * @param[in] m mat2x3 (left) + * @param[in] v vec2 (right, column vector) + * @param[out] dest destination (result, column vector) + */ +CGLM_INLINE +void +glm_mat2x3_mulv(mat2x3 m, vec2 v, vec3 dest) { + float v0 = v[0], v1 = v[1]; + + dest[0] = m[0][0] * v0 + m[1][0] * v1; + dest[1] = m[0][1] * v0 + m[1][1] * v1; + dest[2] = m[0][2] * v0 + m[1][2] * v1; +} + +/*! + * @brief Transpose mat2x3 (src) and store in mat3x2 (dest). + * + * @param[in] src mat2x3 (left) + * @param[out] dest destination (result, mat3x2) + */ +CGLM_INLINE +void +glm_mat2x3_transpose(mat2x3 src, mat3x2 dest) { + dest[0][0] = src[0][0]; dest[0][1] = src[1][0]; + dest[1][0] = src[0][1]; dest[1][1] = src[1][1]; + dest[2][0] = src[0][2]; dest[2][1] = src[1][2]; +} + +/*! + * @brief Multiply mat2x3 (m) by scalar constant (s). + * + * @param[in, out] m (src, dest) + * @param[in] float (scalar) + */ +CGLM_INLINE +void +glm_mat2x3_scale(mat2x3 m, float s) { + m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; + m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; +} + +#endif diff --git a/external/cglm/mat2x4.h b/external/cglm/mat2x4.h new file mode 100644 index 0000000..fa9adf3 --- /dev/null +++ b/external/cglm/mat2x4.h @@ -0,0 +1,168 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_MAT2X4_ZERO_INIT + GLM_MAT2X4_ZERO + + Functions: + CGLM_INLINE void glm_mat2x4_copy(mat2x4 src, mat2x4 dest); + CGLM_INLINE void glm_mat2x4_zero(mat2x4 m); + CGLM_INLINE void glm_mat2x4_make(const float * __restrict src, mat2x4 dest); + CGLM_INLINE void glm_mat2x4_mul(mat2x4 m1, mat4x2 m2, mat4 dest); + CGLM_INLINE void glm_mat2x4_mulv(mat2x4 m, vec2 v, vec4 dest); + CGLM_INLINE void glm_mat2x4_transpose(mat2x4 src, mat4x2 dest); + CGLM_INLINE void glm_mat2x4_scale(mat2x4 m, float s); + */ + +#ifndef cglm_mat2x4_h +#define cglm_mat2x4_h + +#include "common.h" +#include "vec4.h" + +#define GLM_MAT2X4_ZERO_INIT {{0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}} + +/* for C only */ +#define GLM_MAT2X4_ZERO GLM_MAT2X4_ZERO_INIT + +/*! + * @brief Copy mat2x4 (src) to mat2x4 (dest). + * + * @param[in] src mat2x4 (left) + * @param[out] dest destination (result, mat2x4) + */ +CGLM_INLINE +void +glm_mat2x4_copy(mat2x4 src, mat2x4 dest) { + glm_vec4_ucopy(src[0], dest[0]); + glm_vec4_ucopy(src[1], dest[1]); +} + +/*! + * @brief Zero out the mat2x4 (m). + * + * @param[in, out] mat2x4 (src, dest) + */ +CGLM_INLINE +void +glm_mat2x4_zero(mat2x4 m) { + CGLM_ALIGN_MAT mat2x4 t = GLM_MAT2X4_ZERO_INIT; + glm_mat2x4_copy(t, m); +} + +/*! + * @brief Create mat2x4 (dest) from pointer (src). + * + * @param[in] src pointer to an array of floats (left) + * @param[out] dest destination (result, mat2x4) + */ +CGLM_INLINE +void +glm_mat2x4_make(const float * __restrict src, mat2x4 dest) { + dest[0][0] = src[0]; + dest[0][1] = src[1]; + dest[0][2] = src[2]; + dest[0][3] = src[3]; + + dest[1][0] = src[4]; + dest[1][1] = src[5]; + dest[1][2] = src[6]; + dest[1][3] = src[7]; +} + +/*! + * @brief Multiply mat2x4 (m1) by mat4x2 (m2) and store in mat4 (dest). + * + * @code + * glm_mat2x4_mul(mat2x4, mat4x2, mat4); + * @endcode + * + * @param[in] m1 mat2x4 (left) + * @param[in] m2 mat4x2 (right) + * @param[out] dest destination (result, mat4) + */ +CGLM_INLINE +void +glm_mat2x4_mul(mat2x4 m1, mat4x2 m2, mat4 dest) { + float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], a03 = m1[0][3], + a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2], a13 = m1[1][3], + + b00 = m2[0][0], b01 = m2[0][1], + b10 = m2[1][0], b11 = m2[1][1], + b20 = m2[2][0], b21 = m2[2][1], + b30 = m2[3][0], b31 = m2[3][1]; + + dest[0][0] = a00 * b00 + a10 * b01; + dest[0][1] = a01 * b00 + a11 * b01; + dest[0][2] = a02 * b00 + a12 * b01; + dest[0][3] = a03 * b00 + a13 * b01; + + dest[1][0] = a00 * b10 + a10 * b11; + dest[1][1] = a01 * b10 + a11 * b11; + dest[1][2] = a02 * b10 + a12 * b11; + dest[1][3] = a03 * b10 + a13 * b11; + + dest[2][0] = a00 * b20 + a10 * b21; + dest[2][1] = a01 * b20 + a11 * b21; + dest[2][2] = a02 * b20 + a12 * b21; + dest[2][3] = a03 * b20 + a13 * b21; + + dest[3][0] = a00 * b30 + a10 * b31; + dest[3][1] = a01 * b30 + a11 * b31; + dest[3][2] = a02 * b30 + a12 * b31; + dest[3][3] = a03 * b30 + a13 * b31; +} + +/*! + * @brief Multiply mat2x4 (m) by vec2 (v) and store in vec4 (dest). + * + * @param[in] m mat2x4 (left) + * @param[in] v vec2 (right, column vector) + * @param[out] dest destination (result, column vector) + */ +CGLM_INLINE +void +glm_mat2x4_mulv(mat2x4 m, vec2 v, vec4 dest) { + float v0 = v[0], v1 = v[1]; + + dest[0] = m[0][0] * v0 + m[1][0] * v1; + dest[1] = m[0][1] * v0 + m[1][1] * v1; + dest[2] = m[0][2] * v0 + m[1][2] * v1; + dest[3] = m[0][3] * v0 + m[1][3] * v1; +} + +/*! + * @brief Transpose mat2x4 (src) and store in mat4x2 (dest). + * + * @param[in] src mat2x4 (left) + * @param[out] dest destination (result, mat4x2) + */ +CGLM_INLINE +void +glm_mat2x4_transpose(mat2x4 src, mat4x2 dest) { + dest[0][0] = src[0][0]; dest[0][1] = src[1][0]; + dest[1][0] = src[0][1]; dest[1][1] = src[1][1]; + dest[2][0] = src[0][2]; dest[2][1] = src[1][2]; + dest[3][0] = src[0][3]; dest[3][1] = src[1][3]; +} + +/*! + * @brief Multiply mat2x4 (m) by scalar constant (s). + * + * @param[in, out] m (src, dest) + * @param[in] s float (scalar) + */ +CGLM_INLINE +void +glm_mat2x4_scale(mat2x4 m, float s) { + m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; m[0][3] *= s; + m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; m[1][3] *= s; +} + +#endif diff --git a/external/cglm/mat3.h b/external/cglm/mat3.h new file mode 100644 index 0000000..10b373e --- /dev/null +++ b/external/cglm/mat3.h @@ -0,0 +1,480 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_MAT3_IDENTITY_INIT + GLM_MAT3_ZERO_INIT + GLM_MAT3_IDENTITY + GLM_MAT3_ZERO + glm_mat3_dup(mat, dest) + + Functions: + CGLM_INLINE void glm_mat3_copy(mat3 mat, mat3 dest); + CGLM_INLINE void glm_mat3_identity(mat3 mat); + CGLM_INLINE void glm_mat3_identity_array(mat3 * restrict mat, size_t count); + CGLM_INLINE void glm_mat3_zero(mat3 mat); + CGLM_INLINE void glm_mat3_mul(mat3 m1, mat3 m2, mat3 dest); + CGLM_INLINE void glm_mat3_transpose_to(mat3 m, mat3 dest); + CGLM_INLINE void glm_mat3_transpose(mat3 m); + CGLM_INLINE void glm_mat3_mulv(mat3 m, vec3 v, vec3 dest); + CGLM_INLINE float glm_mat3_trace(mat3 m); + CGLM_INLINE void glm_mat3_quat(mat3 m, versor dest); + CGLM_INLINE void glm_mat3_scale(mat3 m, float s); + CGLM_INLINE float glm_mat3_det(mat3 mat); + CGLM_INLINE void glm_mat3_inv(mat3 mat, mat3 dest); + CGLM_INLINE void glm_mat3_swap_col(mat3 mat, int col1, int col2); + CGLM_INLINE void glm_mat3_swap_row(mat3 mat, int row1, int row2); + CGLM_INLINE float glm_mat3_rmc(vec3 r, mat3 m, vec3 c); + CGLM_INLINE void glm_mat3_make(float * restrict src, mat3 dest); + CGLM_INLINE void glm_mat3_textrans(float sx, float sy, float rot, float tx, float ty, mat3 dest); + */ + +#ifndef cglm_mat3_h +#define cglm_mat3_h + +#include "common.h" +#include "vec3.h" + +#ifdef CGLM_SSE_FP +# include "simd/sse2/mat3.h" +#endif + +#ifdef CGLM_SIMD_WASM +# include "simd/wasm/mat3.h" +#endif + +#define GLM_MAT3_IDENTITY_INIT {{1.0f, 0.0f, 0.0f}, \ + {0.0f, 1.0f, 0.0f}, \ + {0.0f, 0.0f, 1.0f}} +#define GLM_MAT3_ZERO_INIT {{0.0f, 0.0f, 0.0f}, \ + {0.0f, 0.0f, 0.0f}, \ + {0.0f, 0.0f, 0.0f}} + + +/* for C only */ +#define GLM_MAT3_IDENTITY ((mat3)GLM_MAT3_IDENTITY_INIT) +#define GLM_MAT3_ZERO ((mat3)GLM_MAT3_ZERO_INIT) + +/* DEPRECATED! use _copy, _ucopy versions */ +#define glm_mat3_dup(mat, dest) glm_mat3_copy(mat, dest) + +/*! + * @brief copy all members of [mat] to [dest] + * + * @param[in] mat source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_mat3_copy(mat3 mat, mat3 dest) { + dest[0][0] = mat[0][0]; + dest[0][1] = mat[0][1]; + dest[0][2] = mat[0][2]; + + dest[1][0] = mat[1][0]; + dest[1][1] = mat[1][1]; + dest[1][2] = mat[1][2]; + + dest[2][0] = mat[2][0]; + dest[2][1] = mat[2][1]; + dest[2][2] = mat[2][2]; +} + +/*! + * @brief make given matrix identity. It is identical with below, + * but it is more easy to do that with this func especially for members + * e.g. glm_mat3_identity(aStruct->aMatrix); + * + * @code + * glm_mat3_copy(GLM_MAT3_IDENTITY, mat); // C only + * + * // or + * mat3 mat = GLM_MAT3_IDENTITY_INIT; + * @endcode + * + * @param[in, out] mat destination + */ +CGLM_INLINE +void +glm_mat3_identity(mat3 mat) { + CGLM_ALIGN_MAT mat3 t = GLM_MAT3_IDENTITY_INIT; + glm_mat3_copy(t, mat); +} + +/*! + * @brief make given matrix array's each element identity matrix + * + * @param[in, out] mat matrix array (must be aligned (16/32) + * if alignment is not disabled) + * + * @param[in] count count of matrices + */ +CGLM_INLINE +void +glm_mat3_identity_array(mat3 * __restrict mat, size_t count) { + CGLM_ALIGN_MAT mat3 t = GLM_MAT3_IDENTITY_INIT; + size_t i; + + for (i = 0; i < count; i++) { + glm_mat3_copy(t, mat[i]); + } +} + +/*! + * @brief make given matrix zero. + * + * @param[in, out] mat matrix + */ +CGLM_INLINE +void +glm_mat3_zero(mat3 mat) { + CGLM_ALIGN_MAT mat3 t = GLM_MAT3_ZERO_INIT; + glm_mat3_copy(t, mat); +} + +/*! + * @brief multiply m1 and m2 to dest + * + * m1, m2 and dest matrices can be same matrix, it is possible to write this: + * + * @code + * mat3 m = GLM_MAT3_IDENTITY_INIT; + * glm_mat3_mul(m, m, m); + * @endcode + * + * @param[in] m1 left matrix + * @param[in] m2 right matrix + * @param[out] dest destination matrix + */ +CGLM_INLINE +void +glm_mat3_mul(mat3 m1, mat3 m2, mat3 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_mat3_mul_wasm(m1, m2, dest); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glm_mat3_mul_sse2(m1, m2, dest); +#else + float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], + a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2], + a20 = m1[2][0], a21 = m1[2][1], a22 = m1[2][2], + + b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2], + b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2], + b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2]; + + dest[0][0] = a00 * b00 + a10 * b01 + a20 * b02; + dest[0][1] = a01 * b00 + a11 * b01 + a21 * b02; + dest[0][2] = a02 * b00 + a12 * b01 + a22 * b02; + dest[1][0] = a00 * b10 + a10 * b11 + a20 * b12; + dest[1][1] = a01 * b10 + a11 * b11 + a21 * b12; + dest[1][2] = a02 * b10 + a12 * b11 + a22 * b12; + dest[2][0] = a00 * b20 + a10 * b21 + a20 * b22; + dest[2][1] = a01 * b20 + a11 * b21 + a21 * b22; + dest[2][2] = a02 * b20 + a12 * b21 + a22 * b22; +#endif +} + +/*! + * @brief transpose mat3 and store in dest + * + * source matrix will not be transposed unless dest is m + * + * @param[in] m matrix + * @param[out] dest result + */ +CGLM_INLINE +void +glm_mat3_transpose_to(mat3 m, mat3 dest) { + dest[0][0] = m[0][0]; + dest[0][1] = m[1][0]; + dest[0][2] = m[2][0]; + dest[1][0] = m[0][1]; + dest[1][1] = m[1][1]; + dest[1][2] = m[2][1]; + dest[2][0] = m[0][2]; + dest[2][1] = m[1][2]; + dest[2][2] = m[2][2]; +} + +/*! + * @brief transpose mat3 and store result in same matrix + * + * @param[in, out] m source and dest + */ +CGLM_INLINE +void +glm_mat3_transpose(mat3 m) { + CGLM_ALIGN_MAT mat3 tmp; + + tmp[0][1] = m[1][0]; + tmp[0][2] = m[2][0]; + tmp[1][0] = m[0][1]; + tmp[1][2] = m[2][1]; + tmp[2][0] = m[0][2]; + tmp[2][1] = m[1][2]; + + m[0][1] = tmp[0][1]; + m[0][2] = tmp[0][2]; + m[1][0] = tmp[1][0]; + m[1][2] = tmp[1][2]; + m[2][0] = tmp[2][0]; + m[2][1] = tmp[2][1]; +} + +/*! + * @brief multiply mat3 with vec3 (column vector) and store in dest vector + * + * @param[in] m mat3 (left) + * @param[in] v vec3 (right, column vector) + * @param[out] dest vec3 (result, column vector) + */ +CGLM_INLINE +void +glm_mat3_mulv(mat3 m, vec3 v, vec3 dest) { + vec3 res; + res[0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2]; + res[1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2]; + res[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2]; + glm_vec3_copy(res, dest); +} + +/*! + * @brief trace of matrix + * + * sum of the elements on the main diagonal from upper left to the lower right + * + * @param[in] m matrix + */ +CGLM_INLINE +float +glm_mat3_trace(mat3 m) { + return m[0][0] + m[1][1] + m[2][2]; +} + +/*! + * @brief convert mat3 to quaternion + * + * @param[in] m rotation matrix + * @param[out] dest destination quaternion + */ +CGLM_INLINE +void +glm_mat3_quat(mat3 m, versor dest) { + float trace, r, rinv; + + /* it seems using like m12 instead of m[1][2] causes extra instructions */ + + trace = m[0][0] + m[1][1] + m[2][2]; + if (trace >= 0.0f) { + r = sqrtf(1.0f + trace); + rinv = 0.5f / r; + + dest[0] = rinv * (m[1][2] - m[2][1]); + dest[1] = rinv * (m[2][0] - m[0][2]); + dest[2] = rinv * (m[0][1] - m[1][0]); + dest[3] = r * 0.5f; + } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) { + r = sqrtf(1.0f - m[1][1] - m[2][2] + m[0][0]); + rinv = 0.5f / r; + + dest[0] = r * 0.5f; + dest[1] = rinv * (m[0][1] + m[1][0]); + dest[2] = rinv * (m[0][2] + m[2][0]); + dest[3] = rinv * (m[1][2] - m[2][1]); + } else if (m[1][1] >= m[2][2]) { + r = sqrtf(1.0f - m[0][0] - m[2][2] + m[1][1]); + rinv = 0.5f / r; + + dest[0] = rinv * (m[0][1] + m[1][0]); + dest[1] = r * 0.5f; + dest[2] = rinv * (m[1][2] + m[2][1]); + dest[3] = rinv * (m[2][0] - m[0][2]); + } else { + r = sqrtf(1.0f - m[0][0] - m[1][1] + m[2][2]); + rinv = 0.5f / r; + + dest[0] = rinv * (m[0][2] + m[2][0]); + dest[1] = rinv * (m[1][2] + m[2][1]); + dest[2] = r * 0.5f; + dest[3] = rinv * (m[0][1] - m[1][0]); + } +} + +/*! + * @brief scale (multiply with scalar) matrix + * + * multiply matrix with scalar + * + * @param[in, out] m matrix + * @param[in] s scalar + */ +CGLM_INLINE +void +glm_mat3_scale(mat3 m, float s) { + m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; + m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; + m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; +} + +/*! + * @brief mat3 determinant + * + * @param[in] mat matrix + * + * @return determinant + */ +CGLM_INLINE +float +glm_mat3_det(mat3 mat) { + float a = mat[0][0], b = mat[0][1], c = mat[0][2], + d = mat[1][0], e = mat[1][1], f = mat[1][2], + g = mat[2][0], h = mat[2][1], i = mat[2][2]; + + return a * (e * i - h * f) - d * (b * i - h * c) + g * (b * f - e * c); +} + +/*! + * @brief inverse mat3 and store in dest + * + * @param[in] mat matrix + * @param[out] dest inverse matrix + */ +CGLM_INLINE +void +glm_mat3_inv(mat3 mat, mat3 dest) { + float a = mat[0][0], b = mat[0][1], c = mat[0][2], + d = mat[1][0], e = mat[1][1], f = mat[1][2], + g = mat[2][0], h = mat[2][1], i = mat[2][2], + + c1 = e * i - f * h, c2 = d * i - g * f, c3 = d * h - g * e, + idt = 1.0f / (a * c1 - b * c2 + c * c3), ndt = -idt; + + dest[0][0] = idt * c1; + dest[0][1] = ndt * (b * i - h * c); + dest[0][2] = idt * (b * f - e * c); + dest[1][0] = ndt * c2; + dest[1][1] = idt * (a * i - g * c); + dest[1][2] = ndt * (a * f - d * c); + dest[2][0] = idt * c3; + dest[2][1] = ndt * (a * h - g * b); + dest[2][2] = idt * (a * e - d * b); +} + +/*! + * @brief swap two matrix columns + * + * @param[in,out] mat matrix + * @param[in] col1 col1 + * @param[in] col2 col2 + */ +CGLM_INLINE +void +glm_mat3_swap_col(mat3 mat, int col1, int col2) { + vec3 tmp; + glm_vec3_copy(mat[col1], tmp); + glm_vec3_copy(mat[col2], mat[col1]); + glm_vec3_copy(tmp, mat[col2]); +} + +/*! + * @brief swap two matrix rows + * + * @param[in,out] mat matrix + * @param[in] row1 row1 + * @param[in] row2 row2 + */ +CGLM_INLINE +void +glm_mat3_swap_row(mat3 mat, int row1, int row2) { + vec3 tmp; + tmp[0] = mat[0][row1]; + tmp[1] = mat[1][row1]; + tmp[2] = mat[2][row1]; + + mat[0][row1] = mat[0][row2]; + mat[1][row1] = mat[1][row2]; + mat[2][row1] = mat[2][row2]; + + mat[0][row2] = tmp[0]; + mat[1][row2] = tmp[1]; + mat[2][row2] = tmp[2]; +} + +/*! + * @brief helper for R (row vector) * M (matrix) * C (column vector) + * + * rmc stands for Row * Matrix * Column + * + * the result is scalar because R * M = Matrix1x3 (row vector), + * then Matrix1x3 * Vec3 (column vector) = Matrix1x1 (Scalar) + * + * @param[in] r row vector or matrix1x3 + * @param[in] m matrix3x3 + * @param[in] c column vector or matrix3x1 + * + * @return scalar value e.g. Matrix1x1 + */ +CGLM_INLINE +float +glm_mat3_rmc(vec3 r, mat3 m, vec3 c) { + vec3 tmp; + glm_mat3_mulv(m, c, tmp); + return glm_vec3_dot(r, tmp); +} + +/*! + * @brief Create mat3 matrix from pointer + * + * @param[in] src pointer to an array of floats + * @param[out] dest matrix + */ +CGLM_INLINE +void +glm_mat3_make(const float * __restrict src, mat3 dest) { + dest[0][0] = src[0]; + dest[0][1] = src[1]; + dest[0][2] = src[2]; + + dest[1][0] = src[3]; + dest[1][1] = src[4]; + dest[1][2] = src[5]; + + dest[2][0] = src[6]; + dest[2][1] = src[7]; + dest[2][2] = src[8]; +} + +/*! + * @brief Create mat3 matrix from texture transform parameters + * + * @param[in] sx scale x + * @param[in] sy scale y + * @param[in] rot rotation in radians CCW/RH + * @param[in] tx translate x + * @param[in] ty translate y + * @param[out] dest texture transform matrix + */ +CGLM_INLINE +void +glm_mat3_textrans(float sx, float sy, float rot, float tx, float ty, mat3 dest) { + float c, s; + + c = cosf(rot); + s = sinf(rot); + + glm_mat3_identity(dest); + + dest[0][0] = c * sx; + dest[0][1] = -s * sy; + dest[1][0] = s * sx; + dest[1][1] = c * sy; + dest[2][0] = tx; + dest[2][1] = ty; +} + +#endif /* cglm_mat3_h */ diff --git a/external/cglm/mat3x2.h b/external/cglm/mat3x2.h new file mode 100644 index 0000000..52173c0 --- /dev/null +++ b/external/cglm/mat3x2.h @@ -0,0 +1,148 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_MAT3X2_ZERO_INIT + GLM_MAT3X2_ZERO + + Functions: + CGLM_INLINE void glm_mat3x2_copy(mat3x2 src, mat3x2 dest); + CGLM_INLINE void glm_mat3x2_zero(mat3x2 m); + CGLM_INLINE void glm_mat3x2_make(const float * __restrict src, mat3x2 dest); + CGLM_INLINE void glm_mat3x2_mul(mat3x2 m1, mat2x3 m2, mat2 dest); + CGLM_INLINE void glm_mat3x2_mulv(mat3x2 m, vec3 v, vec2 dest); + CGLM_INLINE void glm_mat3x2_transpose(mat3x2 src, mat2x3 dest); + CGLM_INLINE void glm_mat3x2_scale(mat3x2 m, float s); + */ + +#ifndef cglm_mat3x2_h +#define cglm_mat3x2_h + +#include "common.h" + +#define GLM_MAT3X2_ZERO_INIT {{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}} + +/* for C only */ +#define GLM_MAT3X2_ZERO GLM_MAT3X2_ZERO_INIT + +/*! + * @brief Copy mat3x2 (src) to mat3x2 (dest). + * + * @param[in] src mat3x2 (left) + * @param[out] dest destination (result, mat3x2) + */ +CGLM_INLINE +void +glm_mat3x2_copy(mat3x2 src, mat3x2 dest) { + glm_vec2_copy(src[0], dest[0]); + glm_vec2_copy(src[1], dest[1]); + glm_vec2_copy(src[2], dest[2]); +} + +/*! + * @brief Zero out the mat3x2 (m). + * + * @param[in, out] mat3x2 (src, dest) + */ +CGLM_INLINE +void +glm_mat3x2_zero(mat3x2 m) { + CGLM_ALIGN_MAT mat3x2 t = GLM_MAT3X2_ZERO_INIT; + glm_mat3x2_copy(t, m); +} + +/*! + * @brief Create mat3x2 (dest) from pointer (src). + * + * @param[in] src pointer to an array of floats (left) + * @param[out] dest destination (result, mat3x2) + */ +CGLM_INLINE +void +glm_mat3x2_make(const float * __restrict src, mat3x2 dest) { + dest[0][0] = src[0]; + dest[0][1] = src[1]; + + dest[1][0] = src[2]; + dest[1][1] = src[3]; + + dest[2][0] = src[4]; + dest[2][1] = src[5]; +} + +/*! + * @brief Multiply mat3x2 (m1) by mat2x3 (m2) and store in mat2 (dest). + * + * @code + * glm_mat3x2_mul(mat3x2, mat2x3, mat2); + * @endcode + * + * @param[in] m1 mat3x2 (left) + * @param[in] m2 mat2x3 (right) + * @param[out] dest destination (result, mat2) + */ +CGLM_INLINE +void +glm_mat3x2_mul(mat3x2 m1, mat2x3 m2, mat2 dest) { + float a00 = m1[0][0], a01 = m1[0][1], + a10 = m1[1][0], a11 = m1[1][1], + a20 = m1[2][0], a21 = m1[2][1], + + b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2], + b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2]; + + dest[0][0] = a00 * b00 + a10 * b01 + a20 * b02; + dest[0][1] = a01 * b00 + a11 * b01 + a21 * b02; + + dest[1][0] = a00 * b10 + a10 * b11 + a20 * b12; + dest[1][1] = a01 * b10 + a11 * b11 + a21 * b12; +} + +/*! + * @brief Multiply mat3x2 (m) by vec3 (v) and store in vec2 (dest). + * + * @param[in] m mat3x2 (left) + * @param[in] v vec3 (right, column vector) + * @param[out] dest destination (result, column vector) + */ +CGLM_INLINE +void +glm_mat3x2_mulv(mat3x2 m, vec3 v, vec2 dest) { + float v0 = v[0], v1 = v[1], v2 = v[2]; + + dest[0] = m[0][0] * v0 + m[1][0] * v1 + m[2][0] * v2; + dest[1] = m[0][1] * v0 + m[1][1] * v1 + m[2][1] * v2; +} + +/*! + * @brief Transpose mat3x2 (src) and store in mat2x3 (dest). + * + * @param[in] src mat3x2 (left) + * @param[out] dest destination (result, mat2x3) + */ +CGLM_INLINE +void +glm_mat3x2_transpose(mat3x2 src, mat2x3 dest) { + dest[0][0] = src[0][0]; dest[0][1] = src[1][0]; dest[0][2] = src[2][0]; + dest[1][0] = src[0][1]; dest[1][1] = src[1][1]; dest[1][2] = src[2][1]; +} + +/*! + * @brief Multiply mat3x2 (m) by scalar constant (s). + * + * @param[in, out] m (src, dest) + * @param[in] s float (scalar) + */ +CGLM_INLINE +void +glm_mat3x2_scale(mat3x2 m, float s) { + m[0][0] *= s; m[0][1] *= s; m[1][0] *= s; + m[1][1] *= s; m[2][0] *= s; m[2][1] *= s; +} + +#endif diff --git a/external/cglm/mat3x4.h b/external/cglm/mat3x4.h new file mode 100644 index 0000000..52d8e7e --- /dev/null +++ b/external/cglm/mat3x4.h @@ -0,0 +1,177 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_MAT3X4_ZERO_INIT + GLM_MAT3X4_ZERO + + Functions: + CGLM_INLINE void glm_mat3x4_copy(mat3x4 src, mat3x4 dest); + CGLM_INLINE void glm_mat3x4_zero(mat3x4 m); + CGLM_INLINE void glm_mat3x4_make(const float * __restrict src, mat3x4 dest); + CGLM_INLINE void glm_mat3x4_mul(mat3x4 m1, mat4x3 m2, mat4 dest); + CGLM_INLINE void glm_mat3x4_mulv(mat3x4 m, vec3 v, vec4 dest); + CGLM_INLINE void glm_mat3x4_transpose(mat3x4 src, mat4x3 dest); + CGLM_INLINE void glm_mat3x4_scale(mat3x4 m, float s); + */ + +#ifndef cglm_mat3x4_h +#define cglm_mat3x4_h + +#include "common.h" + +#define GLM_MAT3X4_ZERO_INIT {{0.0f, 0.0f, 0.0f, 0.0f}, \ + {0.0f, 0.0f, 0.0f, 0.0f}, \ + {0.0f, 0.0f, 0.0f, 0.0f}} + +/* for C only */ +#define GLM_MAT3X4_ZERO GLM_MAT3X4_ZERO_INIT + +/*! + * @brief Copy mat3x4 (src) to mat3x4 (dest). + * + * @param[in] src mat3x4 (left) + * @param[out] dest destination (result, mat3x4) + */ +CGLM_INLINE +void +glm_mat3x4_copy(mat3x4 src, mat3x4 dest) { + glm_vec4_ucopy(src[0], dest[0]); + glm_vec4_ucopy(src[1], dest[1]); + glm_vec4_ucopy(src[2], dest[2]); +} + +/*! + * @brief Zero out the mat3x4 (m). + * + * @param[in, out] mat3x4 (src, dest) + */ +CGLM_INLINE +void +glm_mat3x4_zero(mat3x4 m) { + CGLM_ALIGN_MAT mat3x4 t = GLM_MAT3X4_ZERO_INIT; + glm_mat3x4_copy(t, m); +} + +/*! + * @brief Create mat3x4 (dest) from pointer (src). + * + * @param[in] src pointer to an array of floats (left) + * @param[out] dest destination (result, mat3x4) + */ +CGLM_INLINE +void +glm_mat3x4_make(const float * __restrict src, mat3x4 dest) { + dest[0][0] = src[0]; + dest[0][1] = src[1]; + dest[0][2] = src[2]; + dest[0][3] = src[3]; + + dest[1][0] = src[4]; + dest[1][1] = src[5]; + dest[1][2] = src[6]; + dest[1][3] = src[7]; + + dest[2][0] = src[8]; + dest[2][1] = src[9]; + dest[2][2] = src[10]; + dest[2][3] = src[11]; +} + +/*! + * @brief Multiply mat3x4 (m1) by mat4x3 (m2) and store in mat4 (dest). + * + * @code + * glm_mat3x4_mul(mat3x4, mat4x3, mat4); + * @endcode + * + * @param[in] m1 mat3x4 (left) + * @param[in] m2 mat4x3 (right) + * @param[out] dest destination (result, mat4) + */ +CGLM_INLINE +void +glm_mat3x4_mul(mat3x4 m1, mat4x3 m2, mat4 dest) { + float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], a03 = m1[0][3], + a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2], a13 = m1[1][3], + a20 = m1[2][0], a21 = m1[2][1], a22 = m1[2][2], a23 = m1[2][3], + + b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2], + b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2], + b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2], + b30 = m2[3][0], b31 = m2[3][1], b32 = m2[3][2]; + + dest[0][0] = a00 * b00 + a10 * b01 + a20 * b02; + dest[0][1] = a01 * b00 + a11 * b01 + a21 * b02; + dest[0][2] = a02 * b00 + a12 * b01 + a22 * b02; + dest[0][3] = a03 * b00 + a13 * b01 + a23 * b02; + + dest[1][0] = a00 * b10 + a10 * b11 + a20 * b12; + dest[1][1] = a01 * b10 + a11 * b11 + a21 * b12; + dest[1][2] = a02 * b10 + a12 * b11 + a22 * b12; + dest[1][3] = a03 * b10 + a13 * b11 + a23 * b12; + + dest[2][0] = a00 * b20 + a10 * b21 + a20 * b22; + dest[2][1] = a01 * b20 + a11 * b21 + a21 * b22; + dest[2][2] = a02 * b20 + a12 * b21 + a22 * b22; + dest[2][3] = a03 * b20 + a13 * b21 + a23 * b22; + + dest[3][0] = a00 * b30 + a10 * b31 + a20 * b32; + dest[3][1] = a01 * b30 + a11 * b31 + a21 * b32; + dest[3][2] = a02 * b30 + a12 * b31 + a22 * b32; + dest[3][3] = a03 * b30 + a13 * b31 + a23 * b32; +} + +/*! + * @brief Multiply mat3x4 (m) by vec3 (v) and store in vec4 (dest). + * + * @param[in] m mat3x4 (left) + * @param[in] v vec3 (right, column vector) + * @param[out] dest destination (result, column vector) + */ +CGLM_INLINE +void +glm_mat3x4_mulv(mat3x4 m, vec3 v, vec4 dest) { + float v0 = v[0], v1 = v[1], v2 = v[2]; + + dest[0] = m[0][0] * v0 + m[1][0] * v1 + m[2][0] * v2; + dest[1] = m[0][1] * v0 + m[1][1] * v1 + m[2][1] * v2; + dest[2] = m[0][2] * v0 + m[1][2] * v1 + m[2][2] * v2; + dest[3] = m[0][3] * v0 + m[1][3] * v1 + m[2][3] * v2; +} + +/*! + * @brief Transpose mat3x4 (src) and store in mat4x3 (dest). + * + * @param[in] src mat3x4 (left) + * @param[out] dest destination (result, mat4x3) + */ +CGLM_INLINE +void +glm_mat3x4_transpose(mat3x4 src, mat4x3 dest) { + dest[0][0] = src[0][0]; dest[0][1] = src[1][0]; dest[0][2] = src[2][0]; + dest[1][0] = src[0][1]; dest[1][1] = src[1][1]; dest[1][2] = src[2][1]; + dest[2][0] = src[0][2]; dest[2][1] = src[1][2]; dest[2][2] = src[2][2]; + dest[3][0] = src[0][3]; dest[3][1] = src[1][3]; dest[3][2] = src[2][3]; +} + +/*! + * @brief Multiply mat3x4 (m) by scalar constant (s). + * + * @param[in, out] m (src, dest) + * @param[in] s float (scalar) + */ +CGLM_INLINE +void +glm_mat3x4_scale(mat3x4 m, float s) { + m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; m[0][3] *= s; + m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; m[1][3] *= s; + m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; m[2][3] *= s; +} + +#endif diff --git a/external/cglm/mat4.h b/external/cglm/mat4.h new file mode 100644 index 0000000..c3fe7fd --- /dev/null +++ b/external/cglm/mat4.h @@ -0,0 +1,831 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/*! + * Most of functions in this header are optimized manually with SIMD + * if available. You dont need to call/incude SIMD headers manually + */ + +/* + Macros: + GLM_MAT4_IDENTITY_INIT + GLM_MAT4_ZERO_INIT + GLM_MAT4_IDENTITY + GLM_MAT4_ZERO + + Functions: + CGLM_INLINE void glm_mat4_ucopy(mat4 mat, mat4 dest); + CGLM_INLINE void glm_mat4_copy(mat4 mat, mat4 dest); + CGLM_INLINE void glm_mat4_identity(mat4 mat); + CGLM_INLINE void glm_mat4_identity_array(mat4 * restrict mat, size_t count); + CGLM_INLINE void glm_mat4_zero(mat4 mat); + CGLM_INLINE void glm_mat4_pick3(mat4 mat, mat3 dest); + CGLM_INLINE void glm_mat4_pick3t(mat4 mat, mat3 dest); + CGLM_INLINE void glm_mat4_ins3(mat3 mat, mat4 dest); + CGLM_INLINE void glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest); + CGLM_INLINE void glm_mat4_mulN(mat4 *matrices[], int len, mat4 dest); + CGLM_INLINE void glm_mat4_mulv(mat4 m, vec4 v, vec4 dest); + CGLM_INLINE void glm_mat4_mulv3(mat4 m, vec3 v, float last, vec3 dest); + CGLM_INLINE float glm_mat4_trace(mat4 m); + CGLM_INLINE float glm_mat4_trace3(mat4 m); + CGLM_INLINE void glm_mat4_quat(mat4 m, versor dest) ; + CGLM_INLINE void glm_mat4_transpose_to(mat4 m, mat4 dest); + CGLM_INLINE void glm_mat4_transpose(mat4 m); + CGLM_INLINE void glm_mat4_scale_p(mat4 m, float s); + CGLM_INLINE void glm_mat4_scale(mat4 m, float s); + CGLM_INLINE float glm_mat4_det(mat4 mat); + CGLM_INLINE void glm_mat4_inv(mat4 mat, mat4 dest); + CGLM_INLINE void glm_mat4_inv_fast(mat4 mat, mat4 dest); + CGLM_INLINE void glm_mat4_swap_col(mat4 mat, int col1, int col2); + CGLM_INLINE void glm_mat4_swap_row(mat4 mat, int row1, int row2); + CGLM_INLINE float glm_mat4_rmc(vec4 r, mat4 m, vec4 c); + CGLM_INLINE void glm_mat4_make(float * restrict src, mat4 dest); + CGLM_INLINE void glm_mat4_textrans(float sx, float sy, float rot, float tx, float ty, mat4 dest); + */ + +#ifndef cglm_mat_h +#define cglm_mat_h + +#include "common.h" +#include "vec4.h" +#include "vec3.h" + +#ifdef CGLM_SSE_FP +# include "simd/sse2/mat4.h" +#endif + +#ifdef CGLM_AVX_FP +# include "simd/avx/mat4.h" +#endif + +#ifdef CGLM_NEON_FP +# include "simd/neon/mat4.h" +#endif + +#ifdef CGLM_SIMD_WASM +# include "simd/wasm/mat4.h" +#endif + +#ifndef NDEBUG +# include +#endif + +#define GLM_MAT4_IDENTITY_INIT {{1.0f, 0.0f, 0.0f, 0.0f}, \ + {0.0f, 1.0f, 0.0f, 0.0f}, \ + {0.0f, 0.0f, 1.0f, 0.0f}, \ + {0.0f, 0.0f, 0.0f, 1.0f}} + +#define GLM_MAT4_ZERO_INIT {{0.0f, 0.0f, 0.0f, 0.0f}, \ + {0.0f, 0.0f, 0.0f, 0.0f}, \ + {0.0f, 0.0f, 0.0f, 0.0f}, \ + {0.0f, 0.0f, 0.0f, 0.0f}} + +/* for C only */ +#define GLM_MAT4_IDENTITY ((mat4)GLM_MAT4_IDENTITY_INIT) +#define GLM_MAT4_ZERO ((mat4)GLM_MAT4_ZERO_INIT) + +/* DEPRECATED! use _copy, _ucopy versions */ +#define glm_mat4_udup(mat, dest) glm_mat4_ucopy(mat, dest) +#define glm_mat4_dup(mat, dest) glm_mat4_copy(mat, dest) + +/* DEPRECATED! default is precise now. */ +#define glm_mat4_inv_precise(mat, dest) glm_mat4_inv(mat, dest) + +/*! + * @brief copy all members of [mat] to [dest] + * + * matrix may not be aligned, u stands for unaligned, this may be useful when + * copying a matrix from external source e.g. asset importer... + * + * @param[in] mat source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_mat4_ucopy(mat4 mat, mat4 dest) { + dest[0][0] = mat[0][0]; dest[1][0] = mat[1][0]; + dest[0][1] = mat[0][1]; dest[1][1] = mat[1][1]; + dest[0][2] = mat[0][2]; dest[1][2] = mat[1][2]; + dest[0][3] = mat[0][3]; dest[1][3] = mat[1][3]; + + dest[2][0] = mat[2][0]; dest[3][0] = mat[3][0]; + dest[2][1] = mat[2][1]; dest[3][1] = mat[3][1]; + dest[2][2] = mat[2][2]; dest[3][2] = mat[3][2]; + dest[2][3] = mat[2][3]; dest[3][3] = mat[3][3]; +} + +/*! + * @brief copy all members of [mat] to [dest] + * + * @param[in] mat source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_mat4_copy(mat4 mat, mat4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest[0], glmm_load(mat[0])); + glmm_store(dest[1], glmm_load(mat[1])); + glmm_store(dest[2], glmm_load(mat[2])); + glmm_store(dest[3], glmm_load(mat[3])); +#elif defined(__AVX__) + glmm_store256(dest[0], glmm_load256(mat[0])); + glmm_store256(dest[2], glmm_load256(mat[2])); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest[0], glmm_load(mat[0])); + glmm_store(dest[1], glmm_load(mat[1])); + glmm_store(dest[2], glmm_load(mat[2])); + glmm_store(dest[3], glmm_load(mat[3])); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest[0], vld1q_f32(mat[0])); + vst1q_f32(dest[1], vld1q_f32(mat[1])); + vst1q_f32(dest[2], vld1q_f32(mat[2])); + vst1q_f32(dest[3], vld1q_f32(mat[3])); +#else + glm_mat4_ucopy(mat, dest); +#endif +} + +/*! + * @brief make given matrix identity. It is identical with below, + * but it is more easy to do that with this func especially for members + * e.g. glm_mat4_identity(aStruct->aMatrix); + * + * @code + * glm_mat4_copy(GLM_MAT4_IDENTITY, mat); // C only + * + * // or + * mat4 mat = GLM_MAT4_IDENTITY_INIT; + * @endcode + * + * @param[in, out] mat destination + */ +CGLM_INLINE +void +glm_mat4_identity(mat4 mat) { + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; + glm_mat4_copy(t, mat); +} + +/*! + * @brief make given matrix array's each element identity matrix + * + * @param[in, out] mat matrix array (must be aligned (16/32) + * if alignment is not disabled) + * + * @param[in] count count of matrices + */ +CGLM_INLINE +void +glm_mat4_identity_array(mat4 * __restrict mat, size_t count) { + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_IDENTITY_INIT; + size_t i; + + for (i = 0; i < count; i++) { + glm_mat4_copy(t, mat[i]); + } +} + +/*! + * @brief make given matrix zero. + * + * @param[in, out] mat matrix + */ +CGLM_INLINE +void +glm_mat4_zero(mat4 mat) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_128 x0; + x0 = wasm_f32x4_const_splat(0.f); + glmm_store(mat[0], x0); + glmm_store(mat[1], x0); + glmm_store(mat[2], x0); + glmm_store(mat[3], x0); +#elif defined(__AVX__) + __m256 y0; + y0 = _mm256_setzero_ps(); + glmm_store256(mat[0], y0); + glmm_store256(mat[2], y0); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_128 x0; + x0 = _mm_setzero_ps(); + glmm_store(mat[0], x0); + glmm_store(mat[1], x0); + glmm_store(mat[2], x0); + glmm_store(mat[3], x0); +#elif defined(CGLM_NEON_FP) + glmm_128 x0; + x0 = vdupq_n_f32(0.0f); + vst1q_f32(mat[0], x0); + vst1q_f32(mat[1], x0); + vst1q_f32(mat[2], x0); + vst1q_f32(mat[3], x0); +#else + CGLM_ALIGN_MAT mat4 t = GLM_MAT4_ZERO_INIT; + glm_mat4_copy(t, mat); +#endif +} + +/*! + * @brief copy upper-left of mat4 to mat3 + * + * @param[in] mat source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_mat4_pick3(mat4 mat, mat3 dest) { + dest[0][0] = mat[0][0]; + dest[0][1] = mat[0][1]; + dest[0][2] = mat[0][2]; + + dest[1][0] = mat[1][0]; + dest[1][1] = mat[1][1]; + dest[1][2] = mat[1][2]; + + dest[2][0] = mat[2][0]; + dest[2][1] = mat[2][1]; + dest[2][2] = mat[2][2]; +} + +/*! + * @brief copy upper-left of mat4 to mat3 (transposed) + * + * the postfix t stands for transpose + * + * @param[in] mat source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_mat4_pick3t(mat4 mat, mat3 dest) { + dest[0][0] = mat[0][0]; + dest[0][1] = mat[1][0]; + dest[0][2] = mat[2][0]; + + dest[1][0] = mat[0][1]; + dest[1][1] = mat[1][1]; + dest[1][2] = mat[2][1]; + + dest[2][0] = mat[0][2]; + dest[2][1] = mat[1][2]; + dest[2][2] = mat[2][2]; +} + +/*! + * @brief copy mat3 to mat4's upper-left + * + * @param[in] mat source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_mat4_ins3(mat3 mat, mat4 dest) { + dest[0][0] = mat[0][0]; + dest[0][1] = mat[0][1]; + dest[0][2] = mat[0][2]; + + dest[1][0] = mat[1][0]; + dest[1][1] = mat[1][1]; + dest[1][2] = mat[1][2]; + + dest[2][0] = mat[2][0]; + dest[2][1] = mat[2][1]; + dest[2][2] = mat[2][2]; +} + +/*! + * @brief multiply m1 and m2 to dest + * + * m1, m2 and dest matrices can be same matrix, it is possible to write this: + * + * @code + * mat4 m = GLM_MAT4_IDENTITY_INIT; + * glm_mat4_mul(m, m, m); + * @endcode + * + * @param[in] m1 left matrix + * @param[in] m2 right matrix + * @param[out] dest destination matrix + */ +CGLM_INLINE +void +glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_mat4_mul_wasm(m1, m2, dest); +#elif defined(__AVX__) + glm_mat4_mul_avx(m1, m2, dest); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glm_mat4_mul_sse2(m1, m2, dest); +#elif defined(CGLM_NEON_FP) + glm_mat4_mul_neon(m1, m2, dest); +#else + float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], a03 = m1[0][3], + a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2], a13 = m1[1][3], + a20 = m1[2][0], a21 = m1[2][1], a22 = m1[2][2], a23 = m1[2][3], + a30 = m1[3][0], a31 = m1[3][1], a32 = m1[3][2], a33 = m1[3][3], + + b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2], b03 = m2[0][3], + b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2], b13 = m2[1][3], + b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2], b23 = m2[2][3], + b30 = m2[3][0], b31 = m2[3][1], b32 = m2[3][2], b33 = m2[3][3]; + + dest[0][0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03; + dest[0][1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03; + dest[0][2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03; + dest[0][3] = a03 * b00 + a13 * b01 + a23 * b02 + a33 * b03; + dest[1][0] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13; + dest[1][1] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13; + dest[1][2] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13; + dest[1][3] = a03 * b10 + a13 * b11 + a23 * b12 + a33 * b13; + dest[2][0] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23; + dest[2][1] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23; + dest[2][2] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23; + dest[2][3] = a03 * b20 + a13 * b21 + a23 * b22 + a33 * b23; + dest[3][0] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33; + dest[3][1] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33; + dest[3][2] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33; + dest[3][3] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33; +#endif +} + +/*! + * @brief mupliply N mat4 matrices and store result in dest + * + * this function lets you multiply multiple (more than two or more...) matrices + *

multiplication will be done in loop, this may reduce instructions + * size but if len is too small then compiler may unroll whole loop, + * usage: + * @code + * mat4 m1, m2, m3, m4, res; + * + * glm_mat4_mulN((mat4 *[]){&m1, &m2, &m3, &m4}, 4, res); + * @endcode + * + * @warning matrices parameter is pointer array not mat4 array! + * + * @param[in] matrices mat4 * array + * @param[in] len matrices count + * @param[out] dest result + */ +CGLM_INLINE +void +glm_mat4_mulN(mat4 * __restrict matrices[], uint32_t len, mat4 dest) { + uint32_t i; + +#ifndef NDEBUG + assert(len > 1 && "there must be least 2 matrices to go!"); +#endif + + glm_mat4_mul(*matrices[0], *matrices[1], dest); + + for (i = 2; i < len; i++) + glm_mat4_mul(dest, *matrices[i], dest); +} + +/*! + * @brief multiply mat4 with vec4 (column vector) and store in dest vector + * + * @param[in] m mat4 (left) + * @param[in] v vec4 (right, column vector) + * @param[out] dest vec4 (result, column vector) + */ +CGLM_INLINE +void +glm_mat4_mulv(mat4 m, vec4 v, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_mat4_mulv_wasm(m, v, dest); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glm_mat4_mulv_sse2(m, v, dest); +#elif defined(CGLM_NEON_FP) + glm_mat4_mulv_neon(m, v, dest); +#else + vec4 res; + res[0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3]; + res[1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3]; + res[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3]; + res[3] = m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3]; + glm_vec4_copy(res, dest); +#endif +} + +/*! + * @brief trace of matrix + * + * sum of the elements on the main diagonal from upper left to the lower right + * + * @param[in] m matrix + */ +CGLM_INLINE +float +glm_mat4_trace(mat4 m) { + return m[0][0] + m[1][1] + m[2][2] + m[3][3]; +} + +/*! + * @brief trace of matrix (rotation part) + * + * sum of the elements on the main diagonal from upper left to the lower right + * + * @param[in] m matrix + */ +CGLM_INLINE +float +glm_mat4_trace3(mat4 m) { + return m[0][0] + m[1][1] + m[2][2]; +} + +/*! + * @brief convert mat4's rotation part to quaternion + * + * @param[in] m affine matrix + * @param[out] dest destination quaternion + */ +CGLM_INLINE +void +glm_mat4_quat(mat4 m, versor dest) { + float trace, r, rinv; + + /* it seems using like m12 instead of m[1][2] causes extra instructions */ + + trace = m[0][0] + m[1][1] + m[2][2]; + if (trace >= 0.0f) { + r = sqrtf(1.0f + trace); + rinv = 0.5f / r; + + dest[0] = rinv * (m[1][2] - m[2][1]); + dest[1] = rinv * (m[2][0] - m[0][2]); + dest[2] = rinv * (m[0][1] - m[1][0]); + dest[3] = r * 0.5f; + } else if (m[0][0] >= m[1][1] && m[0][0] >= m[2][2]) { + r = sqrtf(1.0f - m[1][1] - m[2][2] + m[0][0]); + rinv = 0.5f / r; + + dest[0] = r * 0.5f; + dest[1] = rinv * (m[0][1] + m[1][0]); + dest[2] = rinv * (m[0][2] + m[2][0]); + dest[3] = rinv * (m[1][2] - m[2][1]); + } else if (m[1][1] >= m[2][2]) { + r = sqrtf(1.0f - m[0][0] - m[2][2] + m[1][1]); + rinv = 0.5f / r; + + dest[0] = rinv * (m[0][1] + m[1][0]); + dest[1] = r * 0.5f; + dest[2] = rinv * (m[1][2] + m[2][1]); + dest[3] = rinv * (m[2][0] - m[0][2]); + } else { + r = sqrtf(1.0f - m[0][0] - m[1][1] + m[2][2]); + rinv = 0.5f / r; + + dest[0] = rinv * (m[0][2] + m[2][0]); + dest[1] = rinv * (m[1][2] + m[2][1]); + dest[2] = r * 0.5f; + dest[3] = rinv * (m[0][1] - m[1][0]); + } +} + +/*! + * @brief multiply vector with mat4 + * + * actually the result is vec4, after multiplication the last component + * is trimmed. if you need it don't use this func. + * + * @param[in] m mat4(affine transform) + * @param[in] v vec3 + * @param[in] last 4th item to make it vec4 + * @param[out] dest result vector (vec3) + */ +CGLM_INLINE +void +glm_mat4_mulv3(mat4 m, vec3 v, float last, vec3 dest) { + vec4 res; + glm_vec4(v, last, res); + glm_mat4_mulv(m, res, res); + glm_vec3(res, dest); +} + +/*! + * @brief transpose mat4 and store in dest + * + * source matrix will not be transposed unless dest is m + * + * @param[in] m matrix + * @param[out] dest result + */ +CGLM_INLINE +void +glm_mat4_transpose_to(mat4 m, mat4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_mat4_transp_wasm(m, dest); +#elif defined(__AVX__) + glm_mat4_transp_avx(m, dest); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glm_mat4_transp_sse2(m, dest); +#elif defined(CGLM_NEON_FP) + glm_mat4_transp_neon(m, dest); +#else + dest[0][0] = m[0][0]; dest[1][0] = m[0][1]; + dest[0][1] = m[1][0]; dest[1][1] = m[1][1]; + dest[0][2] = m[2][0]; dest[1][2] = m[2][1]; + dest[0][3] = m[3][0]; dest[1][3] = m[3][1]; + dest[2][0] = m[0][2]; dest[3][0] = m[0][3]; + dest[2][1] = m[1][2]; dest[3][1] = m[1][3]; + dest[2][2] = m[2][2]; dest[3][2] = m[2][3]; + dest[2][3] = m[3][2]; dest[3][3] = m[3][3]; +#endif +} + +/*! + * @brief transpose mat4 and store result in same matrix + * + * @param[in, out] m source and dest + */ +CGLM_INLINE +void +glm_mat4_transpose(mat4 m) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_mat4_transp_wasm(m, m); +#elif defined(__AVX__) + glm_mat4_transp_avx(m, m); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glm_mat4_transp_sse2(m, m); +#elif defined(CGLM_NEON_FP) + glm_mat4_transp_neon(m, m); +#else + mat4 d; + glm_mat4_transpose_to(m, d); + glm_mat4_ucopy(d, m); +#endif +} + +/*! + * @brief scale (multiply with scalar) matrix without simd optimization + * + * multiply matrix with scalar + * + * @param[in, out] m matrix + * @param[in] s scalar + */ +CGLM_INLINE +void +glm_mat4_scale_p(mat4 m, float s) { + m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; m[0][3] *= s; + m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; m[1][3] *= s; + m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; m[2][3] *= s; + m[3][0] *= s; m[3][1] *= s; m[3][2] *= s; m[3][3] *= s; +} + +/*! + * @brief scale (multiply with scalar) matrix + * + * multiply matrix with scalar + * + * @param[in, out] m matrix + * @param[in] s scalar + */ +CGLM_INLINE +void +glm_mat4_scale(mat4 m, float s) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_mat4_scale_wasm(m, s); +#elif defined(__AVX__) + glm_mat4_scale_avx(m, s); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glm_mat4_scale_sse2(m, s); +#elif defined(CGLM_NEON_FP) + glm_mat4_scale_neon(m, s); +#else + glm_mat4_scale_p(m, s); +#endif +} + +/*! + * @brief mat4 determinant + * + * @param[in] mat matrix + * + * @return determinant + */ +CGLM_INLINE +float +glm_mat4_det(mat4 mat) { +#if defined(__wasm__) && defined(__wasm_simd128__) + return glm_mat4_det_wasm(mat); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + return glm_mat4_det_sse2(mat); +#elif defined(CGLM_NEON_FP) + return glm_mat4_det_neon(mat); +#else + /* [square] det(A) = det(At) */ + float t[6]; + float a = mat[0][0], b = mat[0][1], c = mat[0][2], d = mat[0][3], + e = mat[1][0], f = mat[1][1], g = mat[1][2], h = mat[1][3], + i = mat[2][0], j = mat[2][1], k = mat[2][2], l = mat[2][3], + m = mat[3][0], n = mat[3][1], o = mat[3][2], p = mat[3][3]; + + t[0] = k * p - o * l; + t[1] = j * p - n * l; + t[2] = j * o - n * k; + t[3] = i * p - m * l; + t[4] = i * o - m * k; + t[5] = i * n - m * j; + + return a * (f * t[0] - g * t[1] + h * t[2]) + - b * (e * t[0] - g * t[3] + h * t[4]) + + c * (e * t[1] - f * t[3] + h * t[5]) + - d * (e * t[2] - f * t[4] + g * t[5]); +#endif +} + +/*! + * @brief inverse mat4 and store in dest + * + * @param[in] mat matrix + * @param[out] dest inverse matrix + */ +CGLM_INLINE +void +glm_mat4_inv(mat4 mat, mat4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_mat4_inv_wasm(mat, dest); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glm_mat4_inv_sse2(mat, dest); +#elif defined(CGLM_NEON_FP) + glm_mat4_inv_neon(mat, dest); +#else + float a = mat[0][0], b = mat[0][1], c = mat[0][2], d = mat[0][3], + e = mat[1][0], f = mat[1][1], g = mat[1][2], h = mat[1][3], + i = mat[2][0], j = mat[2][1], k = mat[2][2], l = mat[2][3], + m = mat[3][0], n = mat[3][1], o = mat[3][2], p = mat[3][3], + + c1 = k * p - l * o, c2 = c * h - d * g, c3 = i * p - l * m, + c4 = a * h - d * e, c5 = j * p - l * n, c6 = b * h - d * f, + c7 = i * n - j * m, c8 = a * f - b * e, c9 = j * o - k * n, + c10 = b * g - c * f, c11 = i * o - k * m, c12 = a * g - c * e, + + idt = 1.0f/(c8*c1+c4*c9+c10*c3+c2*c7-c12*c5-c6*c11), ndt = -idt; + + dest[0][0] = (f * c1 - g * c5 + h * c9) * idt; + dest[0][1] = (b * c1 - c * c5 + d * c9) * ndt; + dest[0][2] = (n * c2 - o * c6 + p * c10) * idt; + dest[0][3] = (j * c2 - k * c6 + l * c10) * ndt; + + dest[1][0] = (e * c1 - g * c3 + h * c11) * ndt; + dest[1][1] = (a * c1 - c * c3 + d * c11) * idt; + dest[1][2] = (m * c2 - o * c4 + p * c12) * ndt; + dest[1][3] = (i * c2 - k * c4 + l * c12) * idt; + + dest[2][0] = (e * c5 - f * c3 + h * c7) * idt; + dest[2][1] = (a * c5 - b * c3 + d * c7) * ndt; + dest[2][2] = (m * c6 - n * c4 + p * c8) * idt; + dest[2][3] = (i * c6 - j * c4 + l * c8) * ndt; + + dest[3][0] = (e * c9 - f * c11 + g * c7) * ndt; + dest[3][1] = (a * c9 - b * c11 + c * c7) * idt; + dest[3][2] = (m * c10 - n * c12 + o * c8) * ndt; + dest[3][3] = (i * c10 - j * c12 + k * c8) * idt; +#endif +} + +/*! + * @brief inverse mat4 and store in dest + * + * this func uses reciprocal approximation without extra corrections + * e.g Newton-Raphson. this should work faster than normal, + * to get more precise use glm_mat4_inv version. + * + * NOTE: You will lose precision, glm_mat4_inv is more accurate + * + * @param[in] mat matrix + * @param[out] dest inverse matrix + */ +CGLM_INLINE +void +glm_mat4_inv_fast(mat4 mat, mat4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_mat4_inv_fast_wasm(mat, dest); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glm_mat4_inv_fast_sse2(mat, dest); +#else + glm_mat4_inv(mat, dest); +#endif +} + +/*! + * @brief swap two matrix columns + * + * @param[in,out] mat matrix + * @param[in] col1 col1 + * @param[in] col2 col2 + */ +CGLM_INLINE +void +glm_mat4_swap_col(mat4 mat, int col1, int col2) { + CGLM_ALIGN(16) vec4 tmp; + glm_vec4_copy(mat[col1], tmp); + glm_vec4_copy(mat[col2], mat[col1]); + glm_vec4_copy(tmp, mat[col2]); +} + +/*! + * @brief swap two matrix rows + * + * @param[in,out] mat matrix + * @param[in] row1 row1 + * @param[in] row2 row2 + */ +CGLM_INLINE +void +glm_mat4_swap_row(mat4 mat, int row1, int row2) { + CGLM_ALIGN(16) vec4 tmp; + tmp[0] = mat[0][row1]; + tmp[1] = mat[1][row1]; + tmp[2] = mat[2][row1]; + tmp[3] = mat[3][row1]; + + mat[0][row1] = mat[0][row2]; + mat[1][row1] = mat[1][row2]; + mat[2][row1] = mat[2][row2]; + mat[3][row1] = mat[3][row2]; + + mat[0][row2] = tmp[0]; + mat[1][row2] = tmp[1]; + mat[2][row2] = tmp[2]; + mat[3][row2] = tmp[3]; +} + +/*! + * @brief helper for R (row vector) * M (matrix) * C (column vector) + * + * rmc stands for Row * Matrix * Column + * + * the result is scalar because R * M = Matrix1x4 (row vector), + * then Matrix1x4 * Vec4 (column vector) = Matrix1x1 (Scalar) + * + * @param[in] r row vector or matrix1x4 + * @param[in] m matrix4x4 + * @param[in] c column vector or matrix4x1 + * + * @return scalar value e.g. B(s) + */ +CGLM_INLINE +float +glm_mat4_rmc(vec4 r, mat4 m, vec4 c) { + vec4 tmp; + glm_mat4_mulv(m, c, tmp); + return glm_vec4_dot(r, tmp); +} + +/*! + * @brief Create mat4 matrix from pointer + * + * @param[in] src pointer to an array of floats + * @param[out] dest matrix + */ +CGLM_INLINE +void +glm_mat4_make(const float * __restrict src, mat4 dest) { + dest[0][0] = src[0]; dest[1][0] = src[4]; + dest[0][1] = src[1]; dest[1][1] = src[5]; + dest[0][2] = src[2]; dest[1][2] = src[6]; + dest[0][3] = src[3]; dest[1][3] = src[7]; + + dest[2][0] = src[8]; dest[3][0] = src[12]; + dest[2][1] = src[9]; dest[3][1] = src[13]; + dest[2][2] = src[10]; dest[3][2] = src[14]; + dest[2][3] = src[11]; dest[3][3] = src[15]; +} + +/*! + * @brief Create mat4 matrix from texture transform parameters + * + * @param[in] sx scale x + * @param[in] sy scale y + * @param[in] rot rotation in radians CCW/RH + * @param[in] tx translate x + * @param[in] ty translate y + * @param[out] dest texture transform matrix + */ +CGLM_INLINE +void +glm_mat4_textrans(float sx, float sy, float rot, float tx, float ty, mat4 dest) { + float c, s; + + c = cosf(rot); + s = sinf(rot); + + glm_mat4_identity(dest); + + dest[0][0] = c * sx; + dest[0][1] = -s * sy; + dest[1][0] = s * sx; + dest[1][1] = c * sy; + dest[3][0] = tx; + dest[3][1] = ty; +} + +#endif /* cglm_mat_h */ diff --git a/external/cglm/mat4x2.h b/external/cglm/mat4x2.h new file mode 100644 index 0000000..91684e4 --- /dev/null +++ b/external/cglm/mat4x2.h @@ -0,0 +1,153 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_MAT4X2_ZERO_INIT + GLM_MAT4X2_ZERO + + Functions: + CGLM_INLINE void glm_mat4x2_copy(mat4x2 src, mat4x2 dest); + CGLM_INLINE void glm_mat4x2_zero(mat4x2 m); + CGLM_INLINE void glm_mat4x2_make(const float * __restrict src, mat4x2 dest); + CGLM_INLINE void glm_mat4x2_mul(mat4x2 m1, mat2x4 m2, mat2 dest); + CGLM_INLINE void glm_mat4x2_mulv(mat4x2 m, vec4 v, vec2 dest); + CGLM_INLINE void glm_mat4x2_transpose(mat4x2 src, mat2x4 dest); + CGLM_INLINE void glm_mat4x2_scale(mat4x2 m, float s); + */ + +#ifndef cglm_mat4x2_h +#define cglm_mat4x2_h + +#include "common.h" + +#define GLM_MAT4X2_ZERO_INIT {{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}} + +/* for C only */ +#define GLM_MAT4X2_ZERO GLM_MAT4X2_ZERO_INIT + +/*! + * @brief Copy mat4x2 (src) to mat4x2 (dest). + * + * @param[in] src mat4x2 (left) + * @param[out] dest destination (result, mat4x2) + */ +CGLM_INLINE +void +glm_mat4x2_copy(mat4x2 src, mat4x2 dest) { + glm_vec2_copy(src[0], dest[0]); + glm_vec2_copy(src[1], dest[1]); + glm_vec2_copy(src[2], dest[2]); + glm_vec2_copy(src[3], dest[3]); +} + +/*! + * @brief Zero out the mat4x2 (m). + * + * @param[in, out] mat4x2 (src, dest) + */ +CGLM_INLINE +void +glm_mat4x2_zero(mat4x2 m) { + CGLM_ALIGN_MAT mat4x2 t = GLM_MAT4X2_ZERO_INIT; + glm_mat4x2_copy(t, m); +} + +/*! + * @brief Create mat4x2 (dest) from pointer (src). + * + * @param[in] src pointer to an array of floats (left) + * @param[out] dest destination (result, mat4x2) + */ +CGLM_INLINE +void +glm_mat4x2_make(const float * __restrict src, mat4x2 dest) { + dest[0][0] = src[0]; + dest[0][1] = src[1]; + + dest[1][0] = src[2]; + dest[1][1] = src[3]; + + dest[2][0] = src[4]; + dest[2][1] = src[5]; + + dest[3][0] = src[6]; + dest[3][1] = src[7]; +} + +/*! + * @brief Multiply mat4x2 (m1) by mat2x4 (m2) and store in mat2 (dest). + * + * @code + * glm_mat4x2_mul(mat4x2, mat2x4, mat2); + * @endcode + * + * @param[in] m1 mat4x2 (left) + * @param[in] m2 mat2x4 (right) + * @param[out] dest destination (result, mat2) + */ +CGLM_INLINE +void +glm_mat4x2_mul(mat4x2 m1, mat2x4 m2, mat2 dest) { + float a00 = m1[0][0], a01 = m1[0][1], + a10 = m1[1][0], a11 = m1[1][1], + a20 = m1[2][0], a21 = m1[2][1], + a30 = m1[3][0], a31 = m1[3][1], + + b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2], b03 = m2[0][3], + b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2], b13 = m2[1][3]; + + dest[0][0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03; + dest[0][1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03; + + dest[1][0] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13; + dest[1][1] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13; +} + +/*! + * @brief Multiply mat4x2 (m) by vec4 (v) and store in vec2 (dest). + * + * @param[in] m mat4x2 (left) + * @param[in] v vec4 (right, column vector) + * @param[out] dest destination (result, column vector) + */ +CGLM_INLINE +void +glm_mat4x2_mulv(mat4x2 m, vec4 v, vec2 dest) { + float v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; + + dest[0] = m[0][0] * v0 + m[1][0] * v1 + m[2][0] * v2 + m[3][0] * v3; + dest[1] = m[0][1] * v0 + m[1][1] * v1 + m[2][1] * v2 + m[3][1] * v3; +} + +/*! + * @brief Transpose mat4x2 (src) and store in mat2x4 (dest). + * + * @param[in] src mat4x2 (left) + * @param[out] dest destination (result, mat2x4) + */ +CGLM_INLINE +void +glm_mat4x2_transpose(mat4x2 m, mat2x4 dest) { + dest[0][0] = m[0][0]; dest[0][1] = m[1][0]; dest[0][2] = m[2][0]; dest[0][3] = m[3][0]; + dest[1][0] = m[0][1]; dest[1][1] = m[1][1]; dest[1][2] = m[2][1]; dest[1][3] = m[3][1]; +} + +/*! + * @brief Multiply mat4x2 (m) by scalar constant (s). + * + * @param[in, out] m (src, dest) + * @param[in] s float (scalar) + */ +CGLM_INLINE +void +glm_mat4x2_scale(mat4x2 m, float s) { + m[0][0] *= s; m[0][1] *= s; m[1][0] *= s; m[1][1] *= s; + m[2][0] *= s; m[2][1] *= s; m[3][0] *= s; m[3][1] *= s; +} + +#endif diff --git a/external/cglm/mat4x3.h b/external/cglm/mat4x3.h new file mode 100644 index 0000000..a429437 --- /dev/null +++ b/external/cglm/mat4x3.h @@ -0,0 +1,168 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_MAT4X3_ZERO_INIT + GLM_MAT4X3_ZERO + + Functions: + CGLM_INLINE void glm_mat4x3_copy(mat4x3 src, mat4x3 dest); + CGLM_INLINE void glm_mat4x3_zero(mat4x3 m); + CGLM_INLINE void glm_mat4x3_make(const float * __restrict src, mat4x3 dest); + CGLM_INLINE void glm_mat4x3_mul(mat4x3 m1, mat3x4 m2, mat3 dest); + CGLM_INLINE void glm_mat4x3_mulv(mat4x3 m, vec4 v, vec3 dest); + CGLM_INLINE void glm_mat4x3_transpose(mat4x3 src, mat3x4 dest); + CGLM_INLINE void glm_mat4x3_scale(mat4x3 m, float s); + */ + +#ifndef cglm_mat4x3_h +#define cglm_mat4x3_h + +#include "common.h" + +#define GLM_MAT4X3_ZERO_INIT {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, \ + {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}} + +/* for C only */ +#define GLM_MAT4X3_ZERO GLM_MAT4X3_ZERO_INIT + +/*! + * @brief Copy mat4x3 (src) to mat4x3 (dest). + * + * @param[in] src mat4x3 (left) + * @param[out] dest destination (result, mat4x3) + */ +CGLM_INLINE +void +glm_mat4x3_copy(mat4x3 src, mat4x3 dest) { + glm_vec3_copy(src[0], dest[0]); + glm_vec3_copy(src[1], dest[1]); + glm_vec3_copy(src[2], dest[2]); + glm_vec3_copy(src[3], dest[3]); +} + +/*! + * @brief Zero out the mat4x3 (m). + * + * @param[in, out] mat4x3 (src, dest) + */ +CGLM_INLINE +void +glm_mat4x3_zero(mat4x3 m) { + CGLM_ALIGN_MAT mat4x3 t = GLM_MAT4X3_ZERO_INIT; + glm_mat4x3_copy(t, m); +} + +/*! + * @brief Create mat4x3 (dest) from pointer (src). + * + * @param[in] src pointer to an array of floats (left) + * @param[out] dest destination (result, mat4x3) + */ +CGLM_INLINE +void +glm_mat4x3_make(const float * __restrict src, mat4x3 dest) { + dest[0][0] = src[0]; + dest[0][1] = src[1]; + dest[0][2] = src[2]; + + dest[1][0] = src[3]; + dest[1][1] = src[4]; + dest[1][2] = src[5]; + + dest[2][0] = src[6]; + dest[2][1] = src[7]; + dest[2][2] = src[8]; + + dest[3][0] = src[9]; + dest[3][1] = src[10]; + dest[3][2] = src[11]; +} + +/*! + * @brief Multiply mat4x3 (m1) by mat3x4 (m2) and store in mat3 (dest). + * + * @code + * glm_mat4x3_mul(mat4x3, mat3x4, mat3); + * @endcode + * + * @param[in] m1 mat4x3 (left) + * @param[in] m2 mat3x4 (right) + * @param[out] dest destination (result, mat3) + */ +CGLM_INLINE +void +glm_mat4x3_mul(mat4x3 m1, mat3x4 m2, mat3 dest) { + float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], + a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2], + a20 = m1[2][0], a21 = m1[2][1], a22 = m1[2][2], + a30 = m1[3][0], a31 = m1[3][1], a32 = m1[3][2], + + b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2], b03 = m2[0][3], + b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2], b13 = m2[1][3], + b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2], b23 = m2[2][3]; + + dest[0][0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03; + dest[0][1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03; + dest[0][2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03; + + dest[1][0] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13; + dest[1][1] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13; + dest[1][2] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13; + + dest[2][0] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23; + dest[2][1] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23; + dest[2][2] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23; +} + +/*! + * @brief Multiply mat4x3 (m) by vec4 (v) and store in vec3 (dest). + * + * @param[in] m mat4x3 (left) + * @param[in] v vec3 (right, column vector) + * @param[out] dest destination (result, column vector) + */ +CGLM_INLINE +void +glm_mat4x3_mulv(mat4x3 m, vec4 v, vec3 dest) { + float v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; + + dest[0] = m[0][0] * v0 + m[1][0] * v1 + m[2][0] * v2 + m[3][0] * v3; + dest[1] = m[0][1] * v0 + m[1][1] * v1 + m[2][1] * v2 + m[3][1] * v3; + dest[2] = m[0][2] * v0 + m[1][2] * v1 + m[2][2] * v2 + m[3][2] * v3; +} + +/*! + * @brief Transpose mat4x3 (src) and store in mat3x4 (dest). + * + * @param[in] src mat4x3 (left) + * @param[out] dest destination (result, mat3x4) + */ +CGLM_INLINE +void +glm_mat4x3_transpose(mat4x3 src, mat3x4 dest) { + dest[0][0] = src[0][0]; dest[0][1] = src[1][0]; dest[0][2] = src[2][0]; dest[0][3] = src[3][0]; + dest[1][0] = src[0][1]; dest[1][1] = src[1][1]; dest[1][2] = src[2][1]; dest[1][3] = src[3][1]; + dest[2][0] = src[0][2]; dest[2][1] = src[1][2]; dest[2][2] = src[2][2]; dest[2][3] = src[3][2]; +} + +/*! + * @brief Multiply mat4x3 (m) by scalar constant (s). + * + * @param[in, out] m (src, dest) + * @param[in] s float (scalar) + */ +CGLM_INLINE +void +glm_mat4x3_scale(mat4x3 m, float s) { + m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; m[1][0] *= s; + m[1][1] *= s; m[1][2] *= s; m[2][0] *= s; m[2][1] *= s; + m[2][2] *= s; m[3][0] *= s; m[3][1] *= s; m[3][2] *= s; +} + +#endif /* cglm_mat4x3_h */ diff --git a/external/cglm/noise.h b/external/cglm/noise.h new file mode 100644 index 0000000..bec12e9 --- /dev/null +++ b/external/cglm/noise.h @@ -0,0 +1,734 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + * + * Based on the work of Stefan Gustavson and Ashima Arts on "webgl-noise": + * https://github.com/stegu/webgl-noise + * Following Stefan Gustavson's paper "Simplex noise demystified": + * http://www.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf + * + * Implementation based on glm::perlin function: + * https://github.com/g-truc/glm/blob/master/glm/gtc/noise.inl + */ + +#ifndef cglm_noise_h +#define cglm_noise_h + +#include "vec4.h" +#include "vec4-ext.h" + +#include "vec3.h" +#include "vec3-ext.h" + +#include "vec2.h" +#include "vec2-ext.h" + +#define glm__noiseDetail_mod289(x) (x - floorf(x * (1.0f / 289.0f)) * 289.0f) + +/* glm__noiseDetail_permute(vec4 x, vec4 dest) */ +#define glm__noiseDetail_permute(x, dest) { \ + dest[0] = glm__noiseDetail_mod289((x[0] * 34.0f + 1.0f) * x[0]); \ + dest[1] = glm__noiseDetail_mod289((x[1] * 34.0f + 1.0f) * x[1]); \ + dest[2] = glm__noiseDetail_mod289((x[2] * 34.0f + 1.0f) * x[2]); \ + dest[3] = glm__noiseDetail_mod289((x[3] * 34.0f + 1.0f) * x[3]); \ +} + +/* glm__noiseDetail_fade_vec4(vec4 t, vec4 dest) */ +#define glm__noiseDetail_fade_vec4(t, dest) { \ + /* dest = (t * t * t) * (t * (t * 6.0f - 15.0f) + 10.0f) */ \ + vec4 temp; \ + glm_vec4_mul(t, t, temp); \ + glm_vec4_mul(temp, t, temp); \ + /* dest = (t * (t * 6.0f - 15.0f) + 10.0f) */ \ + glm_vec4_scale(t, 6.0f, dest); \ + glm_vec4_subs(dest, 15.0f, dest); \ + glm_vec4_mul(t, dest, dest); \ + glm_vec4_adds(dest, 10.0f, dest); \ + /* dest = temp * dest */ \ + glm_vec4_mul(temp, dest, dest); \ +} + +/* glm__noiseDetail_fade_vec3(vec3 t, vec3 dest) */ +#define glm__noiseDetail_fade_vec3(t, dest) { \ + /* dest = (t * t * t) * (t * (t * 6.0f - 15.0f) + 10.0f) */ \ + /* temp = t * t * t */ \ + vec3 temp; \ + glm_vec3_mul(t, t, temp); \ + glm_vec3_mul(temp, t, temp); \ + /* dest = (t * (t * 6.0f - 15.0f) + 10.0f) */ \ + glm_vec3_scale(t, 6.0f, dest); \ + glm_vec3_subs(dest, 15.0f, dest); \ + glm_vec3_mul(t, dest, dest); \ + glm_vec3_adds(dest, 10.0f, dest); \ + /* dest = temp * dest */ \ + glm_vec3_mul(temp, dest, dest); \ +} + +/* glm__noiseDetail_fade_vec2(vec2 t, vec2 dest) */ +#define glm__noiseDetail_fade_vec2(t, dest) { \ + /* dest = (t * t * t) * (t * (t * 6.0f - 15.0f) + 10.0f) */ \ + /* temp = t * t * t */ \ + vec2 temp; \ + glm_vec2_mul(t, t, temp); \ + glm_vec2_mul(temp, t, temp); \ + /* dest = (t * (t * 6.0f - 15.0f) + 10.0f) */ \ + glm_vec2_scale(t, 6.0f, dest); \ + glm_vec2_subs(dest, 15.0f, dest); \ + glm_vec2_mul(t, dest, dest); \ + glm_vec2_adds(dest, 10.0f, dest); \ + /* dest = temp * dest */ \ + glm_vec2_mul(temp, dest, dest); \ +} + +/* glm__noiseDetail_taylorInvSqrt(vec4 x, vec4 dest) */ +#define glm__noiseDetail_taylorInvSqrt(x, dest) { \ + /* dest = 1.79284291400159f - 0.85373472095314f * x */ \ + vec4 temp; \ + glm_vec4_scale(x, 0.85373472095314f, temp); /* temp = 0.853...f * x */ \ + glm_vec4_fill(dest, 1.79284291400159f); /* dest = 1.792...f */ \ + glm_vec4_sub(dest, temp, dest); /* dest = 1.79284291400159f - temp */ \ +} + +/* norm = taylorInvSqrt(vec4( + * dot(g00__, g00__), + * dot(g01__, g01__), + * dot(g10__, g10__), + * dot(g11__, g11__) + * )); +*/ + +/* glm__noiseDetail_gradNorm_vec4(vec4 g00__, vec4 g01__, vec4 g10__, vec4 g11__) */ +#define glm__noiseDetail_gradNorm_vec4(g00__, g01__, g10__, g11__) { \ + vec4 norm; \ + norm[0] = glm_vec4_dot(g00__, g00__); /* norm.x = dot(g00__, g00__) */ \ + norm[1] = glm_vec4_dot(g01__, g01__); /* norm.y = dot(g01__, g01__) */ \ + norm[2] = glm_vec4_dot(g10__, g10__); /* norm.z = dot(g10__, g10__) */ \ + norm[3] = glm_vec4_dot(g11__, g11__); /* norm.w = dot(g11__, g11__) */ \ + glm__noiseDetail_taylorInvSqrt(norm, norm); /* norm = taylorInvSqrt(norm) */ \ + \ + glm_vec4_scale(g00__, norm[0], g00__); /* g00__ *= norm.x */ \ + glm_vec4_scale(g01__, norm[1], g01__); /* g01__ *= norm.y */ \ + glm_vec4_scale(g10__, norm[2], g10__); /* g10__ *= norm.z */ \ + glm_vec4_scale(g11__, norm[3], g11__); /* g11__ *= norm.w */ \ +} + +/* glm__noiseDetail_gradNorm_vec3(vec3 g00_, vec3 g01_, vec3 g10_, vec3 g11_) */ +#define glm__noiseDetail_gradNorm_vec3(g00_, g01_, g10_, g11_) { \ + vec4 norm; \ + norm[0] = glm_vec3_dot(g00_, g00_); /* norm.x = dot(g00_, g00_) */ \ + norm[1] = glm_vec3_dot(g01_, g01_); /* norm.y = dot(g01_, g01_) */ \ + norm[2] = glm_vec3_dot(g10_, g10_); /* norm.z = dot(g10_, g10_) */ \ + norm[3] = glm_vec3_dot(g11_, g11_); /* norm.w = dot(g11_, g11_) */ \ + glm__noiseDetail_taylorInvSqrt(norm, norm); /* norm = taylorInvSqrt(norm) */ \ + \ + glm_vec3_scale(g00_, norm[0], g00_); /* g00_ *= norm.x */ \ + glm_vec3_scale(g01_, norm[1], g01_); /* g01_ *= norm.y */ \ + glm_vec3_scale(g10_, norm[2], g10_); /* g10_ *= norm.z */ \ + glm_vec3_scale(g11_, norm[3], g11_); /* g11_ *= norm.w */ \ +} + +/* glm__noiseDetail_gradNorm_vec2(vec2 g00, vec2 g01, vec2 g10, vec2 g11) */ +#define glm__noiseDetail_gradNorm_vec2(g00, g01, g10, g11) { \ + vec4 norm; \ + norm[0] = glm_vec2_dot(g00, g00); /* norm.x = dot(g00, g00) */ \ + norm[1] = glm_vec2_dot(g01, g01); /* norm.y = dot(g01, g01) */ \ + norm[2] = glm_vec2_dot(g10, g10); /* norm.z = dot(g10, g10) */ \ + norm[3] = glm_vec2_dot(g11, g11); /* norm.w = dot(g11, g11) */ \ + glm__noiseDetail_taylorInvSqrt(norm, norm); /* norm = taylorInvSqrt(norm) */ \ + \ + glm_vec2_scale(g00, norm[0], g00); /* g00 *= norm.x */ \ + glm_vec2_scale(g01, norm[1], g01); /* g01 *= norm.y */ \ + glm_vec2_scale(g10, norm[2], g10); /* g10 *= norm.z */ \ + glm_vec2_scale(g11, norm[3], g11); /* g11 *= norm.w */ \ +} + +/* glm__noiseDetail_i2gxyzw(vec4 ixy, vec4 gx, vec4 gy, vec4 gz, vec4 gw) */ +#define glm__noiseDetail_i2gxyzw(ixy, gx, gy, gz, gw) { \ + /* gx = ixy / 7.0 */ \ + glm_vec4_divs(ixy, 7.0f, gx); /* gx = ixy / 7.0 */ \ + \ + /* gy = fract(gx) / 7.0 */ \ + glm_vec4_floor(gx, gy); /* gy = floor(gx) */ \ + glm_vec4_divs(gy, 7.0f, gy); /* gy /= 7.0 */ \ + \ + /* gz = floor(gy) / 6.0 */ \ + glm_vec4_floor(gy, gz); /* gz = floor(gy) */ \ + glm_vec4_divs(gz, 6.0f, gz); /* gz /= 6.0 */ \ + \ + /* gx = fract(gx) - 0.5f */ \ + glm_vec4_fract(gx, gx); /* gx = fract(gx) */ \ + glm_vec4_subs(gx, 0.5f, gx); /* gx -= 0.5f */ \ + \ + /* gy = fract(gy) - 0.5f */ \ + glm_vec4_fract(gy, gy); /* gy = fract(gy) */ \ + glm_vec4_subs(gy, 0.5f, gy); /* gy -= 0.5f */ \ + \ + /* gz = fract(gz) - 0.5f */ \ + glm_vec4_fract(gz, gz); /* gz = fract(gz) */ \ + glm_vec4_subs(gz, 0.5f, gz); /* gz -= 0.5f */ \ + \ + /* abs(gx), abs(gy), abs(gz) */ \ + vec4 gxa, gya, gza; \ + glm_vec4_abs(gx, gxa); /* gxa = abs(gx) */ \ + glm_vec4_abs(gy, gya); /* gya = abs(gy) */ \ + glm_vec4_abs(gz, gza); /* gza = abs(gz) */ \ + \ + /* gw = 0.75 - abs(gx) - abs(gy) - abs(gz) */ \ + glm_vec4_fill(gw, 0.75f); /* gw = 0.75 */ \ + glm_vec4_sub(gw, gxa, gw); /* gw -= gxa */ \ + glm_vec4_sub(gw, gza, gw); /* gw -= gza */ \ + glm_vec4_sub(gw, gya, gw); /* gw -= gya */ \ + \ + /* sw = step(gw, 0.0); */ \ + vec4 sw; \ + glm_vec4_stepr(gw, 0.0f, sw); /* sw = step(gw, 0.0) */ \ + \ + /* gx -= sw * (step(vec4(0), gx) - T(0.5)); */ \ + vec4 temp = {0.0f}; /* temp = 0.0 */ \ + glm_vec4_step(temp, gx, temp); /* temp = step(temp, gx) */ \ + glm_vec4_subs(temp, 0.5f, temp); /* temp -= 0.5 */ \ + glm_vec4_mul(sw, temp, temp); /* temp *= sw */ \ + glm_vec4_sub(gx, temp, gx); /* gx -= temp */ \ + \ + /* gy -= sw * (step(vec4(0), gy) - T(0.5)); */ \ + glm_vec4_zero(temp); /* reset temp */ \ + glm_vec4_step(temp, gy, temp); /* temp = step(temp, gy) */ \ + glm_vec4_subs(temp, 0.5f, temp); /* temp -= 0.5 */ \ + glm_vec4_mul(sw, temp, temp); /* temp *= sw */ \ + glm_vec4_sub(gy, temp, gy); /* gy -= temp */ \ +} + +/* NOTE: This function is not *quite* analogous to glm__noiseDetail_i2gxyzw + * to try to match the output of glm::perlin. I think it might be a bug in + * in the original implementation, but for now I'm keeping it consistent. -MK + * + * Follow up: The original implementation (glm v 1.0.1) does: + * + * vec<4, T, Q> gx0 = ixy0 * T(1.0 / 7.0); + * + * as opposed to: + * + * vec<4, T, Q> gx0 = ixy0 / T(7); + * + * This ends up mapping to different simd instructions, at least on AMD. + * The delta is tiny but it gets amplified by the rest of the noise function. + * Hence we too need to do `glm_vec4_scale` as opposed to `glm_vec4_divs`, to + * match it. -MK + */ + +/* glm__noiseDetail_i2gxyz(vec4 i, vec4 gx, vec4 gy, vec4 gz) */ +#define glm__noiseDetail_i2gxyz(ixy, gx, gy, gz) { \ + /* gx = ixy / 7.0 */ \ + glm_vec4_scale(ixy, 1.0f / 7.0f, gx); /* gx = ixy * (1/7.0) */\ + \ + /* gy = fract(floor(gx0) / 7.0)) - 0.5; */ \ + glm_vec4_floor(gx, gy); /* gy = floor(gx) */ \ + glm_vec4_scale(gy, 1.0f / 7.0f, gy); /* gy *= 1 / 7.0 */ \ + glm_vec4_fract(gy, gy); /* gy = fract(gy) */ \ + glm_vec4_subs(gy, 0.5f, gy); /* gy -= 0.5f */ \ + \ + /* gx = fract(gx); */ \ + glm_vec4_fract(gx, gx); /* gx = fract(gx) */ \ + \ + /* abs(gx), abs(gy) */ \ + vec4 gxa, gya; \ + glm_vec4_abs(gx, gxa); /* gxa = abs(gx) */ \ + glm_vec4_abs(gy, gya); /* gya = abs(gy) */ \ + \ + /* gz = vec4(0.5) - abs(gx0) - abs(gy0); */ \ + glm_vec4_fill(gz, 0.5f); /* gz = 0.5 */ \ + glm_vec4_sub(gz, gxa, gz); /* gz -= gxa */ \ + glm_vec4_sub(gz, gya, gz); /* gz -= gya */ \ + \ + /* sz = step(gw, 0.0); */ \ + vec4 sz; \ + glm_vec4_stepr(gz, 0.0f, sz); /* sz = step(gz, 0.0) */ \ + \ + /* gx0 -= sz0 * (step(0.0, gx0) - T(0.5)); */ \ + vec4 temp = {0.0f}; /* temp = 0.0 */ \ + glm_vec4_step(temp, gx, temp); /* temp = step(temp, gx) */ \ + glm_vec4_subs(temp, 0.5f, temp); /* temp -= 0.5 */ \ + glm_vec4_mul(sz, temp, temp); /* temp *= sz */ \ + glm_vec4_sub(gx, temp, gx); /* gx -= temp */ \ + \ + /* gy0 -= sz0 * (step(0.0, gy0) - T(0.5)); */ \ + glm_vec4_zero(temp); /* reset temp */ \ + glm_vec4_step(temp, gy, temp); /* temp = step(temp, gy) */ \ + glm_vec4_subs(temp, 0.5f, temp); /* temp -= 0.5 */ \ + glm_vec4_mul(sz, temp, temp); /* temp *= sz */ \ + glm_vec4_sub(gy, temp, gy); /* gy -= temp */ \ +} + +/* glm__noiseDetail_i2gxy(vec4 i, vec4 gx, vec4 gy) */ +#define glm__noiseDetail_i2gxy(i, gx, gy) { \ + /* gx = 2.0 * fract(i / 41.0) - 1.0; */ \ + glm_vec4_divs(i, 41.0f, gx); /* gx = i / 41.0 */ \ + glm_vec4_fract(gx, gx); /* gx = fract(gx) */ \ + glm_vec4_scale(gx, 2.0f, gx); /* gx *= 2.0 */ \ + glm_vec4_subs(gx, 1.0f, gx); /* gx -= 1.0 */ \ + \ + /* gy = abs(gx) - 0.5; */ \ + glm_vec4_abs(gx, gy); /* gy = abs(gx) */ \ + glm_vec4_subs(gy, 0.5f, gy); /* gy -= 0.5 */ \ + \ + /* tx = floor(gx + 0.5); */ \ + vec4 tx; \ + glm_vec4_adds(gx, 0.5f, tx); /* tx = gx + 0.5 */ \ + glm_vec4_floor(tx, tx); /* tx = floor(tx) */ \ + \ + /* gx = gx - tx; */ \ + glm_vec4_sub(gx, tx, gx); /* gx -= tx */ \ +} + +/* ============================================================================ + * Classic perlin noise + * ============================================================================ + */ + +/*! + * @brief Classic perlin noise + * + * @param[in] point 4D vector + * @returns perlin noise value + */ +CGLM_INLINE +float +glm_perlin_vec4(vec4 point) { + /* Integer part of p for indexing */ + vec4 Pi0; + glm_vec4_floor(point, Pi0); /* Pi0 = floor(point); */ + + /* Integer part + 1 */ + vec4 Pi1; + glm_vec4_adds(Pi0, 1.0f, Pi1); /* Pi1 = Pi0 + 1.0f; */ + + glm_vec4_mods(Pi0, 289.0f, Pi0); /* Pi0 = mod(Pi0, 289.0f); */ + glm_vec4_mods(Pi1, 289.0f, Pi1); /* Pi1 = mod(Pi1, 289.0f); */ + + /* Fractional part of p for interpolation */ + vec4 Pf0; + glm_vec4_fract(point, Pf0); + + /* Fractional part - 1.0 */ + vec4 Pf1; + glm_vec4_subs(Pf0, 1.0f, Pf1); + + vec4 ix = {Pi0[0], Pi1[0], Pi0[0], Pi1[0]}; + vec4 iy = {Pi0[1], Pi0[1], Pi1[1], Pi1[1]}; + vec4 iz0 = {Pi0[2], Pi0[2], Pi0[2], Pi0[2]}; /* iz0 = vec4(Pi0.z); */ + vec4 iz1 = {Pi1[2], Pi1[2], Pi1[2], Pi1[2]}; /* iz1 = vec4(Pi1.z); */ + vec4 iw0 = {Pi0[3], Pi0[3], Pi0[3], Pi0[3]}; /* iw0 = vec4(Pi0.w); */ + vec4 iw1 = {Pi1[3], Pi1[3], Pi1[3], Pi1[3]}; /* iw1 = vec4(Pi1.w); */ + + /* ------------ */ + + /* ixy = permute(permute(ix) + iy) */ + vec4 ixy; + glm__noiseDetail_permute(ix, ixy); /* ixy = permute(ix) */ + glm_vec4_add(ixy, iy, ixy); /* ixy += iy; */ + glm__noiseDetail_permute(ixy, ixy); /* ixy = permute(ixy) */ + + /* ixy0 = permute(ixy + iz0) */ + vec4 ixy0; + glm_vec4_add(ixy, iz0, ixy0); /* ixy0 = ixy + iz0 */ + glm__noiseDetail_permute(ixy0, ixy0); /* ixy0 = permute(ixy0) */ + + /* ixy1 = permute(ixy + iz1) */ + vec4 ixy1; + glm_vec4_add(ixy, iz1, ixy1); /* ixy1 = ixy, iz1 */ + glm__noiseDetail_permute(ixy1, ixy1); /* ixy1 = permute(ixy1) */ + + /* ixy00 = permute(ixy0 + iw0) */ + vec4 ixy00; + glm_vec4_add(ixy0, iw0, ixy00); /* ixy00 = ixy0 + iw0 */ + glm__noiseDetail_permute(ixy00, ixy00); /* ixy00 = permute(ixy00) */ + + /* ixy01 = permute(ixy0 + iw1) */ + vec4 ixy01; + glm_vec4_add(ixy0, iw1, ixy01); /* ixy01 = ixy0 + iw1 */ + glm__noiseDetail_permute(ixy01, ixy01); /* ixy01 = permute(ixy01) */ + + /* ixy10 = permute(ixy1 + iw0) */ + vec4 ixy10; + glm_vec4_add(ixy1, iw0, ixy10); /* ixy10 = ixy1 + iw0 */ + glm__noiseDetail_permute(ixy10, ixy10); /* ixy10 = permute(ixy10) */ + + /* ixy11 = permute(ixy1 + iw1) */ + vec4 ixy11; + glm_vec4_add(ixy1, iw1, ixy11); /* ixy11 = ixy1 + iw1 */ + glm__noiseDetail_permute(ixy11, ixy11); /* ixy11 = permute(ixy11) */ + + /* ------------ */ + + vec4 gx00, gy00, gz00, gw00; + glm__noiseDetail_i2gxyzw(ixy00, gx00, gy00, gz00, gw00); + + vec4 gx01, gy01, gz01, gw01; + glm__noiseDetail_i2gxyzw(ixy01, gx01, gy01, gz01, gw01); + + vec4 gx10, gy10, gz10, gw10; + glm__noiseDetail_i2gxyzw(ixy10, gx10, gy10, gz10, gw10); + + vec4 gx11, gy11, gz11, gw11; + glm__noiseDetail_i2gxyzw(ixy11, gx11, gy11, gz11, gw11); + + /* ------------ */ + + vec4 g0000 = {gx00[0], gy00[0], gz00[0], gw00[0]}; /* g0000 = vec4(gx00.x, gy00.x, gz00.x, gw00.x); */ + vec4 g0100 = {gx00[2], gy00[2], gz00[2], gw00[2]}; /* g0100 = vec4(gx00.z, gy00.z, gz00.z, gw00.z); */ + vec4 g1000 = {gx00[1], gy00[1], gz00[1], gw00[1]}; /* g1000 = vec4(gx00.y, gy00.y, gz00.y, gw00.y); */ + vec4 g1100 = {gx00[3], gy00[3], gz00[3], gw00[3]}; /* g1100 = vec4(gx00.w, gy00.w, gz00.w, gw00.w); */ + + vec4 g0001 = {gx01[0], gy01[0], gz01[0], gw01[0]}; /* g0001 = vec4(gx01.x, gy01.x, gz01.x, gw01.x); */ + vec4 g0101 = {gx01[2], gy01[2], gz01[2], gw01[2]}; /* g0101 = vec4(gx01.z, gy01.z, gz01.z, gw01.z); */ + vec4 g1001 = {gx01[1], gy01[1], gz01[1], gw01[1]}; /* g1001 = vec4(gx01.y, gy01.y, gz01.y, gw01.y); */ + vec4 g1101 = {gx01[3], gy01[3], gz01[3], gw01[3]}; /* g1101 = vec4(gx01.w, gy01.w, gz01.w, gw01.w); */ + + vec4 g0010 = {gx10[0], gy10[0], gz10[0], gw10[0]}; /* g0010 = vec4(gx10.x, gy10.x, gz10.x, gw10.x); */ + vec4 g0110 = {gx10[2], gy10[2], gz10[2], gw10[2]}; /* g0110 = vec4(gx10.z, gy10.z, gz10.z, gw10.z); */ + vec4 g1010 = {gx10[1], gy10[1], gz10[1], gw10[1]}; /* g1010 = vec4(gx10.y, gy10.y, gz10.y, gw10.y); */ + vec4 g1110 = {gx10[3], gy10[3], gz10[3], gw10[3]}; /* g1110 = vec4(gx10.w, gy10.w, gz10.w, gw10.w); */ + + vec4 g0011 = {gx11[0], gy11[0], gz11[0], gw11[0]}; /* g0011 = vec4(gx11.x, gy11.x, gz11.x, gw11.x); */ + vec4 g0111 = {gx11[2], gy11[2], gz11[2], gw11[2]}; /* g0111 = vec4(gx11.z, gy11.z, gz11.z, gw11.z); */ + vec4 g1011 = {gx11[1], gy11[1], gz11[1], gw11[1]}; /* g1011 = vec4(gx11.y, gy11.y, gz11.y, gw11.y); */ + vec4 g1111 = {gx11[3], gy11[3], gz11[3], gw11[3]}; /* g1111 = vec4(gx11.w, gy11.w, gz11.w, gw11.w); */ + + glm__noiseDetail_gradNorm_vec4(g0000, g0100, g1000, g1100); + glm__noiseDetail_gradNorm_vec4(g0001, g0101, g1001, g1101); + glm__noiseDetail_gradNorm_vec4(g0010, g0110, g1010, g1110); + glm__noiseDetail_gradNorm_vec4(g0011, g0111, g1011, g1111); + + /* ------------ */ + + float n0000 = glm_vec4_dot(g0000, Pf0); /* n0000 = dot(g0000, Pf0) */ + + /* n1000 = dot(g1000, vec4(Pf1.x, Pf0.y, Pf0.z, Pf0.w)) */ + vec4 n1000d = {Pf1[0], Pf0[1], Pf0[2], Pf0[3]}; + float n1000 = glm_vec4_dot(g1000, n1000d); + + /* n0100 = dot(g0100, vec4(Pf0.x, Pf1.y, Pf0.z, Pf0.w)) */ + vec4 n0100d = {Pf0[0], Pf1[1], Pf0[2], Pf0[3]}; + float n0100 = glm_vec4_dot(g0100, n0100d); + + /* n1100 = dot(g1100, vec4(Pf1.x, Pf1.y, Pf0.z, Pf0.w)) */ + vec4 n1100d = {Pf1[0], Pf1[1], Pf0[2], Pf0[3]}; + float n1100 = glm_vec4_dot(g1100, n1100d); + + /* n0010 = dot(g0010, vec4(Pf0.x, Pf0.y, Pf1.z, Pf0.w)) */ + vec4 n0010d = {Pf0[0], Pf0[1], Pf1[2], Pf0[3]}; + float n0010 = glm_vec4_dot(g0010, n0010d); + + /* n1010 = dot(g1010, vec4(Pf1.x, Pf0.y, Pf1.z, Pf0.w)) */ + vec4 n1010d = {Pf1[0], Pf0[1], Pf1[2], Pf0[3]}; + float n1010 = glm_vec4_dot(g1010, n1010d); + + /* n0110 = dot(g0110, vec4(Pf0.x, Pf1.y, Pf1.z, Pf0.w)) */ + vec4 n0110d = {Pf0[0], Pf1[1], Pf1[2], Pf0[3]}; + float n0110 = glm_vec4_dot(g0110, n0110d); + + /* n1110 = dot(g1110, vec4(Pf1.x, Pf1.y, Pf1.z, Pf0.w)) */ + vec4 n1110d = {Pf1[0], Pf1[1], Pf1[2], Pf0[3]}; + float n1110 = glm_vec4_dot(g1110, n1110d); + + /* n0001 = dot(g0001, vec4(Pf0.x, Pf0.y, Pf0.z, Pf1.w)) */ + vec4 n0001d = {Pf0[0], Pf0[1], Pf0[2], Pf1[3]}; + float n0001 = glm_vec4_dot(g0001, n0001d); + + /* n1001 = dot(g1001, vec4(Pf1.x, Pf0.y, Pf0.z, Pf1.w)) */ + vec4 n1001d = {Pf1[0], Pf0[1], Pf0[2], Pf1[3]}; + float n1001 = glm_vec4_dot(g1001, n1001d); + + /* n0101 = dot(g0101, vec4(Pf0.x, Pf1.y, Pf0.z, Pf1.w)) */ + vec4 n0101d = {Pf0[0], Pf1[1], Pf0[2], Pf1[3]}; + float n0101 = glm_vec4_dot(g0101, n0101d); + + /* n1101 = dot(g1101, vec4(Pf1.x, Pf1.y, Pf0.z, Pf1.w)) */ + vec4 n1101d = {Pf1[0], Pf1[1], Pf0[2], Pf1[3]}; + float n1101 = glm_vec4_dot(g1101, n1101d); + + /* n0011 = dot(g0011, vec4(Pf0.x, Pf0.y, Pf1.z, Pf1.w)) */ + vec4 n0011d = {Pf0[0], Pf0[1], Pf1[2], Pf1[3]}; + float n0011 = glm_vec4_dot(g0011, n0011d); + + /* n1011 = dot(g1011, vec4(Pf1.x, Pf0.y, Pf1.z, Pf1.w)) */ + vec4 n1011d = {Pf1[0], Pf0[1], Pf1[2], Pf1[3]}; + float n1011 = glm_vec4_dot(g1011, n1011d); + + /* n0111 = dot(g0111, vec4(Pf0.x, Pf1.y, Pf1.z, Pf1.w)) */ + vec4 n0111d = {Pf0[0], Pf1[1], Pf1[2], Pf1[3]}; + float n0111 = glm_vec4_dot(g0111, n0111d); + + float n1111 = glm_vec4_dot(g1111, Pf1); /* n1111 = dot(g1111, Pf1) */ + + /* ------------ */ + + vec4 fade_xyzw; + glm__noiseDetail_fade_vec4(Pf0, fade_xyzw); /* fade_xyzw = fade(Pf0) */ + + /* n_0w = lerp(vec4(n0000, n1000, n0100, n1100), vec4(n0001, n1001, n0101, n1101), fade_xyzw.w) */ + vec4 n_0w1 = {n0000, n1000, n0100, n1100}; + vec4 n_0w2 = {n0001, n1001, n0101, n1101}; + vec4 n_0w; + glm_vec4_lerp(n_0w1, n_0w2, fade_xyzw[3], n_0w); + + /* n_1w = lerp(vec4(n0010, n1010, n0110, n1110), vec4(n0011, n1011, n0111, n1111), fade_xyzw.w) */ + vec4 n_1w1 = {n0010, n1010, n0110, n1110}; + vec4 n_1w2 = {n0011, n1011, n0111, n1111}; + vec4 n_1w; + glm_vec4_lerp(n_1w1, n_1w2, fade_xyzw[3], n_1w); + + /* n_zw = lerp(n_0w, n_1w, fade_xyzw.z) */ + vec4 n_zw; + glm_vec4_lerp(n_0w, n_1w, fade_xyzw[2], n_zw); + + /* n_yzw = lerp(vec2(n_zw.x, n_zw.y), vec2(n_zw.z, n_zw.w), fade_xyzw.y) */ + vec2 n_yzw; + vec2 n_yzw1 = {n_zw[0], n_zw[1]}; + vec2 n_yzw2 = {n_zw[2], n_zw[3]}; + glm_vec2_lerp(n_yzw1, n_yzw2, fade_xyzw[1], n_yzw); + + /* n_xyzw = lerp(n_yzw.x, n_yzw.y, fade_xyzw.x) */ + float n_xyzw = glm_lerp(n_yzw[0], n_yzw[1], fade_xyzw[0]); + + return n_xyzw * 2.2f; +} + + +/*! + * @brief Classic perlin noise + * + * @param[in] point 3D vector + * @returns perlin noise value + */ +CGLM_INLINE +float +glm_perlin_vec3(vec3 point) { + /* Integer part of p for indexing */ + vec3 Pi0; + glm_vec3_floor(point, Pi0); /* Pi0 = floor(point); */ + + /* Integer part + 1 */ + vec3 Pi1; + glm_vec3_adds(Pi0, 1.0f, Pi1); /* Pi1 = Pi0 + 1.0f; */ + + glm_vec3_mods(Pi0, 289.0f, Pi0); /* Pi0 = mod(Pi0, 289.0f); */ + glm_vec3_mods(Pi1, 289.0f, Pi1); /* Pi1 = mod(Pi1, 289.0f); */ + + /* Fractional part of p for interpolation */ + vec3 Pf0; + glm_vec3_fract(point, Pf0); + + /* Fractional part - 1.0 */ + vec3 Pf1; + glm_vec3_subs(Pf0, 1.0f, Pf1); + + vec4 ix = {Pi0[0], Pi1[0], Pi0[0], Pi1[0]}; + vec4 iy = {Pi0[1], Pi0[1], Pi1[1], Pi1[1]}; + vec4 iz0 = {Pi0[2], Pi0[2], Pi0[2], Pi0[2]}; /* iz0 = vec4(Pi0.z); */ + vec4 iz1 = {Pi1[2], Pi1[2], Pi1[2], Pi1[2]}; /* iz1 = vec4(Pi1.z); */ + + /* ------------ */ + + /* ixy = permute(permute(ix) + iy) */ + vec4 ixy; + glm__noiseDetail_permute(ix, ixy); /* ixy = permute(ix) */ + glm_vec4_add(ixy, iy, ixy); /* ixy += iy; */ + glm__noiseDetail_permute(ixy, ixy); /* ixy = permute(ixy) */ + + /* ixy0 = permute(ixy + iz0) */ + vec4 ixy0; + glm_vec4_add(ixy, iz0, ixy0); /* ixy0 = ixy + iz0 */ + glm__noiseDetail_permute(ixy0, ixy0); /* ixy0 = permute(ixy0) */ + + /* ixy1 = permute(ixy + iz1) */ + vec4 ixy1; + glm_vec4_add(ixy, iz1, ixy1); /* ixy1 = ixy, iz1 */ + glm__noiseDetail_permute(ixy1, ixy1); /* ixy1 = permute(ixy1) */ + + /* ------------ */ + + vec4 gx0, gy0, gz0; + glm__noiseDetail_i2gxyz(ixy0, gx0, gy0, gz0); + + vec4 gx1, gy1, gz1; + glm__noiseDetail_i2gxyz(ixy1, gx1, gy1, gz1); + + /* ------------ */ + + vec3 g000 = {gx0[0], gy0[0], gz0[0]}; /* g000 = vec3(gx0.x, gy0.x, gz0.x); */ + vec3 g100 = {gx0[1], gy0[1], gz0[1]}; /* g100 = vec3(gx0.y, gy0.y, gz0.y); */ + vec3 g010 = {gx0[2], gy0[2], gz0[2]}; /* g010 = vec3(gx0.z, gy0.z, gz0.z); */ + vec3 g110 = {gx0[3], gy0[3], gz0[3]}; /* g110 = vec3(gx0.w, gy0.w, gz0.w); */ + + vec3 g001 = {gx1[0], gy1[0], gz1[0]}; /* g001 = vec3(gx1.x, gy1.x, gz1.x); */ + vec3 g101 = {gx1[1], gy1[1], gz1[1]}; /* g101 = vec3(gx1.y, gy1.y, gz1.y); */ + vec3 g011 = {gx1[2], gy1[2], gz1[2]}; /* g011 = vec3(gx1.z, gy1.z, gz1.z); */ + vec3 g111 = {gx1[3], gy1[3], gz1[3]}; /* g111 = vec3(gx1.w, gy1.w, gz1.w); */ + + glm__noiseDetail_gradNorm_vec3(g000, g010, g100, g110); + glm__noiseDetail_gradNorm_vec3(g001, g011, g101, g111); + + /* ------------ */ + + float n000 = glm_vec3_dot(g000, Pf0); /* n000 = dot(g000, Pf0) */ + + /* n100 = dot(g100, vec3(Pf1.x, Pf0.y, Pf0.z)) */ + vec3 n100d = {Pf1[0], Pf0[1], Pf0[2]}; + float n100 = glm_vec3_dot(g100, n100d); + + /* n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)) */ + vec3 n010d = {Pf0[0], Pf1[1], Pf0[2]}; + float n010 = glm_vec3_dot(g010, n010d); + + /* n110 = dot(g110, vec3(Pf1.x, Pf1.y, Pf0.z)) */ + vec3 n110d = {Pf1[0], Pf1[1], Pf0[2]}; + float n110 = glm_vec3_dot(g110, n110d); + + /* n001 = dot(g001, vec3(Pf0.x, Pf0.y, Pf1.z)) */ + vec3 n001d = {Pf0[0], Pf0[1], Pf1[2]}; + float n001 = glm_vec3_dot(g001, n001d); + + /* n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)) */ + vec3 n101d = {Pf1[0], Pf0[1], Pf1[2]}; + float n101 = glm_vec3_dot(g101, n101d); + + /* n011 = dot(g011, vec3(Pf0.x, Pf1.y, Pf1.z)) */ + vec3 n011d = {Pf0[0], Pf1[1], Pf1[2]}; + float n011 = glm_vec3_dot(g011, n011d); + + float n111 = glm_vec3_dot(g111, Pf1); /* n111 = dot(g111, Pf1) */ + + /* ------------ */ + + vec3 fade_xyz; + glm__noiseDetail_fade_vec3(Pf0, fade_xyz); /* fade_xyz = fade(Pf0) */ + + /* n_z = lerp(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z); */ + vec4 n_z; + vec4 n_z1 = {n000, n100, n010, n110}; + vec4 n_z2 = {n001, n101, n011, n111}; + glm_vec4_lerp(n_z1, n_z2, fade_xyz[2], n_z); + + /* vec2 n_yz = lerp(vec2(n_z.x, n_z.y), vec2(n_z.z, n_z.w), fade_xyz.y); */ + vec2 n_yz; + vec2 n_yz1 = {n_z[0], n_z[1]}; + vec2 n_yz2 = {n_z[2], n_z[3]}; + glm_vec2_lerp(n_yz1, n_yz2, fade_xyz[1], n_yz); + + /* n_xyz = lerp(n_yz.x, n_yz.y, fade_xyz.x); */ + float n_xyz = glm_lerp(n_yz[0], n_yz[1], fade_xyz[0]); + + return n_xyz * 2.2f; +} + +/*! + * @brief Classic perlin noise + * + * @param[in] point 2D vector + * @returns perlin noise value + */ +CGLM_INLINE +float +glm_perlin_vec2(vec2 point) { + + /* Integer part of p for indexing */ + /* Pi = floor(vec4(point.x, point.y, point.x, point.y)) + vec4(0.0, 0.0, 1.0, 1.0); */ + vec4 Pi = {point[0], point[1], point[0], point[1]}; /* Pi = vec4(point.x, point.y, point.x, point.y) */ + glm_vec4_floor(Pi, Pi); /* Pi = floor(Pi) */ + Pi[2] += 1.0f; /* Pi.z += 1.0 */ + Pi[3] += 1.0f; /* Pi.w += 1.0 */ + + /* Fractional part of p for interpolation */ + /* vec<4, T, Q> Pf = glm::fract(vec<4, T, Q>(Position.x, Position.y, Position.x, Position.y)) - vec<4, T, Q>(0.0, 0.0, 1.0, 1.0); */ + vec4 Pf = {point[0], point[1], point[0], point[1]}; /* Pf = vec4(point.x, point.y, point.x, point.y) */ + glm_vec4_fract(Pf, Pf); /* Pf = fract(Pf) */ + Pf[2] -= 1.0f; /* Pf.z -= 1.0 */ + Pf[3] -= 1.0f; /* Pf.w -= 1.0 */ + + /* Mod to avoid truncation effects in permutation */ + glm_vec4_mods(Pi, 289.0f, Pi); /* Pi = mod(Pi, 289.0f); */ + + vec4 ix = {Pi[0], Pi[2], Pi[0], Pi[2]}; /* ix = vec4(Pi.x, Pi.z, Pi.x, Pi.z) */ + vec4 iy = {Pi[1], Pi[1], Pi[3], Pi[3]}; /* iy = vec4(Pi.y, Pi.y, Pi.w, Pi.w) */ + vec4 fx = {Pf[0], Pf[2], Pf[0], Pf[2]}; /* fx = vec4(Pf.x, Pf.z, Pf.x, Pf.z) */ + vec4 fy = {Pf[1], Pf[1], Pf[3], Pf[3]}; /* fy = vec4(Pf.y, Pf.y, Pf.w, Pf.w) */ + + /* ------------ */ + + /* i = permute(permute(ix) + iy); */ + vec4 i; + glm__noiseDetail_permute(ix, i); /* i = permute(ix) */ + glm_vec4_add(i, iy, i); /* i += iy; */ + glm__noiseDetail_permute(i, i); /* i = permute(i) */ + + /* ------------ */ + + vec4 gx, gy; + glm__noiseDetail_i2gxy(i, gx, gy); + + /* ------------ */ + + vec2 g00 = {gx[0], gy[0]}; /* g00 = vec2(gx.x, gy.x) */ + vec2 g10 = {gx[1], gy[1]}; /* g10 = vec2(gx.y, gy.y) */ + vec2 g01 = {gx[2], gy[2]}; /* g01 = vec2(gx.z, gy.z) */ + vec2 g11 = {gx[3], gy[3]}; /* g11 = vec2(gx.w, gy.w) */ + + glm__noiseDetail_gradNorm_vec2(g00, g01, g10, g11); + + /* ------------ */ + + /* n00 = dot(g00, vec2(fx.x, fy.x)) */ + vec2 n00d = {fx[0], fy[0]}; /* n00d = vec2(fx.x, fy.x) */ + float n00 = glm_vec2_dot(g00, n00d); /* n00 = dot(g00, n00d) */ + + /* n10 = dot(g10, vec2(fx.y, fy.y)) */ + vec2 n10d = {fx[1], fy[1]}; /* n10d = vec2(fx.y, fy.y) */ + float n10 = glm_vec2_dot(g10, n10d); /* n10 = dot(g10, n10d) */ + + /* n01 = dot(g01, vec2(fx.z, fy.z)) */ + vec2 n01d = {fx[2], fy[2]}; /* n01d = vec2(fx.z, fy.z) */ + float n01 = glm_vec2_dot(g01, n01d); /* n01 = dot(g01, n01d) */ + + /* n11 = dot(g11, vec2(fx.w, fy.w)) */ + vec2 n11d = {fx[3], fy[3]}; /* n11d = vec2(fx.w, fy.w) */ + float n11 = glm_vec2_dot(g11, n11d); /* n11 = dot(g11, n11d) */ + + /* ------------ */ + + /* fade_xyz = fade(vec2(Pf.x, Pf.y)) */ + vec2 fade_xy; + vec2 temp2 = {Pf[0], Pf[1]}; /* temp = vec2(Pf.x, Pf.y) */ + glm__noiseDetail_fade_vec2(temp2, fade_xy); /* fade_xy = fade(temp) */ + + /* n_x = lerp(vec2(n00, n01), vec2(n10, n11), fade_xy.x); */ + vec2 n_x; + vec2 n_x1 = {n00, n01}; /* n_x1 = vec2(n00, n01) */ + vec2 n_x2 = {n10, n11}; /* n_x2 = vec2(n10, n11) */ + glm_vec2_lerp(n_x1, n_x2, fade_xy[0], n_x); /* n_x = lerp(n_x1, n_x2, fade_xy.x) */ + + /* T n_xy = mix(n_x.x, n_x.y, fade_xy.y); */ + /* n_xy = lerp(n_x.x, n_x.y, fade_xy.y); */ + float n_xy = glm_lerp(n_x[0], n_x[1], fade_xy[1]); + + return n_xy * 2.3f; +} + +/* Undefine all helper macros */ + +#undef glm__noiseDetail_mod289 +#undef glm__noiseDetail_permute +#undef glm__noiseDetail_fade_vec4 +#undef glm__noiseDetail_fade_vec3 +#undef glm__noiseDetail_fade_vec2 +#undef glm__noiseDetail_taylorInvSqrt +#undef glm__noiseDetail_gradNorm_vec4 +#undef glm__noiseDetail_gradNorm_vec3 +#undef glm__noiseDetail_gradNorm_vec2 +#undef glm__noiseDetail_i2gxyzw +#undef glm__noiseDetail_i2gxyz +#undef glm__noiseDetail_i2gxy + +#endif /* cglm_noise_h */ diff --git a/external/cglm/plane.h b/external/cglm/plane.h new file mode 100644 index 0000000..9efabb7 --- /dev/null +++ b/external/cglm/plane.h @@ -0,0 +1,44 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_plane_h +#define cglm_plane_h + +#include "common.h" +#include "vec3.h" +#include "vec4.h" + +/* + Plane equation: Ax + By + Cz + D = 0; + + It stored in vec4 as [A, B, C, D]. (A, B, C) is normal and D is distance +*/ + +/* + Functions: + CGLM_INLINE void glm_plane_normalize(vec4 plane); + */ + +/*! + * @brief normalizes a plane + * + * @param[in, out] plane plane to normalize + */ +CGLM_INLINE +void +glm_plane_normalize(vec4 plane) { + float norm; + + if (CGLM_UNLIKELY((norm = glm_vec3_norm(plane)) < FLT_EPSILON)) { + glm_vec4_zero(plane); + return; + } + + glm_vec4_scale(plane, 1.0f / norm, plane); +} + +#endif /* cglm_plane_h */ diff --git a/external/cglm/project.h b/external/cglm/project.h new file mode 100644 index 0000000..1d0a4e5 --- /dev/null +++ b/external/cglm/project.h @@ -0,0 +1,172 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_project_h +#define cglm_project_h + +#include "common.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" + +#ifndef CGLM_CLIPSPACE_INCLUDE_ALL +# if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT +# include "clipspace/project_zo.h" +# elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT +# include "clipspace/project_no.h" +# endif +#else +# include "clipspace/project_zo.h" +# include "clipspace/project_no.h" +#endif + +/*! + * @brief maps the specified viewport coordinates into specified space [1] + * the matrix should contain projection matrix. + * + * if you don't have ( and don't want to have ) an inverse matrix then use + * glm_unproject version. You may use existing inverse of matrix in somewhere + * else, this is why glm_unprojecti exists to save save inversion cost + * + * [1] space: + * 1- if m = invProj: View Space + * 2- if m = invViewProj: World Space + * 3- if m = invMVP: Object Space + * + * You probably want to map the coordinates into object space + * so use invMVP as m + * + * Computing viewProj: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * glm_mat4_inv(viewProj, invMVP); + * + * @param[in] pos point/position in viewport coordinates + * @param[in] invMat matrix (see brief) + * @param[in] vp viewport as [x, y, width, height] + * @param[out] dest unprojected coordinates + */ +CGLM_INLINE +void +glm_unprojecti(vec3 pos, mat4 invMat, vec4 vp, vec3 dest) { +#if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT + glm_unprojecti_zo(pos, invMat, vp, dest); +#elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT + glm_unprojecti_no(pos, invMat, vp, dest); +#endif +} + +/*! + * @brief maps the specified viewport coordinates into specified space [1] + * the matrix should contain projection matrix. + * + * this is same as glm_unprojecti except this function get inverse matrix for + * you. + * + * [1] space: + * 1- if m = proj: View Space + * 2- if m = viewProj: World Space + * 3- if m = MVP: Object Space + * + * You probably want to map the coordinates into object space + * so use MVP as m + * + * Computing viewProj and MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] pos point/position in viewport coordinates + * @param[in] m matrix (see brief) + * @param[in] vp viewport as [x, y, width, height] + * @param[out] dest unprojected coordinates + */ +CGLM_INLINE +void +glm_unproject(vec3 pos, mat4 m, vec4 vp, vec3 dest) { + mat4 inv; + glm_mat4_inv(m, inv); + glm_unprojecti(pos, inv, vp, dest); +} + +/*! + * @brief map object coordinates to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] pos object coordinates + * @param[in] m MVP matrix + * @param[in] vp viewport as [x, y, width, height] + * @param[out] dest projected coordinates + */ +CGLM_INLINE +void +glm_project(vec3 pos, mat4 m, vec4 vp, vec3 dest) { +#if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT + glm_project_zo(pos, m, vp, dest); +#elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT + glm_project_no(pos, m, vp, dest); +#endif +} + +/*! + * @brief map object's z coordinate to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] v object coordinates + * @param[in] m MVP matrix + * + * @returns projected z coordinate + */ +CGLM_INLINE +float +glm_project_z(vec3 v, mat4 m) { +#if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT + return glm_project_z_zo(v, m); +#elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT + return glm_project_z_no(v, m); +#endif +} + +/*! + * @brief define a picking region + * + * @param[in] center center [x, y] of a picking region in window coordinates + * @param[in] size size [width, height] of the picking region in window coordinates + * @param[in] vp viewport as [x, y, width, height] + * @param[out] dest projected coordinates + */ +CGLM_INLINE +void +glm_pickmatrix(vec2 center, vec2 size, vec4 vp, mat4 dest) { + mat4 res; + vec3 v; + + if (size[0] <= 0.0f || size[1] <= 0.0f) + return; + + /* Translate and scale the picked region to the entire window */ + v[0] = (vp[2] - 2.0f * (center[0] - vp[0])) / size[0]; + v[1] = (vp[3] - 2.0f * (center[1] - vp[1])) / size[1]; + v[2] = 0.0f; + + glm_translate_make(res, v); + + v[0] = vp[2] / size[0]; + v[1] = vp[3] / size[1]; + v[2] = 1.0f; + + glm_scale(res, v); + + glm_mat4_copy(res, dest); +} + +#endif /* cglm_project_h */ diff --git a/external/cglm/quat.h b/external/cglm/quat.h new file mode 100644 index 0000000..cf1f325 --- /dev/null +++ b/external/cglm/quat.h @@ -0,0 +1,949 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_QUAT_IDENTITY_INIT + GLM_QUAT_IDENTITY + + Functions: + CGLM_INLINE void glm_quat_identity(versor q); + CGLM_INLINE void glm_quat_init(versor q, float x, float y, float z, float w); + CGLM_INLINE void glm_quat(versor q, float angle, float x, float y, float z); + CGLM_INLINE void glm_quatv(versor q, float angle, vec3 axis); + CGLM_INLINE void glm_quat_copy(versor q, versor dest); + CGLM_INLINE void glm_quat_from_vecs(vec3 a, vec3 b, versor dest); + CGLM_INLINE float glm_quat_norm(versor q); + CGLM_INLINE void glm_quat_normalize(versor q); + CGLM_INLINE void glm_quat_normalize_to(versor q, versor dest); + CGLM_INLINE float glm_quat_dot(versor p, versor q); + CGLM_INLINE void glm_quat_conjugate(versor q, versor dest); + CGLM_INLINE void glm_quat_inv(versor q, versor dest); + CGLM_INLINE void glm_quat_add(versor p, versor q, versor dest); + CGLM_INLINE void glm_quat_sub(versor p, versor q, versor dest); + CGLM_INLINE float glm_quat_real(versor q); + CGLM_INLINE void glm_quat_imag(versor q, vec3 dest); + CGLM_INLINE void glm_quat_imagn(versor q, vec3 dest); + CGLM_INLINE float glm_quat_imaglen(versor q); + CGLM_INLINE float glm_quat_angle(versor q); + CGLM_INLINE void glm_quat_axis(versor q, vec3 dest); + CGLM_INLINE void glm_quat_mul(versor p, versor q, versor dest); + CGLM_INLINE void glm_quat_mat4(versor q, mat4 dest); + CGLM_INLINE void glm_quat_mat4t(versor q, mat4 dest); + CGLM_INLINE void glm_quat_mat3(versor q, mat3 dest); + CGLM_INLINE void glm_quat_mat3t(versor q, mat3 dest); + CGLM_INLINE void glm_quat_lerp(versor from, versor to, float t, versor dest); + CGLM_INLINE void glm_quat_lerpc(versor from, versor to, float t, versor dest); + CGLM_INLINE void glm_quat_slerp(versor q, versor r, float t, versor dest); + CGLM_INLINE void glm_quat_slerp_longest(versor q, versor r, float t, versor dest); + CGLM_INLINE void glm_quat_nlerp(versor q, versor r, float t, versor dest); + CGLM_INLINE void glm_quat_look(vec3 eye, versor ori, mat4 dest); + CGLM_INLINE void glm_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest); + CGLM_INLINE void glm_quat_forp(vec3 from, + vec3 to, + vec3 fwd, + vec3 up, + versor dest); + CGLM_INLINE void glm_quat_rotatev(versor q, vec3 v, vec3 dest); + CGLM_INLINE void glm_quat_rotate(mat4 m, versor q, mat4 dest); + CGLM_INLINE void glm_quat_make(float * restrict src, versor dest); + */ + +#ifndef cglm_quat_h +#define cglm_quat_h + +#include "common.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" +#include "mat3.h" +#include "affine-mat.h" +#include "affine.h" + +#ifdef CGLM_SSE_FP +# include "simd/sse2/quat.h" +#endif + +#ifdef CGLM_NEON_FP +# include "simd/neon/quat.h" +#endif + +#ifdef CGLM_SIMD_WASM +# include "simd/wasm/quat.h" +#endif + +CGLM_INLINE void glm_quat_normalize(versor q); + +/* + * IMPORTANT: + * ---------------------------------------------------------------------------- + * cglm stores quat as [x, y, z, w] since v0.3.6 + * + * it was [w, x, y, z] before v0.3.6 it has been changed to [x, y, z, w] + * with v0.3.6 version. + * ---------------------------------------------------------------------------- + */ + +#define GLM_QUAT_IDENTITY_INIT {0.0f, 0.0f, 0.0f, 1.0f} +#define GLM_QUAT_IDENTITY ((versor)GLM_QUAT_IDENTITY_INIT) + +/*! + * @brief makes given quat to identity + * + * @param[in, out] q quaternion + */ +CGLM_INLINE +void +glm_quat_identity(versor q) { + CGLM_ALIGN(16) versor v = GLM_QUAT_IDENTITY_INIT; + glm_vec4_copy(v, q); +} + +/*! + * @brief make given quaternion array's each element identity quaternion + * + * @param[in, out] q quat array (must be aligned (16) + * if alignment is not disabled) + * + * @param[in] count count of quaternions + */ +CGLM_INLINE +void +glm_quat_identity_array(versor * __restrict q, size_t count) { + CGLM_ALIGN(16) versor v = GLM_QUAT_IDENTITY_INIT; + size_t i; + + for (i = 0; i < count; i++) { + glm_vec4_copy(v, q[i]); + } +} + +/*! + * @brief inits quaternion with raw values + * + * @param[out] q quaternion + * @param[in] x x + * @param[in] y y + * @param[in] z z + * @param[in] w w (real part) + */ +CGLM_INLINE +void +glm_quat_init(versor q, float x, float y, float z, float w) { + q[0] = x; + q[1] = y; + q[2] = z; + q[3] = w; +} + +/*! + * @brief creates NEW quaternion with axis vector + * + * @param[out] q quaternion + * @param[in] angle angle (radians) + * @param[in] axis axis + */ +CGLM_INLINE +void +glm_quatv(versor q, float angle, vec3 axis) { + CGLM_ALIGN(8) vec3 k; + float a, c, s; + + a = angle * 0.5f; + c = cosf(a); + s = sinf(a); + + glm_normalize_to(axis, k); + + q[0] = s * k[0]; + q[1] = s * k[1]; + q[2] = s * k[2]; + q[3] = c; +} + +/*! + * @brief creates NEW quaternion with individual axis components + * + * @param[out] q quaternion + * @param[in] angle angle (radians) + * @param[in] x axis.x + * @param[in] y axis.y + * @param[in] z axis.z + */ +CGLM_INLINE +void +glm_quat(versor q, float angle, float x, float y, float z) { + CGLM_ALIGN(8) vec3 axis = {x, y, z}; + glm_quatv(q, angle, axis); +} + +/*! + * @brief copy quaternion to another one + * + * @param[in] q quaternion + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_quat_copy(versor q, versor dest) { + glm_vec4_copy(q, dest); +} + +/*! + * @brief compute quaternion rotating vector A to vector B + * + * @param[in] a vec3 (must have unit length) + * @param[in] b vec3 (must have unit length) + * @param[out] dest quaternion (of unit length) + */ +CGLM_INLINE +void +glm_quat_from_vecs(vec3 a, vec3 b, versor dest) { + CGLM_ALIGN(8) vec3 axis; + float cos_theta; + float cos_half_theta; + + cos_theta = glm_vec3_dot(a, b); + if (cos_theta >= 1.f - GLM_FLT_EPSILON) { /* a ∥ b */ + glm_quat_identity(dest); + return; + } + if (cos_theta < -1.f + GLM_FLT_EPSILON) { /* angle(a, b) = π */ + glm_vec3_ortho(a, axis); + cos_half_theta = 0.f; /* cos π/2 */ + } else { + glm_vec3_cross(a, b, axis); + cos_half_theta = 1.0f + cos_theta; /* cos 0 + cos θ */ + } + + glm_quat_init(dest, axis[0], axis[1], axis[2], cos_half_theta); + glm_quat_normalize(dest); +} + +/*! + * @brief returns norm (magnitude) of quaternion + * + * @param[in] q quaternion + */ +CGLM_INLINE +float +glm_quat_norm(versor q) { + return glm_vec4_norm(q); +} + +/*! + * @brief normalize quaternion and store result in dest + * + * @param[in] q quaternion to normalze + * @param[out] dest destination quaternion + */ +CGLM_INLINE +void +glm_quat_normalize_to(versor q, versor dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_128 xdot, x0; + float dot; + + x0 = glmm_load(q); + xdot = glmm_vdot(x0, x0); + /* dot = _mm_cvtss_f32(xdot); */ + dot = wasm_f32x4_extract_lane(xdot, 0); + + if (dot <= 0.0f) { + glm_quat_identity(dest); + return; + } + + glmm_store(dest, wasm_f32x4_div(x0, wasm_f32x4_sqrt(xdot))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + __m128 xdot, x0; + float dot; + + x0 = glmm_load(q); + xdot = glmm_vdot(x0, x0); + dot = _mm_cvtss_f32(xdot); + + if (dot <= 0.0f) { + glm_quat_identity(dest); + return; + } + + glmm_store(dest, _mm_div_ps(x0, _mm_sqrt_ps(xdot))); +#else + float dot; + + dot = glm_vec4_norm2(q); + + if (dot <= 0.0f) { + glm_quat_identity(dest); + return; + } + + glm_vec4_scale(q, 1.0f / sqrtf(dot), dest); +#endif +} + +/*! + * @brief normalize quaternion + * + * @param[in, out] q quaternion + */ +CGLM_INLINE +void +glm_quat_normalize(versor q) { + glm_quat_normalize_to(q, q); +} + +/*! + * @brief dot product of two quaternion + * + * @param[in] p quaternion 1 + * @param[in] q quaternion 2 + */ +CGLM_INLINE +float +glm_quat_dot(versor p, versor q) { + return glm_vec4_dot(p, q); +} + +/*! + * @brief conjugate of quaternion + * + * @param[in] q quaternion + * @param[out] dest conjugate + */ +CGLM_INLINE +void +glm_quat_conjugate(versor q, versor dest) { + glm_vec4_negate_to(q, dest); + dest[3] = -dest[3]; +} + +/*! + * @brief inverse of non-zero quaternion + * + * @param[in] q quaternion + * @param[out] dest inverse quaternion + */ +CGLM_INLINE +void +glm_quat_inv(versor q, versor dest) { + CGLM_ALIGN(16) versor conj; + glm_quat_conjugate(q, conj); + glm_vec4_scale(conj, 1.0f / glm_vec4_norm2(q), dest); +} + +/*! + * @brief add (componentwise) two quaternions and store result in dest + * + * @param[in] p quaternion 1 + * @param[in] q quaternion 2 + * @param[out] dest result quaternion + */ +CGLM_INLINE +void +glm_quat_add(versor p, versor q, versor dest) { + glm_vec4_add(p, q, dest); +} + +/*! + * @brief subtract (componentwise) two quaternions and store result in dest + * + * @param[in] p quaternion 1 + * @param[in] q quaternion 2 + * @param[out] dest result quaternion + */ +CGLM_INLINE +void +glm_quat_sub(versor p, versor q, versor dest) { + glm_vec4_sub(p, q, dest); +} + +/*! + * @brief returns real part of quaternion + * + * @param[in] q quaternion + */ +CGLM_INLINE +float +glm_quat_real(versor q) { + return q[3]; +} + +/*! + * @brief returns imaginary part of quaternion + * + * @param[in] q quaternion + * @param[out] dest imag + */ +CGLM_INLINE +void +glm_quat_imag(versor q, vec3 dest) { + dest[0] = q[0]; + dest[1] = q[1]; + dest[2] = q[2]; +} + +/*! + * @brief returns normalized imaginary part of quaternion + * + * @param[in] q quaternion + */ +CGLM_INLINE +void +glm_quat_imagn(versor q, vec3 dest) { + glm_normalize_to(q, dest); +} + +/*! + * @brief returns length of imaginary part of quaternion + * + * @param[in] q quaternion + */ +CGLM_INLINE +float +glm_quat_imaglen(versor q) { + return glm_vec3_norm(q); +} + +/*! + * @brief returns angle of quaternion + * + * @param[in] q quaternion + */ +CGLM_INLINE +float +glm_quat_angle(versor q) { + /* + sin(theta / 2) = length(x*x + y*y + z*z) + cos(theta / 2) = w + theta = 2 * atan(sin(theta / 2) / cos(theta / 2)) + */ + return 2.0f * atan2f(glm_quat_imaglen(q), glm_quat_real(q)); +} + +/*! + * @brief axis of quaternion + * + * @param[in] q quaternion + * @param[out] dest axis of quaternion + */ +CGLM_INLINE +void +glm_quat_axis(versor q, vec3 dest) { + glm_quat_imagn(q, dest); +} + +/*! + * @brief multiplies two quaternion and stores result in dest + * this is also called Hamilton Product + * + * According to WikiPedia: + * The product of two rotation quaternions [clarification needed] will be + * equivalent to the rotation q followed by the rotation p + * + * @param[in] p quaternion 1 + * @param[in] q quaternion 2 + * @param[out] dest result quaternion + */ +CGLM_INLINE +void +glm_quat_mul(versor p, versor q, versor dest) { + /* + + (a1 b2 + b1 a2 + c1 d2 − d1 c2)i + + (a1 c2 − b1 d2 + c1 a2 + d1 b2)j + + (a1 d2 + b1 c2 − c1 b2 + d1 a2)k + a1 a2 − b1 b2 − c1 c2 − d1 d2 + */ +#if defined(__wasm__) && defined(__wasm_simd128__) + glm_quat_mul_wasm(p, q, dest); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glm_quat_mul_sse2(p, q, dest); +#elif defined(CGLM_NEON_FP) + glm_quat_mul_neon(p, q, dest); +#else + dest[0] = p[3] * q[0] + p[0] * q[3] + p[1] * q[2] - p[2] * q[1]; + dest[1] = p[3] * q[1] - p[0] * q[2] + p[1] * q[3] + p[2] * q[0]; + dest[2] = p[3] * q[2] + p[0] * q[1] - p[1] * q[0] + p[2] * q[3]; + dest[3] = p[3] * q[3] - p[0] * q[0] - p[1] * q[1] - p[2] * q[2]; +#endif +} + +/*! + * @brief convert quaternion to mat4 + * + * @param[in] q quaternion + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_quat_mat4(versor q, mat4 dest) { + float w, x, y, z, + xx, yy, zz, + xy, yz, xz, + wx, wy, wz, norm, s; + + norm = glm_quat_norm(q); + s = norm > 0.0f ? 2.0f / norm : 0.0f; + + x = q[0]; + y = q[1]; + z = q[2]; + w = q[3]; + + xx = s * x * x; xy = s * x * y; wx = s * w * x; + yy = s * y * y; yz = s * y * z; wy = s * w * y; + zz = s * z * z; xz = s * x * z; wz = s * w * z; + + dest[0][0] = 1.0f - yy - zz; + dest[1][1] = 1.0f - xx - zz; + dest[2][2] = 1.0f - xx - yy; + + dest[0][1] = xy + wz; + dest[1][2] = yz + wx; + dest[2][0] = xz + wy; + + dest[1][0] = xy - wz; + dest[2][1] = yz - wx; + dest[0][2] = xz - wy; + + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; +} + +/*! + * @brief convert quaternion to mat4 (transposed) + * + * @param[in] q quaternion + * @param[out] dest result matrix as transposed + */ +CGLM_INLINE +void +glm_quat_mat4t(versor q, mat4 dest) { + float w, x, y, z, + xx, yy, zz, + xy, yz, xz, + wx, wy, wz, norm, s; + + norm = glm_quat_norm(q); + s = norm > 0.0f ? 2.0f / norm : 0.0f; + + x = q[0]; + y = q[1]; + z = q[2]; + w = q[3]; + + xx = s * x * x; xy = s * x * y; wx = s * w * x; + yy = s * y * y; yz = s * y * z; wy = s * w * y; + zz = s * z * z; xz = s * x * z; wz = s * w * z; + + dest[0][0] = 1.0f - yy - zz; + dest[1][1] = 1.0f - xx - zz; + dest[2][2] = 1.0f - xx - yy; + + dest[1][0] = xy + wz; + dest[2][1] = yz + wx; + dest[0][2] = xz + wy; + + dest[0][1] = xy - wz; + dest[1][2] = yz - wx; + dest[2][0] = xz - wy; + + dest[0][3] = 0.0f; + dest[1][3] = 0.0f; + dest[2][3] = 0.0f; + dest[3][0] = 0.0f; + dest[3][1] = 0.0f; + dest[3][2] = 0.0f; + dest[3][3] = 1.0f; +} + +/*! + * @brief convert quaternion to mat3 + * + * @param[in] q quaternion + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_quat_mat3(versor q, mat3 dest) { + float w, x, y, z, + xx, yy, zz, + xy, yz, xz, + wx, wy, wz, norm, s; + + norm = glm_quat_norm(q); + s = norm > 0.0f ? 2.0f / norm : 0.0f; + + x = q[0]; + y = q[1]; + z = q[2]; + w = q[3]; + + xx = s * x * x; xy = s * x * y; wx = s * w * x; + yy = s * y * y; yz = s * y * z; wy = s * w * y; + zz = s * z * z; xz = s * x * z; wz = s * w * z; + + dest[0][0] = 1.0f - yy - zz; + dest[1][1] = 1.0f - xx - zz; + dest[2][2] = 1.0f - xx - yy; + + dest[0][1] = xy + wz; + dest[1][2] = yz + wx; + dest[2][0] = xz + wy; + + dest[1][0] = xy - wz; + dest[2][1] = yz - wx; + dest[0][2] = xz - wy; +} + +/*! + * @brief convert quaternion to mat3 (transposed) + * + * @param[in] q quaternion + * @param[out] dest result matrix + */ +CGLM_INLINE +void +glm_quat_mat3t(versor q, mat3 dest) { + float w, x, y, z, + xx, yy, zz, + xy, yz, xz, + wx, wy, wz, norm, s; + + norm = glm_quat_norm(q); + s = norm > 0.0f ? 2.0f / norm : 0.0f; + + x = q[0]; + y = q[1]; + z = q[2]; + w = q[3]; + + xx = s * x * x; xy = s * x * y; wx = s * w * x; + yy = s * y * y; yz = s * y * z; wy = s * w * y; + zz = s * z * z; xz = s * x * z; wz = s * w * z; + + dest[0][0] = 1.0f - yy - zz; + dest[1][1] = 1.0f - xx - zz; + dest[2][2] = 1.0f - xx - yy; + + dest[1][0] = xy + wz; + dest[2][1] = yz + wx; + dest[0][2] = xz + wy; + + dest[0][1] = xy - wz; + dest[1][2] = yz - wx; + dest[2][0] = xz - wy; +} + +/*! + * @brief interpolates between two quaternions + * using linear interpolation (LERP) + * + * @param[in] from from + * @param[in] to to + * @param[in] t interpolant (amount) + * @param[out] dest result quaternion + */ +CGLM_INLINE +void +glm_quat_lerp(versor from, versor to, float t, versor dest) { + glm_vec4_lerp(from, to, t, dest); +} + +/*! + * @brief interpolates between two quaternions + * using linear interpolation (LERP) + * + * @param[in] from from + * @param[in] to to + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest result quaternion + */ +CGLM_INLINE +void +glm_quat_lerpc(versor from, versor to, float t, versor dest) { + glm_vec4_lerpc(from, to, t, dest); +} + +/*! + * @brief interpolates between two quaternions + * taking the shortest rotation path using + * normalized linear interpolation (NLERP) + * + * @param[in] from from + * @param[in] to to + * @param[in] t interpolant (amount) + * @param[out] dest result quaternion + */ +CGLM_INLINE +void +glm_quat_nlerp(versor from, versor to, float t, versor dest) { + versor target; + float dot; + + dot = glm_vec4_dot(from, to); + + glm_vec4_scale(to, (dot >= 0) ? 1.0f : -1.0f, target); + glm_quat_lerp(from, target, t, dest); + glm_quat_normalize(dest); +} + +/*! + * @brief interpolates between two quaternions + * using spherical linear interpolation (SLERP) + * + * @param[in] from from + * @param[in] to to + * @param[in] t amount + * @param[out] dest result quaternion + */ +CGLM_INLINE +void +glm_quat_slerp(versor from, versor to, float t, versor dest) { + CGLM_ALIGN(16) vec4 q1, q2; + float cosTheta, sinTheta, angle; + + cosTheta = glm_quat_dot(from, to); + glm_quat_copy(from, q1); + + if (fabsf(cosTheta) >= 1.0f) { + glm_quat_copy(q1, dest); + return; + } + + if (cosTheta < 0.0f) { + glm_vec4_negate(q1); + cosTheta = -cosTheta; + } + + sinTheta = sqrtf(1.0f - cosTheta * cosTheta); + + /* LERP to avoid zero division */ + if (fabsf(sinTheta) < 0.001f) { + glm_quat_lerp(from, to, t, dest); + return; + } + + /* SLERP */ + angle = acosf(cosTheta); + glm_vec4_scale(q1, sinf((1.0f - t) * angle), q1); + glm_vec4_scale(to, sinf(t * angle), q2); + + glm_vec4_add(q1, q2, q1); + glm_vec4_scale(q1, 1.0f / sinTheta, dest); +} + +/*! + * @brief interpolates between two quaternions + * using spherical linear interpolation (SLERP) and always takes the long path + * + * @param[in] from from + * @param[in] to to + * @param[in] t amount + * @param[out] dest result quaternion + */ +CGLM_INLINE +void +glm_quat_slerp_longest(versor from, versor to, float t, versor dest) { + CGLM_ALIGN(16) vec4 q1, q2; + float cosTheta, sinTheta, angle; + + cosTheta = glm_quat_dot(from, to); + glm_quat_copy(from, q1); + + if (fabsf(cosTheta) >= 1.0f) { + glm_quat_copy(q1, dest); + return; + } + + /* longest path */ + if (!(cosTheta < 0.0f)) { + glm_vec4_negate(q1); + cosTheta = -cosTheta; + } + + sinTheta = sqrtf(1.0f - cosTheta * cosTheta); + + /* LERP to avoid zero division */ + if (fabsf(sinTheta) < 0.001f) { + glm_quat_lerp(from, to, t, dest); + return; + } + + /* SLERP */ + angle = acosf(cosTheta); + glm_vec4_scale(q1, sinf((1.0f - t) * angle), q1); + glm_vec4_scale(to, sinf(t * angle), q2); + + glm_vec4_add(q1, q2, q1); + glm_vec4_scale(q1, 1.0f / sinTheta, dest); +} + +/*! + * @brief creates view matrix using quaternion as camera orientation + * + * @param[in] eye eye + * @param[in] ori orientation in world space as quaternion + * @param[out] dest view matrix + */ +CGLM_INLINE +void +glm_quat_look(vec3 eye, versor ori, mat4 dest) { + /* orientation */ + glm_quat_mat4t(ori, dest); + + /* translate */ + glm_mat4_mulv3(dest, eye, 1.0f, dest[3]); + glm_vec3_negate(dest[3]); +} + +/*! + * @brief creates look rotation quaternion + * + * @param[in] dir direction to look + * @param[in] up up vector + * @param[out] dest destination quaternion + */ +CGLM_INLINE +void +glm_quat_for(vec3 dir, vec3 up, versor dest) { + CGLM_ALIGN_MAT mat3 m; + + glm_vec3_normalize_to(dir, m[2]); + + /* No need to negate in LH, but we use RH here */ + glm_vec3_negate(m[2]); + + glm_vec3_crossn(up, m[2], m[0]); + glm_vec3_cross(m[2], m[0], m[1]); + + glm_mat3_quat(m, dest); +} + +/*! + * @brief creates look rotation quaternion using source and + * destination positions p suffix stands for position + * + * @param[in] from source point + * @param[in] to destination point + * @param[in] up up vector + * @param[out] dest destination quaternion + */ +CGLM_INLINE +void +glm_quat_forp(vec3 from, vec3 to, vec3 up, versor dest) { + CGLM_ALIGN(8) vec3 dir; + glm_vec3_sub(to, from, dir); + glm_quat_for(dir, up, dest); +} + +/*! + * @brief rotate vector using using quaternion + * + * @param[in] q quaternion + * @param[in] v vector to rotate + * @param[out] dest rotated vector + */ +CGLM_INLINE +void +glm_quat_rotatev(versor q, vec3 v, vec3 dest) { + CGLM_ALIGN(16) versor p; + CGLM_ALIGN(8) vec3 u, v1, v2; + float s; + + glm_quat_normalize_to(q, p); + glm_quat_imag(p, u); + s = glm_quat_real(p); + + glm_vec3_scale(u, 2.0f * glm_vec3_dot(u, v), v1); + glm_vec3_scale(v, s * s - glm_vec3_dot(u, u), v2); + glm_vec3_add(v1, v2, v1); + + glm_vec3_cross(u, v, v2); + glm_vec3_scale(v2, 2.0f * s, v2); + + glm_vec3_add(v1, v2, dest); +} + +/*! + * @brief rotate existing transform matrix using quaternion + * + * @param[in] m existing transform matrix + * @param[in] q quaternion + * @param[out] dest rotated matrix/transform + */ +CGLM_INLINE +void +glm_quat_rotate(mat4 m, versor q, mat4 dest) { + CGLM_ALIGN_MAT mat4 rot; + glm_quat_mat4(q, rot); + glm_mul_rot(m, rot, dest); +} + +/*! + * @brief rotate existing transform matrix using quaternion at pivot point + * + * @param[in, out] m existing transform matrix + * @param[in] q quaternion + * @param[out] pivot pivot + */ +CGLM_INLINE +void +glm_quat_rotate_at(mat4 m, versor q, vec3 pivot) { + CGLM_ALIGN(8) vec3 pivotInv; + + glm_vec3_negate_to(pivot, pivotInv); + + glm_translate(m, pivot); + glm_quat_rotate(m, q, m); + glm_translate(m, pivotInv); +} + +/*! + * @brief rotate NEW transform matrix using quaternion at pivot point + * + * this creates rotation matrix, it assumes you don't have a matrix + * + * this should work faster than glm_quat_rotate_at because it reduces + * one glm_translate. + * + * @param[out] m existing transform matrix + * @param[in] q quaternion + * @param[in] pivot pivot + */ +CGLM_INLINE +void +glm_quat_rotate_atm(mat4 m, versor q, vec3 pivot) { + CGLM_ALIGN(8) vec3 pivotInv; + + glm_vec3_negate_to(pivot, pivotInv); + + glm_translate_make(m, pivot); + glm_quat_rotate(m, q, m); + glm_translate(m, pivotInv); +} + +/*! + * @brief Create quaternion from pointer + * + * @param[in] src pointer to an array of floats + * @param[out] dest quaternion + */ +CGLM_INLINE +void +glm_quat_make(const float * __restrict src, versor dest) { + dest[0] = src[0]; dest[1] = src[1]; + dest[2] = src[2]; dest[3] = src[3]; +} + +#endif /* cglm_quat_h */ diff --git a/external/cglm/ray.h b/external/cglm/ray.h new file mode 100644 index 0000000..d7831bc --- /dev/null +++ b/external/cglm/ray.h @@ -0,0 +1,174 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE bool glm_ray_triangle(vec3 origin, + vec3 direction, + vec3 v0, + vec3 v1, + vec3 v2, + float *d); + CGLM_INLINE bool glm_ray_sphere(vec3 origin, + vec3 dir, + vec4 s, + float * __restrict t1, + float * __restrict t2) + CGLM_INLINE void glm_ray_at(vec3 orig, vec3 dir, float t, vec3 point); +*/ + +#ifndef cglm_ray_h +#define cglm_ray_h + +#include "vec3.h" + +/*! + * @brief Möller–Trumbore ray-triangle intersection algorithm + * + * @param[in] origin origin of ray + * @param[in] direction direction of ray + * @param[in] v0 first vertex of triangle + * @param[in] v1 second vertex of triangle + * @param[in] v2 third vertex of triangle + * @param[in, out] d distance to intersection + * @return whether there is intersection + */ +CGLM_INLINE +bool +glm_ray_triangle(vec3 origin, + vec3 direction, + vec3 v0, + vec3 v1, + vec3 v2, + float *d) { + vec3 edge1, edge2, p, t, q; + float det, inv_det, u, v, dist; + const float epsilon = 0.000001f; + + glm_vec3_sub(v1, v0, edge1); + glm_vec3_sub(v2, v0, edge2); + glm_vec3_cross(direction, edge2, p); + + det = glm_vec3_dot(edge1, p); + if (det > -epsilon && det < epsilon) + return false; + + inv_det = 1.0f / det; + + glm_vec3_sub(origin, v0, t); + + u = inv_det * glm_vec3_dot(t, p); + if (u < 0.0f || u > 1.0f) + return false; + + glm_vec3_cross(t, edge1, q); + + v = inv_det * glm_vec3_dot(direction, q); + if (v < 0.0f || u + v > 1.0f) + return false; + + dist = inv_det * glm_vec3_dot(edge2, q); + + if (d) + *d = dist; + + return dist > epsilon; +} + +/*! + * @brief ray sphere intersection + * + * returns false if there is no intersection if true: + * + * - t1 > 0, t2 > 0: ray intersects the sphere at t1 and t2 both ahead of the origin + * - t1 < 0, t2 > 0: ray starts inside the sphere, exits at t2 + * - t1 < 0, t2 < 0: no intersection ahead of the ray ( returns false ) + * - the caller can check if the intersection points (t1 and t2) fall within a + * specific range (for example, tmin < t1, t2 < tmax) to determine if the + * intersections are within a desired segment of the ray + * + * @param[in] origin ray origin + * @param[out] dir normalized ray direction + * @param[in] s sphere [center.x, center.y, center.z, radii] + * @param[in] t1 near point1 (closer to origin) + * @param[in] t2 far point2 (farther from origin) + * + * @returns whether there is intersection + */ +CGLM_INLINE +bool +glm_ray_sphere(vec3 origin, + vec3 dir, + vec4 s, + float * __restrict t1, + float * __restrict t2) { + vec3 dp; + float r2, ddp, dpp, dscr, q, tmp, _t1, _t2; + + glm_vec3_sub(s, origin, dp); + + ddp = glm_vec3_dot(dir, dp); + dpp = glm_vec3_norm2(dp); + + /* compute the remedy term for numerical stability */ + glm_vec3_mulsubs(dir, ddp, dp); /* dp: remedy term */ + + r2 = s[3] * s[3]; + dscr = r2 - glm_vec3_norm2(dp); + + if (dscr < 0.0f) { + /* no intersection */ + return false; + } + + dscr = sqrtf(dscr); + q = (ddp >= 0.0f) ? (ddp + dscr) : (ddp - dscr); + + /* + include Press, William H., Saul A. Teukolsky, + William T. Vetterling, and Brian P. Flannery, + "Numerical Recipes in C," Cambridge University Press, 1992. + */ + _t1 = q; + _t2 = (dpp - r2) / q; + + /* adjust t1 and t2 to ensure t1 is the closer intersection */ + if (_t1 > _t2) { + tmp = _t1; + _t1 = _t2; + _t2 = tmp; + } + + *t1 = _t1; + *t2 = _t2; + + /* check if the closest intersection (t1) is behind the ray's origin */ + if (_t1 < 0.0f && _t2 < 0.0f) { + /* both intersections are behind the ray, no visible intersection */ + return false; + } + + return true; +} + +/*! + * @brief point using t by 𝐏(𝑡)=𝐀+𝑡𝐛 + * + * @param[in] orig origin of ray + * @param[in] dir direction of ray + * @param[in] t parameter + * @param[out] point point at t + */ +CGLM_INLINE +void +glm_ray_at(vec3 orig, vec3 dir, float t, vec3 point) { + vec3 dst; + glm_vec3_scale(dir, t, dst); + glm_vec3_add(orig, dst, point); +} + +#endif diff --git a/external/cglm/simd/arm.h b/external/cglm/simd/arm.h new file mode 100644 index 0000000..9f51742 --- /dev/null +++ b/external/cglm/simd/arm.h @@ -0,0 +1,206 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_simd_arm_h +#define cglm_simd_arm_h +#include "intrin.h" +#ifdef CGLM_SIMD_ARM + +#if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || defined(__aarch64__) +# define CGLM_ARM64 1 +#else +# define CGLM_ARM64 0 +#endif + +#define glmm_load(p) vld1q_f32(p) +#define glmm_store(p, a) vst1q_f32(p, a) + +#define glmm_set1(x) vdupq_n_f32(x) +#define glmm_set1_ptr(x) vdupq_n_f32(*x) +#define glmm_set1_rval(x) vdupq_n_f32(x) +#define glmm_128 float32x4_t + +#define glmm_splat_x(x) vdupq_lane_f32(vget_low_f32(x), 0) +#define glmm_splat_y(x) vdupq_lane_f32(vget_low_f32(x), 1) +#define glmm_splat_z(x) vdupq_lane_f32(vget_high_f32(x), 0) +#define glmm_splat_w(x) vdupq_lane_f32(vget_high_f32(x), 1) + +#define glmm_xor(a, b) \ + vreinterpretq_f32_s32(veorq_s32(vreinterpretq_s32_f32(a), \ + vreinterpretq_s32_f32(b))) + +#define glmm_swplane(v) vextq_f32(v, v, 2) +#define glmm_low(x) vget_low_f32(x) +#define glmm_high(x) vget_high_f32(x) + +#define glmm_combine_ll(x, y) vcombine_f32(vget_low_f32(x), vget_low_f32(y)) +#define glmm_combine_hl(x, y) vcombine_f32(vget_high_f32(x), vget_low_f32(y)) +#define glmm_combine_lh(x, y) vcombine_f32(vget_low_f32(x), vget_high_f32(y)) +#define glmm_combine_hh(x, y) vcombine_f32(vget_high_f32(x), vget_high_f32(y)) + +#if defined(_WIN32) && defined(_MSC_VER) +/* # define glmm_float32x4_init(x, y, z, w) { .n128_f32 = { x, y, z, w } } */ +CGLM_INLINE +float32x4_t +glmm_float32x4_init(float x, float y, float z, float w) { + CGLM_ALIGN(16) float v[4] = {x, y, z, w}; + return vld1q_f32(v); +} +#else +# define glmm_float32x4_init(x, y, z, w) { x, y, z, w } +#endif + +#define glmm_float32x4_SIGNMASK_PNPN glmm_float32x4_init( 0.f, -0.f, 0.f, -0.f) +#define glmm_float32x4_SIGNMASK_NPNP glmm_float32x4_init(-0.f, 0.f, -0.f, 0.f) +#define glmm_float32x4_SIGNMASK_NPPN glmm_float32x4_init(-0.f, 0.f, 0.f, -0.f) + +static inline float32x4_t glmm_abs(float32x4_t v) { return vabsq_f32(v); } +static inline float32x4_t glmm_min(float32x4_t a, float32x4_t b) { return vminq_f32(a, b); } +static inline float32x4_t glmm_max(float32x4_t a, float32x4_t b) { return vmaxq_f32(a, b); } + +static inline +float32x4_t +glmm_vhadd(float32x4_t v) { +#if CGLM_ARM64 + float32x4_t p; + p = vpaddq_f32(v, v); /* [a+b, c+d, a+b, c+d] */ + return vpaddq_f32(p, p); /* [t, t, t, t] */; +#else + return vaddq_f32(vaddq_f32(glmm_splat_x(v), glmm_splat_y(v)), + vaddq_f32(glmm_splat_z(v), glmm_splat_w(v))); +#endif + /* TODO: measure speed of this compare to above */ + /* return vdupq_n_f32(vaddvq_f32(v)); */ + + /* + return vaddq_f32(vaddq_f32(glmm_splat_x(v), glmm_splat_y(v)), + vaddq_f32(glmm_splat_z(v), glmm_splat_w(v))); + */ + /* + this seems slower: + v = vaddq_f32(v, vrev64q_f32(v)); + return vaddq_f32(v, vcombine_f32(vget_high_f32(v), vget_low_f32(v))); + */ +} + +static inline +float +glmm_hadd(float32x4_t v) { +#if CGLM_ARM64 + return vaddvq_f32(v); +#else + v = vaddq_f32(v, vrev64q_f32(v)); + v = vaddq_f32(v, vcombine_f32(vget_high_f32(v), vget_low_f32(v))); + return vgetq_lane_f32(v, 0); +#endif +} + +static inline +float +glmm_hmin(float32x4_t v) { + float32x2_t t; + t = vpmin_f32(vget_low_f32(v), vget_high_f32(v)); + t = vpmin_f32(t, t); + return vget_lane_f32(t, 0); +} + +static inline +float +glmm_hmax(float32x4_t v) { + float32x2_t t; + t = vpmax_f32(vget_low_f32(v), vget_high_f32(v)); + t = vpmax_f32(t, t); + return vget_lane_f32(t, 0); +} + +static inline +float +glmm_dot(float32x4_t a, float32x4_t b) { + return glmm_hadd(vmulq_f32(a, b)); +} + +static inline +float32x4_t +glmm_vdot(float32x4_t a, float32x4_t b) { + return glmm_vhadd(vmulq_f32(a, b)); +} + +static inline +float +glmm_norm(float32x4_t a) { + return sqrtf(glmm_dot(a, a)); +} + +static inline +float +glmm_norm2(float32x4_t a) { + return glmm_dot(a, a); +} + +static inline +float +glmm_norm_one(float32x4_t a) { + return glmm_hadd(glmm_abs(a)); +} + +static inline +float +glmm_norm_inf(float32x4_t a) { + return glmm_hmax(glmm_abs(a)); +} + +static inline +float32x4_t +glmm_div(float32x4_t a, float32x4_t b) { +#if CGLM_ARM64 + return vdivq_f32(a, b); +#else + /* 2 iterations of Newton-Raphson refinement of reciprocal */ + float32x4_t r0, r1; + r0 = vrecpeq_f32(b); + r1 = vrecpsq_f32(r0, b); + r0 = vmulq_f32(r1, r0); + r1 = vrecpsq_f32(r0, b); + r0 = vmulq_f32(r1, r0); + return vmulq_f32(a, r0); +#endif +} + +static inline +float32x4_t +glmm_fmadd(float32x4_t a, float32x4_t b, float32x4_t c) { +#if CGLM_ARM64 + return vfmaq_f32(c, a, b); /* why vfmaq_f32 is slower than vmlaq_f32 ??? */ +#else + return vmlaq_f32(c, a, b); +#endif +} + +static inline +float32x4_t +glmm_fnmadd(float32x4_t a, float32x4_t b, float32x4_t c) { +#if CGLM_ARM64 + return vfmsq_f32(c, a, b); +#else + return vmlsq_f32(c, a, b); +#endif +} + +static inline +float32x4_t +glmm_fmsub(float32x4_t a, float32x4_t b, float32x4_t c) { + return glmm_fmadd(a, b, vnegq_f32(c)); +} + +static inline +float32x4_t +glmm_fnmsub(float32x4_t a, float32x4_t b, float32x4_t c) { + return vsubq_f32(vdupq_n_f32(0.0f), glmm_fmadd(a, b, c)); +} + +#endif +#endif /* cglm_simd_arm_h */ diff --git a/external/cglm/simd/avx/affine.h b/external/cglm/simd/avx/affine.h new file mode 100644 index 0000000..b02ff0c --- /dev/null +++ b/external/cglm/simd/avx/affine.h @@ -0,0 +1,66 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_affine_mat_avx_h +#define cglm_affine_mat_avx_h +#ifdef __AVX__ + +#include "../../common.h" +#include "../intrin.h" + +#include + +CGLM_INLINE +void +glm_mul_avx(mat4 m1, mat4 m2, mat4 dest) { + /* D = R * L (Column-Major) */ + + __m256 y0, y1, y2, y3, y4, y5, y6, y7, y8, y9; + + y0 = glmm_load256(m2[0]); /* h g f e d c b a */ + y1 = glmm_load256(m2[2]); /* p o n m l k j i */ + + y2 = glmm_load256(m1[0]); /* h g f e d c b a */ + y3 = glmm_load256(m1[2]); /* p o n m l k j i */ + + /* 0x03: 0b00000011 */ + y4 = _mm256_permute2f128_ps(y2, y2, 0x03); /* d c b a h g f e */ + y5 = _mm256_permute2f128_ps(y3, y3, 0x03); /* l k j i p o n m */ + + /* f f f f a a a a */ + /* h h h h c c c c */ + /* e e e e b b b b */ + /* g g g g d d d d */ + y6 = _mm256_permutevar_ps(y0, _mm256_set_epi32(1, 1, 1, 1, 0, 0, 0, 0)); + y7 = _mm256_permutevar_ps(y0, _mm256_set_epi32(3, 3, 3, 3, 2, 2, 2, 2)); + y8 = _mm256_permutevar_ps(y0, _mm256_set_epi32(0, 0, 0, 0, 1, 1, 1, 1)); + y9 = _mm256_permutevar_ps(y0, _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3)); + + glmm_store256(dest[0], + _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6), + _mm256_mul_ps(y3, y7)), + _mm256_add_ps(_mm256_mul_ps(y4, y8), + _mm256_mul_ps(y5, y9)))); + + /* n n n n i i i i */ + /* p p p p k k k k */ + /* m m m m j j j j */ + /* o o o o l l l l */ + y6 = _mm256_permutevar_ps(y1, _mm256_set_epi32(1, 1, 1, 1, 0, 0, 0, 0)); + y7 = _mm256_permutevar_ps(y1, _mm256_set_epi32(3, 3, 3, 3, 2, 2, 2, 2)); + y8 = _mm256_permutevar_ps(y1, _mm256_set_epi32(0, 0, 0, 0, 1, 1, 1, 1)); + y9 = _mm256_permutevar_ps(y1, _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3)); + + glmm_store256(dest[2], + _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(y2, y6), + _mm256_mul_ps(y3, y7)), + _mm256_add_ps(_mm256_mul_ps(y4, y8), + _mm256_mul_ps(y5, y9)))); +} + +#endif +#endif /* cglm_affine_mat_avx_h */ diff --git a/external/cglm/simd/avx/mat4.h b/external/cglm/simd/avx/mat4.h new file mode 100644 index 0000000..33771c2 --- /dev/null +++ b/external/cglm/simd/avx/mat4.h @@ -0,0 +1,115 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_mat_simd_avx_h +#define cglm_mat_simd_avx_h +#ifdef __AVX__ + +#include "../../common.h" +#include "../intrin.h" + +CGLM_INLINE +void +glm_mat4_scale_avx(mat4 m, float s) { + __m256 y0, y1, y2, y3, y4; + + y0 = glmm_load256(m[0]); /* h g f e d c b a */ + y1 = glmm_load256(m[2]); /* p o n m l k j i */ + + y2 = _mm256_broadcast_ss(&s); + + y3 = _mm256_mul_ps(y0, y2); + y4 = _mm256_mul_ps(y1, y2); + + glmm_store256(m[0], y3); + glmm_store256(m[2], y4); +} + +/* TODO: this must be tested and compared to SSE version, may be slower!!! */ +CGLM_INLINE +void +glm_mat4_transp_avx(mat4 m, mat4 dest) { + __m256 y0, y1, y2, y3; + + y0 = glmm_load256(m[0]); /* h g f e d c b a */ + y1 = glmm_load256(m[2]); /* p o n m l k j i */ + + y2 = _mm256_unpacklo_ps(y0, y1); /* n f m e j b i a */ + y3 = _mm256_unpackhi_ps(y0, y1); /* p h o g l d k c */ + + y0 = _mm256_permute2f128_ps(y2, y3, 0x20); /* l d k c j b i a */ + y1 = _mm256_permute2f128_ps(y2, y3, 0x31); /* p h o g n f m e */ + + y2 = _mm256_unpacklo_ps(y0, y1); /* o k g c m i e a */ + y3 = _mm256_unpackhi_ps(y0, y1); /* p l h d n j f b */ + + y0 = _mm256_permute2f128_ps(y2, y3, 0x20); /* n j f b m i e a */ + y1 = _mm256_permute2f128_ps(y2, y3, 0x31); /* p l h d o k g c */ + + glmm_store256(dest[0], y0); + glmm_store256(dest[2], y1); +} + +CGLM_INLINE +void +glm_mat4_mul_avx(mat4 m1, mat4 m2, mat4 dest) { + /* D = R * L (Column-Major) */ + + __m256 y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13; + __m256i yi0, yi1, yi2, yi3; + + y0 = glmm_load256(m2[0]); /* h g f e d c b a */ + y1 = glmm_load256(m2[2]); /* p o n m l k j i */ + + y2 = glmm_load256(m1[0]); /* h g f e d c b a */ + y3 = glmm_load256(m1[2]); /* p o n m l k j i */ + + /* 0x03: 0b00000011 */ + y4 = _mm256_permute2f128_ps(y2, y2, 0x03); /* d c b a h g f e */ + y5 = _mm256_permute2f128_ps(y3, y3, 0x03); /* l k j i p o n m */ + + yi0 = _mm256_set_epi32(1, 1, 1, 1, 0, 0, 0, 0); + yi1 = _mm256_set_epi32(3, 3, 3, 3, 2, 2, 2, 2); + yi2 = _mm256_set_epi32(0, 0, 0, 0, 1, 1, 1, 1); + yi3 = _mm256_set_epi32(2, 2, 2, 2, 3, 3, 3, 3); + + /* f f f f a a a a */ + /* h h h h c c c c */ + /* e e e e b b b b */ + /* g g g g d d d d */ + y6 = _mm256_permutevar_ps(y0, yi0); + y7 = _mm256_permutevar_ps(y0, yi1); + y8 = _mm256_permutevar_ps(y0, yi2); + y9 = _mm256_permutevar_ps(y0, yi3); + + /* n n n n i i i i */ + /* p p p p k k k k */ + /* m m m m j j j j */ + /* o o o o l l l l */ + y10 = _mm256_permutevar_ps(y1, yi0); + y11 = _mm256_permutevar_ps(y1, yi1); + y12 = _mm256_permutevar_ps(y1, yi2); + y13 = _mm256_permutevar_ps(y1, yi3); + + y0 = _mm256_mul_ps(y2, y6); + y1 = _mm256_mul_ps(y2, y10); + + y0 = glmm256_fmadd(y3, y7, y0); + y1 = glmm256_fmadd(y3, y11, y1); + + y0 = glmm256_fmadd(y4, y8, y0); + y1 = glmm256_fmadd(y4, y12, y1); + + y0 = glmm256_fmadd(y5, y9, y0); + y1 = glmm256_fmadd(y5, y13, y1); + + glmm_store256(dest[0], y0); + glmm_store256(dest[2], y1); +} + +#endif +#endif /* cglm_mat_simd_avx_h */ diff --git a/external/cglm/simd/intrin.h b/external/cglm/simd/intrin.h new file mode 100644 index 0000000..c477f34 --- /dev/null +++ b/external/cglm/simd/intrin.h @@ -0,0 +1,153 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_intrin_h +#define cglm_intrin_h + +#if defined(_MSC_VER) && !defined(_M_ARM64EC) +# if (defined(_M_AMD64) || defined(_M_X64)) || _M_IX86_FP == 2 +# ifndef __SSE__ +# define __SSE__ +# endif +# ifndef __SSE2__ +# define __SSE2__ +# endif +# elif _M_IX86_FP == 1 +# ifndef __SSE__ +# define __SSE__ +# endif +# endif +/* do not use alignment for older visual studio versions */ +/* also ARM32 also causes similar error, disable it for now on ARM32 too */ +# if _MSC_VER < 1913 || _M_ARM /* Visual Studio 2017 version 15.6 */ +# define CGLM_ALL_UNALIGNED +# endif +#endif + +#ifdef __AVX__ +# include +# define CGLM_AVX_FP 1 +# ifndef __SSE2__ +# define __SSE2__ +# endif +# ifndef __SSE3__ +# define __SSE3__ +# endif +# ifndef __SSE4__ +# define __SSE4__ +# endif +# ifndef __SSE4_1__ +# define __SSE4_1__ +# endif +# ifndef __SSE4_2__ +# define __SSE4_2__ +# endif +# ifndef CGLM_SIMD_x86 +# define CGLM_SIMD_x86 +# endif +#endif + +#if defined(__SSE__) +# include +# define CGLM_SSE_FP 1 +# ifndef CGLM_SIMD_x86 +# define CGLM_SIMD_x86 +# endif +#endif + +#if defined(__SSE2__) +# include +# define CGLM_SSE2_FP 1 +# ifndef CGLM_SIMD_x86 +# define CGLM_SIMD_x86 +# endif +#endif + +#if defined(__SSE3__) +# include +# ifndef CGLM_SIMD_x86 +# define CGLM_SIMD_x86 +# endif +#endif + +#if defined(__SSE4_1__) +# include +# ifndef CGLM_SIMD_x86 +# define CGLM_SIMD_x86 +# endif +#endif + +#if defined(__SSE4_2__) +# include +# ifndef CGLM_SIMD_x86 +# define CGLM_SIMD_x86 +# endif +#endif + +/* ARM Neon */ +#if defined(_WIN32) && defined(_MSC_VER) +/* TODO: non-ARM stuff already inported, will this be better option */ +/* # include */ + +# if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) +# include +# include +# ifndef CGLM_NEON_FP +# define CGLM_NEON_FP 1 +# endif +# ifndef CGLM_SIMD_ARM +# define CGLM_SIMD_ARM +# endif +# elif defined(_M_ARM) +# include +# include +# ifndef CGLM_NEON_FP +# define CGLM_NEON_FP 1 +# endif +# ifndef CGLM_SIMD_ARM +# define CGLM_SIMD_ARM +# endif +# endif + +#else /* non-windows */ +# if defined(__ARM_NEON) || defined(__ARM_NEON__) +# include +# if defined(__ARM_NEON_FP) || defined(__ARM_FP) +# define CGLM_NEON_FP 1 +# endif +# ifndef CGLM_SIMD_ARM +# define CGLM_SIMD_ARM +# endif +# endif +#endif + +/* WebAssembly */ +#if defined(__wasm__) && defined(__wasm_simd128__) +# ifndef CGLM_SIMD_WASM +# define CGLM_SIMD_WASM +# endif +#endif + +#if defined(CGLM_SIMD_x86) || defined(CGLM_SIMD_ARM) || defined(CGLM_SIMD_WASM) +# ifndef CGLM_SIMD +# define CGLM_SIMD +# endif +#endif + +#if defined(CGLM_SIMD_x86) && !defined(CGLM_SIMD_WASM) +# include "x86.h" +#endif + +#if defined(CGLM_SIMD_ARM) +# include "arm.h" +#endif + +#if defined(CGLM_SIMD_WASM) +# include "wasm.h" +#endif + +#endif /* cglm_intrin_h */ diff --git a/external/cglm/simd/neon/affine.h b/external/cglm/simd/neon/affine.h new file mode 100644 index 0000000..b0a65a6 --- /dev/null +++ b/external/cglm/simd/neon/affine.h @@ -0,0 +1,121 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_affine_neon_h +#define cglm_affine_neon_h +#if defined(CGLM_NEON_FP) + +#include "../../common.h" +#include "../intrin.h" + +CGLM_INLINE +void +glm_mul_neon(mat4 m1, mat4 m2, mat4 dest) { + /* D = R * L (Column-Major) */ + + glmm_128 l, r0, r1, r2, r3, v0, v1, v2, v3; + + l = glmm_load(m1[0]); + r0 = glmm_load(m2[0]); + r1 = glmm_load(m2[1]); + r2 = glmm_load(m2[2]); + r3 = glmm_load(m2[3]); + + v0 = vmulq_f32(glmm_splat_x(r0), l); + v1 = vmulq_f32(glmm_splat_x(r1), l); + v2 = vmulq_f32(glmm_splat_x(r2), l); + v3 = vmulq_f32(glmm_splat_x(r3), l); + + l = glmm_load(m1[1]); + v0 = glmm_fmadd(glmm_splat_y(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_y(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_y(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_y(r3), l, v3); + + l = glmm_load(m1[2]); + v0 = glmm_fmadd(glmm_splat_z(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_z(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_z(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_z(r3), l, v3); + + v3 = glmm_fmadd(glmm_splat_w(r3), glmm_load(m1[3]), v3); + + glmm_store(dest[0], v0); + glmm_store(dest[1], v1); + glmm_store(dest[2], v2); + glmm_store(dest[3], v3); +} + +CGLM_INLINE +void +glm_mul_rot_neon(mat4 m1, mat4 m2, mat4 dest) { + /* D = R * L (Column-Major) */ + + glmm_128 l, r0, r1, r2, v0, v1, v2; + + l = glmm_load(m1[0]); + r0 = glmm_load(m2[0]); + r1 = glmm_load(m2[1]); + r2 = glmm_load(m2[2]); + + v0 = vmulq_f32(glmm_splat_x(r0), l); + v1 = vmulq_f32(glmm_splat_x(r1), l); + v2 = vmulq_f32(glmm_splat_x(r2), l); + + l = glmm_load(m1[1]); + v0 = glmm_fmadd(glmm_splat_y(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_y(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_y(r2), l, v2); + + l = glmm_load(m1[2]); + v0 = glmm_fmadd(glmm_splat_z(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_z(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_z(r2), l, v2); + + glmm_store(dest[0], v0); + glmm_store(dest[1], v1); + glmm_store(dest[2], v2); + glmm_store(dest[3], glmm_load(m1[3])); +} + +CGLM_INLINE +void +glm_inv_tr_neon(mat4 mat) { + float32x4x4_t vmat; + glmm_128 r0, r1, r2, x0; + + vmat = vld4q_f32(mat[0]); + r0 = vmat.val[0]; + r1 = vmat.val[1]; + r2 = vmat.val[2]; + + x0 = glmm_fmadd(r0, glmm_splat_w(r0), + glmm_fmadd(r1, glmm_splat_w(r1), + vmulq_f32(r2, glmm_splat_w(r2)))); + x0 = vnegq_f32(x0); + + glmm_store(mat[0], r0); + glmm_store(mat[1], r1); + glmm_store(mat[2], r2); + glmm_store(mat[3], x0); + + mat[0][3] = 0.0f; + mat[1][3] = 0.0f; + mat[2][3] = 0.0f; + mat[3][3] = 1.0f; + + /* TODO: ? + zo = vget_high_f32(r3); + vst1_lane_f32(&mat[0][3], zo, 0); + vst1_lane_f32(&mat[1][3], zo, 0); + vst1_lane_f32(&mat[2][3], zo, 0); + vst1_lane_f32(&mat[3][3], zo, 1); + */ +} + +#endif +#endif /* cglm_affine_neon_h */ diff --git a/external/cglm/simd/neon/mat2.h b/external/cglm/simd/neon/mat2.h new file mode 100644 index 0000000..7d0d9eb --- /dev/null +++ b/external/cglm/simd/neon/mat2.h @@ -0,0 +1,44 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_mat2_neon_h +#define cglm_mat2_neon_h +#if defined(CGLM_NEON_FP) + +#include "../../common.h" +#include "../intrin.h" + +CGLM_INLINE +void +glm_mat2_mul_neon(mat2 m1, mat2 m2, mat2 dest) { + float32x4x2_t a1; + glmm_128 x0, x1, x2; + float32x2_t dc, ba; + + x1 = glmm_load(m1[0]); /* d c b a */ + x2 = glmm_load(m2[0]); /* h g f e */ + + dc = vget_high_f32(x1); + ba = vget_low_f32(x1); + + /* g g e e, h h f f */ + a1 = vtrnq_f32(x2, x2); + + /* + dest[0][0] = a * e + c * f; + dest[0][1] = b * e + d * f; + dest[1][0] = a * g + c * h; + dest[1][1] = b * g + d * h; + */ + x0 = glmm_fmadd(vcombine_f32(ba, ba), a1.val[0], + vmulq_f32(vcombine_f32(dc, dc), a1.val[1])); + + glmm_store(dest[0], x0); +} + +#endif +#endif /* cglm_mat2_neon_h */ diff --git a/external/cglm/simd/neon/mat4.h b/external/cglm/simd/neon/mat4.h new file mode 100644 index 0000000..6cf9811 --- /dev/null +++ b/external/cglm/simd/neon/mat4.h @@ -0,0 +1,468 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_mat4_neon_h +#define cglm_mat4_neon_h +#if defined(CGLM_NEON_FP) + +#include "../../common.h" +#include "../intrin.h" + +CGLM_INLINE +void +glm_mat4_scale_neon(mat4 m, float s) { + float32x4_t v0; + + v0 = vdupq_n_f32(s); + + vst1q_f32(m[0], vmulq_f32(vld1q_f32(m[0]), v0)); + vst1q_f32(m[1], vmulq_f32(vld1q_f32(m[1]), v0)); + vst1q_f32(m[2], vmulq_f32(vld1q_f32(m[2]), v0)); + vst1q_f32(m[3], vmulq_f32(vld1q_f32(m[3]), v0)); +} + +CGLM_INLINE +void +glm_mat4_transp_neon(mat4 m, mat4 dest) { + float32x4x4_t vmat; + + vmat = vld4q_f32(m[0]); + + vst1q_f32(dest[0], vmat.val[0]); + vst1q_f32(dest[1], vmat.val[1]); + vst1q_f32(dest[2], vmat.val[2]); + vst1q_f32(dest[3], vmat.val[3]); +} + +CGLM_INLINE +void +glm_mat4_mul_neon(mat4 m1, mat4 m2, mat4 dest) { + /* D = R * L (Column-Major) */ + + glmm_128 l, r0, r1, r2, r3, v0, v1, v2, v3; + + l = glmm_load(m1[0]); + r0 = glmm_load(m2[0]); + r1 = glmm_load(m2[1]); + r2 = glmm_load(m2[2]); + r3 = glmm_load(m2[3]); + + v0 = vmulq_f32(glmm_splat_x(r0), l); + v1 = vmulq_f32(glmm_splat_x(r1), l); + v2 = vmulq_f32(glmm_splat_x(r2), l); + v3 = vmulq_f32(glmm_splat_x(r3), l); + + l = glmm_load(m1[1]); + v0 = glmm_fmadd(glmm_splat_y(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_y(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_y(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_y(r3), l, v3); + + l = glmm_load(m1[2]); + v0 = glmm_fmadd(glmm_splat_z(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_z(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_z(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_z(r3), l, v3); + + l = glmm_load(m1[3]); + v0 = glmm_fmadd(glmm_splat_w(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_w(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_w(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_w(r3), l, v3); + + glmm_store(dest[0], v0); + glmm_store(dest[1], v1); + glmm_store(dest[2], v2); + glmm_store(dest[3], v3); +} + +CGLM_INLINE +void +glm_mat4_mulv_neon(mat4 m, vec4 v, vec4 dest) { + float32x4_t l0, l1, l2, l3; + float32x2_t vlo, vhi; + + l0 = vld1q_f32(m[0]); + l1 = vld1q_f32(m[1]); + l2 = vld1q_f32(m[2]); + l3 = vld1q_f32(m[3]); + + vlo = vld1_f32(&v[0]); + vhi = vld1_f32(&v[2]); + + l0 = vmulq_lane_f32(l0, vlo, 0); + l0 = vmlaq_lane_f32(l0, l1, vlo, 1); + l0 = vmlaq_lane_f32(l0, l2, vhi, 0); + l0 = vmlaq_lane_f32(l0, l3, vhi, 1); + + vst1q_f32(dest, l0); +} + +CGLM_INLINE +float +glm_mat4_det_neon(mat4 mat) { + float32x4_t r0, r1, r2, r3, x0, x1, x2; + float32x2_t ij, op, mn, kl, nn, mm, jj, ii, gh, ef, t12, t34; + float32x4x2_t a1; + float32x4_t x3 = glmm_float32x4_SIGNMASK_PNPN; + + /* 127 <- 0, [square] det(A) = det(At) */ + r0 = glmm_load(mat[0]); /* d c b a */ + r1 = vrev64q_f32(glmm_load(mat[1])); /* g h e f */ + r2 = vrev64q_f32(glmm_load(mat[2])); /* l k i j */ + r3 = vrev64q_f32(glmm_load(mat[3])); /* o p m n */ + + gh = vget_high_f32(r1); + ef = vget_low_f32(r1); + kl = vget_high_f32(r2); + ij = vget_low_f32(r2); + op = vget_high_f32(r3); + mn = vget_low_f32(r3); + mm = vdup_lane_f32(mn, 1); + nn = vdup_lane_f32(mn, 0); + ii = vdup_lane_f32(ij, 1); + jj = vdup_lane_f32(ij, 0); + + /* + t[1] = j * p - n * l; + t[2] = j * o - n * k; + t[3] = i * p - m * l; + t[4] = i * o - m * k; + */ + x0 = glmm_fnmadd(vcombine_f32(kl, kl), vcombine_f32(nn, mm), + vmulq_f32(vcombine_f32(op, op), vcombine_f32(jj, ii))); + + t12 = vget_low_f32(x0); + t34 = vget_high_f32(x0); + + /* 1 3 1 3 2 4 2 4 */ + a1 = vuzpq_f32(x0, x0); + + /* + t[0] = k * p - o * l; + t[0] = k * p - o * l; + t[5] = i * n - m * j; + t[5] = i * n - m * j; + */ + x1 = glmm_fnmadd(vcombine_f32(vdup_lane_f32(kl, 0), jj), + vcombine_f32(vdup_lane_f32(op, 1), mm), + vmulq_f32(vcombine_f32(vdup_lane_f32(op, 0), nn), + vcombine_f32(vdup_lane_f32(kl, 1), ii))); + + /* + a * (f * t[0] - g * t[1] + h * t[2]) + - b * (e * t[0] - g * t[3] + h * t[4]) + + c * (e * t[1] - f * t[3] + h * t[5]) + - d * (e * t[2] - f * t[4] + g * t[5]) + */ + x2 = glmm_fnmadd(vcombine_f32(vdup_lane_f32(gh, 1), vdup_lane_f32(ef, 0)), + vcombine_f32(vget_low_f32(a1.val[0]), t34), + vmulq_f32(vcombine_f32(ef, vdup_lane_f32(ef, 1)), + vcombine_f32(vget_low_f32(x1), t12))); + + x2 = glmm_fmadd(vcombine_f32(vdup_lane_f32(gh, 0), gh), + vcombine_f32(vget_low_f32(a1.val[1]), vget_high_f32(x1)), x2); + + x2 = glmm_xor(x2, x3); + + return glmm_hadd(vmulq_f32(x2, r0)); +} + +/* old one */ +#if 0 +CGLM_INLINE +void +glm_mat4_inv_neon(mat4 mat, mat4 dest) { + float32x4_t r0, r1, r2, r3, + v0, v1, v2, v3, + t0, t1, t2, t3, t4, t5, + x0, x1, x2, x3, x4, x5, x6, x7, x8; + float32x4x2_t a1; + float32x2_t lp, ko, hg, jn, im, fe, ae, bf, cg, dh; + float32x4_t x9 = glmm_float32x4_SIGNMASK_NPNP; + + x8 = vrev64q_f32(x9); + + /* 127 <- 0 */ + r0 = glmm_load(mat[0]); /* d c b a */ + r1 = glmm_load(mat[1]); /* h g f e */ + r2 = glmm_load(mat[2]); /* l k j i */ + r3 = glmm_load(mat[3]); /* p o n m */ + + /* l p k o, j n i m */ + a1 = vzipq_f32(r3, r2); + + jn = vget_high_f32(a1.val[0]); + im = vget_low_f32(a1.val[0]); + lp = vget_high_f32(a1.val[1]); + ko = vget_low_f32(a1.val[1]); + hg = vget_high_f32(r1); + + x1 = vcombine_f32(vdup_lane_f32(lp, 0), lp); /* l p p p */ + x2 = vcombine_f32(vdup_lane_f32(ko, 0), ko); /* k o o o */ + x0 = vcombine_f32(vdup_lane_f32(lp, 1), vdup_lane_f32(hg, 1)); /* h h l l */ + x3 = vcombine_f32(vdup_lane_f32(ko, 1), vdup_lane_f32(hg, 0)); /* g g k k */ + + /* t1[0] = k * p - o * l; + t1[0] = k * p - o * l; + t2[0] = g * p - o * h; + t3[0] = g * l - k * h; */ + t0 = glmm_fnmadd(x2, x0, vmulq_f32(x3, x1)); + + fe = vget_low_f32(r1); + x4 = vcombine_f32(vdup_lane_f32(jn, 0), jn); /* j n n n */ + x5 = vcombine_f32(vdup_lane_f32(jn, 1), vdup_lane_f32(fe, 1)); /* f f j j */ + + /* t1[1] = j * p - n * l; + t1[1] = j * p - n * l; + t2[1] = f * p - n * h; + t3[1] = f * l - j * h; */ + t1 = glmm_fnmadd(x4, x0, vmulq_f32(x5, x1)); + + /* t1[2] = j * o - n * k + t1[2] = j * o - n * k; + t2[2] = f * o - n * g; + t3[2] = f * k - j * g; */ + t2 = glmm_fnmadd(x4, x3, vmulq_f32(x5, x2)); + + x6 = vcombine_f32(vdup_lane_f32(im, 1), vdup_lane_f32(fe, 0)); /* e e i i */ + x7 = vcombine_f32(vdup_lane_f32(im, 0), im); /* i m m m */ + + /* t1[3] = i * p - m * l; + t1[3] = i * p - m * l; + t2[3] = e * p - m * h; + t3[3] = e * l - i * h; */ + t3 = glmm_fnmadd(x7, x0, vmulq_f32(x6, x1)); + + /* t1[4] = i * o - m * k; + t1[4] = i * o - m * k; + t2[4] = e * o - m * g; + t3[4] = e * k - i * g; */ + t4 = glmm_fnmadd(x7, x3, vmulq_f32(x6, x2)); + + /* t1[5] = i * n - m * j; + t1[5] = i * n - m * j; + t2[5] = e * n - m * f; + t3[5] = e * j - i * f; */ + t5 = glmm_fnmadd(x7, x5, vmulq_f32(x6, x4)); + + /* h d f b, g c e a */ + a1 = vtrnq_f32(r0, r1); + + x4 = vrev64q_f32(a1.val[0]); /* c g a e */ + x5 = vrev64q_f32(a1.val[1]); /* d h b f */ + + ae = vget_low_f32(x4); + cg = vget_high_f32(x4); + bf = vget_low_f32(x5); + dh = vget_high_f32(x5); + + x0 = vcombine_f32(ae, vdup_lane_f32(ae, 1)); /* a a a e */ + x1 = vcombine_f32(bf, vdup_lane_f32(bf, 1)); /* b b b f */ + x2 = vcombine_f32(cg, vdup_lane_f32(cg, 1)); /* c c c g */ + x3 = vcombine_f32(dh, vdup_lane_f32(dh, 1)); /* d d d h */ + + /* + dest[0][0] = f * t1[0] - g * t1[1] + h * t1[2]; + dest[0][1] =-(b * t1[0] - c * t1[1] + d * t1[2]); + dest[0][2] = b * t2[0] - c * t2[1] + d * t2[2]; + dest[0][3] =-(b * t3[0] - c * t3[1] + d * t3[2]); */ + v0 = glmm_xor(glmm_fmadd(x3, t2, glmm_fnmadd(x2, t1, vmulq_f32(x1, t0))), x8); + + /* + dest[2][0] = e * t1[1] - f * t1[3] + h * t1[5]; + dest[2][1] =-(a * t1[1] - b * t1[3] + d * t1[5]); + dest[2][2] = a * t2[1] - b * t2[3] + d * t2[5]; + dest[2][3] =-(a * t3[1] - b * t3[3] + d * t3[5]);*/ + v2 = glmm_xor(glmm_fmadd(x3, t5, glmm_fnmadd(x1, t3, vmulq_f32(x0, t1))), x8); + + /* + dest[1][0] =-(e * t1[0] - g * t1[3] + h * t1[4]); + dest[1][1] = a * t1[0] - c * t1[3] + d * t1[4]; + dest[1][2] =-(a * t2[0] - c * t2[3] + d * t2[4]); + dest[1][3] = a * t3[0] - c * t3[3] + d * t3[4]; */ + v1 = glmm_xor(glmm_fmadd(x3, t4, glmm_fnmadd(x2, t3, vmulq_f32(x0, t0))), x9); + + /* + dest[3][0] =-(e * t1[2] - f * t1[4] + g * t1[5]); + dest[3][1] = a * t1[2] - b * t1[4] + c * t1[5]; + dest[3][2] =-(a * t2[2] - b * t2[4] + c * t2[5]); + dest[3][3] = a * t3[2] - b * t3[4] + c * t3[5]; */ + v3 = glmm_xor(glmm_fmadd(x2, t5, glmm_fnmadd(x1, t4, vmulq_f32(x0, t2))), x9); + + /* determinant */ + x0 = vcombine_f32(vget_low_f32(vzipq_f32(v0, v1).val[0]), + vget_low_f32(vzipq_f32(v2, v3).val[0])); + + /* + x0 = glmm_div(glmm_set1_rval(1.0f), glmm_vhadd(vmulq_f32(x0, r0))); + + glmm_store(dest[0], vmulq_f32(v0, x0)); + glmm_store(dest[1], vmulq_f32(v1, x0)); + glmm_store(dest[2], vmulq_f32(v2, x0)); + glmm_store(dest[3], vmulq_f32(v3, x0)); + */ + + x0 = glmm_vhadd(vmulq_f32(x0, r0)); + + glmm_store(dest[0], glmm_div(v0, x0)); + glmm_store(dest[1], glmm_div(v1, x0)); + glmm_store(dest[2], glmm_div(v2, x0)); + glmm_store(dest[3], glmm_div(v3, x0)); +} +#endif + +CGLM_INLINE +void +glm_mat4_inv_neon(mat4 mat, mat4 dest) { + float32x4_t r0, r1, r2, r3, + v0, v1, v2, v3, v4, v5, + t0, t1, t2; + float32x4x2_t a0, a1, a2, a3, a4; + float32x4_t s1 = glmm_float32x4_SIGNMASK_PNPN, s2; + +#if !CGLM_ARM64 + float32x2_t l0, l1; +#endif + + s2 = vrev64q_f32(s1); + + /* 127 <- 0 */ + r0 = glmm_load(mat[0]); /* d c b a */ + r1 = glmm_load(mat[1]); /* h g f e */ + r2 = glmm_load(mat[2]); /* l k j i */ + r3 = glmm_load(mat[3]); /* p o n m */ + + a1 = vzipq_f32(r0, r2); /* l d k c, j b i a */ + a2 = vzipq_f32(r1, r3); /* p h o g, n f m e */ + a3 = vzipq_f32(a2.val[0], a1.val[0]); /* j n b f, i m a e */ + a4 = vzipq_f32(a2.val[1], a1.val[1]); /* l p d h, k o c g */ + + v0 = vextq_f32(a1.val[0], a1.val[1], 2); /* k c j b */ + v1 = vextq_f32(a2.val[0], a2.val[1], 2); /* o g n f */ + v2 = vextq_f32(a1.val[1], a2.val[0], 2); /* m e l d */ + v3 = vextq_f32(a2.val[1], a1.val[0], 2); /* i a p h */ + v4 = vextq_f32(v1, v2, 2); /* l d o g */ + v5 = vextq_f32(v0, v3, 2); /* p h k c */ + + /* c2 = c * h - g * d c12 = a * g - c * e c8 = a * f - b * e + c1 = k * p - o * l c11 = i * o - k * m c7 = i * n - j * m + c4 = h * a - d * e c6 = b * h - d * f c10 = b * g - c * f + c3 = p * i - l * m c5 = j * p - l * n c9 = j * o - k * n */ + t0 = vmulq_f32(v5, v3); + t1 = vmulq_f32(a1.val[0], a2.val[1]); + t2 = vmulq_f32(a1.val[0], v1); + + t0 = glmm_fnmadd(v4, v2, t0); + t1 = glmm_fnmadd(a1.val[1], a2.val[0], t1); + t2 = glmm_fnmadd(v0, a2.val[0], t2); + + t0 = vrev64q_f32(t0); + t1 = vrev64q_f32(t1); + t2 = vrev64q_f32(t2); + + /* det */ + v0 = vrev64q_f32(t2); + v1 = vextq_f32(t1, t1, 2); + v0 = vmulq_f32(t0, v0); + v1 = vrev64q_f32(v1); + v1 = vmulq_f32(v1, t1); + + /* c3 * c10 + c4 * c9 + c1 * c8 + c2 * c7 */ +#if CGLM_ARM64 + v0 = vpaddq_f32(v0, v0); + v0 = vpaddq_f32(v0, v0); +#else + l0 = vget_low_f32(v0); + l1 = vget_high_f32(v0); + + l0 = vpadd_f32(l0, l0); /* [a+b, a+b] */ + l1 = vpadd_f32(l1, l1); /* [c+d, c+d] */ + l0 = vadd_f32(l0, l1); /* [sum, sum] */ + + v0 = vcombine_f32(l0, l0); +#endif + + /* c5 * c12 + c6 * c11 */ +#if CGLM_ARM64 + v1 = vpaddq_f32(v1, v1); +#else + l0 = vget_low_f32(v1); + l1 = vget_high_f32(v1); + + l0 = vpadd_f32(l0, l0); /* [a+b, a+b] */ + l1 = vpadd_f32(l1, l1); /* [c+d, c+d] */ + + v1 = vcombine_f32(l0, l1); +#endif + + v0 = vsubq_f32(v0, v1); /* det */ + + /* inv div */ + v1 = vdupq_n_f32(1.0f); + v0 = glmm_div(v1, v0); /* inv div */ + + /* multiply t0,t1,t2 by idt to reduce 1mul below: 2eor+4mul vs 3mul+4eor */ + t0 = vmulq_f32(t0, v0); + t1 = vmulq_f32(t1, v0); + t2 = vmulq_f32(t2, v0); + + a0 = vzipq_f32(t0, t0); /* c4 c4 c3 c3, c2 c2 c1 c1 */ + a1 = vzipq_f32(t1, t1); /* c6 c6 c5 c5, c12 c12 c11 c11 */ + a2 = vzipq_f32(t2, t2); /* c10 c10 c9 c9, c8 c8 c7 c7 */ + + /* result */ + + /* dest[0][0] = (f * c1 - g * c5 + h * c9) * idt; + dest[0][1] = (b * c1 - c * c5 + d * c9) * ndt; + dest[0][2] = (n * c2 - o * c6 + p * c10) * idt; + dest[0][3] = (j * c2 - k * c6 + l * c10) * ndt; + + dest[1][0] = (e * c1 - g * c3 + h * c11) * ndt; + dest[1][1] = (a * c1 - c * c3 + d * c11) * idt; + dest[1][2] = (m * c2 - o * c4 + p * c12) * ndt; + dest[1][3] = (i * c2 - k * c4 + l * c12) * idt; + + dest[2][0] = (e * c5 - f * c3 + h * c7) * idt; + dest[2][1] = (a * c5 - b * c3 + d * c7) * ndt; + dest[2][2] = (m * c6 - n * c4 + p * c8) * idt; + dest[2][3] = (i * c6 - j * c4 + l * c8) * ndt; + + dest[3][0] = (e * c9 - f * c11 + g * c7) * ndt; + dest[3][1] = (a * c9 - b * c11 + c * c7) * idt; + dest[3][2] = (m * c10 - n * c12 + o * c8) * ndt; + dest[3][3] = (i * c10 - j * c12 + k * c8) * idt; */ + + r0 = vmulq_f32(a3.val[1], a0.val[0]); + r1 = vmulq_f32(a3.val[0], a0.val[0]); + r2 = vmulq_f32(a3.val[0], a1.val[1]); + r3 = vmulq_f32(a3.val[0], a2.val[1]); + + r0 = glmm_fnmadd(a4.val[0], a1.val[1], r0); + r1 = glmm_fnmadd(a4.val[0], a0.val[1], r1); + r2 = glmm_fnmadd(a3.val[1], a0.val[1], r2); + r3 = glmm_fnmadd(a3.val[1], a1.val[0], r3); + + r0 = glmm_fmadd(a4.val[1], a2.val[1], r0); + r1 = glmm_fmadd(a4.val[1], a1.val[0], r1); + r2 = glmm_fmadd(a4.val[1], a2.val[0], r2); + r3 = glmm_fmadd(a4.val[0], a2.val[0], r3); + + /* 4xor may be fastart then 4mul, see above */ + r0 = glmm_xor(r0, s1); + r1 = glmm_xor(r1, s2); + r2 = glmm_xor(r2, s1); + r3 = glmm_xor(r3, s2); + + glmm_store(dest[0], r0); + glmm_store(dest[1], r1); + glmm_store(dest[2], r2); + glmm_store(dest[3], r3); +} + +#endif +#endif /* cglm_mat4_neon_h */ diff --git a/external/cglm/simd/neon/quat.h b/external/cglm/simd/neon/quat.h new file mode 100644 index 0000000..55dc1da --- /dev/null +++ b/external/cglm/simd/neon/quat.h @@ -0,0 +1,57 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_quat_neon_h +#define cglm_quat_neon_h +#if defined(CGLM_NEON_FP) + +#include "../../common.h" +#include "../intrin.h" + +CGLM_INLINE +void +glm_quat_mul_neon(versor p, versor q, versor dest) { + /* + + (a1 b2 + b1 a2 + c1 d2 − d1 c2)i + + (a1 c2 − b1 d2 + c1 a2 + d1 b2)j + + (a1 d2 + b1 c2 − c1 b2 + d1 a2)k + a1 a2 − b1 b2 − c1 c2 − d1 d2 + */ + + glmm_128 xp, xq, xqr, r, x, y, z, s2, s3; + glmm_128 s1 = glmm_float32x4_SIGNMASK_NPPN; + + float32x2_t qh, ql; + + xp = glmm_load(p); /* 3 2 1 0 */ + xq = glmm_load(q); + + r = vmulq_f32(glmm_splat_w(xp), xq); + x = glmm_splat_x(xp); + y = glmm_splat_y(xp); + z = glmm_splat_z(xp); + + ql = vget_high_f32(s1); + s3 = vcombine_f32(ql, ql); + s2 = vzipq_f32(s3, s3).val[0]; + + xqr = vrev64q_f32(xq); + qh = vget_high_f32(xqr); + ql = vget_low_f32(xqr); + + r = glmm_fmadd(glmm_xor(x, s3), vcombine_f32(qh, ql), r); + + r = glmm_fmadd(glmm_xor(y, s2), vcombine_f32(vget_high_f32(xq), + vget_low_f32(xq)), r); + + r = glmm_fmadd(glmm_xor(z, s1), vcombine_f32(ql, qh), r); + + glmm_store(dest, r); +} + +#endif +#endif /* cglm_quat_neon_h */ diff --git a/external/cglm/simd/sse2/affine.h b/external/cglm/simd/sse2/affine.h new file mode 100644 index 0000000..0619995 --- /dev/null +++ b/external/cglm/simd/sse2/affine.h @@ -0,0 +1,115 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_affine_mat_sse2_h +#define cglm_affine_mat_sse2_h +#if defined( __SSE__ ) || defined( __SSE2__ ) + +#include "../../common.h" +#include "../intrin.h" + +CGLM_INLINE +void +glm_mul_sse2(mat4 m1, mat4 m2, mat4 dest) { + /* D = R * L (Column-Major) */ + glmm_128 l, r0, r1, r2, r3, v0, v1, v2, v3; + + l = glmm_load(m1[0]); + r0 = glmm_load(m2[0]); + r1 = glmm_load(m2[1]); + r2 = glmm_load(m2[2]); + r3 = glmm_load(m2[3]); + + v0 = _mm_mul_ps(glmm_splat_x(r0), l); + v1 = _mm_mul_ps(glmm_splat_x(r1), l); + v2 = _mm_mul_ps(glmm_splat_x(r2), l); + v3 = _mm_mul_ps(glmm_splat_x(r3), l); + + l = glmm_load(m1[1]); + v0 = glmm_fmadd(glmm_splat_y(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_y(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_y(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_y(r3), l, v3); + + l = glmm_load(m1[2]); + v0 = glmm_fmadd(glmm_splat_z(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_z(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_z(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_z(r3), l, v3); + + l = glmm_load(m1[3]); + v3 = glmm_fmadd(glmm_splat_w(r3), l, v3); + + glmm_store(dest[0], v0); + glmm_store(dest[1], v1); + glmm_store(dest[2], v2); + glmm_store(dest[3], v3); +} + +CGLM_INLINE +void +glm_mul_rot_sse2(mat4 m1, mat4 m2, mat4 dest) { + /* D = R * L (Column-Major) */ + + glmm_128 l, r0, r1, r2, v0, v1, v2; + + l = glmm_load(m1[0]); + r0 = glmm_load(m2[0]); + r1 = glmm_load(m2[1]); + r2 = glmm_load(m2[2]); + + v0 = _mm_mul_ps(glmm_splat_x(r0), l); + v1 = _mm_mul_ps(glmm_splat_x(r1), l); + v2 = _mm_mul_ps(glmm_splat_x(r2), l); + + l = glmm_load(m1[1]); + v0 = glmm_fmadd(glmm_splat_y(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_y(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_y(r2), l, v2); + + l = glmm_load(m1[2]); + v0 = glmm_fmadd(glmm_splat_z(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_z(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_z(r2), l, v2); + + glmm_store(dest[0], v0); + glmm_store(dest[1], v1); + glmm_store(dest[2], v2); + glmm_store(dest[3], glmm_load(m1[3])); +} + +CGLM_INLINE +void +glm_inv_tr_sse2(mat4 mat) { + __m128 r0, r1, r2, r3, x0, x1, x2, x3, x4, x5; + + r0 = glmm_load(mat[0]); + r1 = glmm_load(mat[1]); + r2 = glmm_load(mat[2]); + r3 = glmm_load(mat[3]); + x1 = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f); + + _MM_TRANSPOSE4_PS(r0, r1, r2, x1); + + x2 = glmm_shuff1(r3, 0, 0, 0, 0); + x3 = glmm_shuff1(r3, 1, 1, 1, 1); + x4 = glmm_shuff1(r3, 2, 2, 2, 2); + x5 = glmm_float32x4_SIGNMASK_NEG; + + x0 = glmm_fmadd(r0, x2, glmm_fmadd(r1, x3, _mm_mul_ps(r2, x4))); + x0 = _mm_xor_ps(x0, x5); + + x0 = _mm_add_ps(x0, x1); + + glmm_store(mat[0], r0); + glmm_store(mat[1], r1); + glmm_store(mat[2], r2); + glmm_store(mat[3], x0); +} + +#endif +#endif /* cglm_affine_mat_sse2_h */ diff --git a/external/cglm/simd/sse2/mat2.h b/external/cglm/simd/sse2/mat2.h new file mode 100644 index 0000000..31b3a29 --- /dev/null +++ b/external/cglm/simd/sse2/mat2.h @@ -0,0 +1,48 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_mat2_sse_h +#define cglm_mat2_sse_h +#if defined( __SSE__ ) || defined( __SSE2__ ) + +#include "../../common.h" +#include "../intrin.h" + +CGLM_INLINE +void +glm_mat2_mul_sse2(mat2 m1, mat2 m2, mat2 dest) { + __m128 x0, x1, x2, x3, x4; + + x1 = glmm_load(m1[0]); /* d c b a */ + x2 = glmm_load(m2[0]); /* h g f e */ + + x3 = glmm_shuff1(x2, 2, 2, 0, 0); + x4 = glmm_shuff1(x2, 3, 3, 1, 1); + x0 = _mm_movelh_ps(x1, x1); + x2 = _mm_movehl_ps(x1, x1); + + /* + dest[0][0] = a * e + c * f; + dest[0][1] = b * e + d * f; + dest[1][0] = a * g + c * h; + dest[1][1] = b * g + d * h; + */ + x0 = glmm_fmadd(x0, x3, _mm_mul_ps(x2, x4)); + + glmm_store(dest[0], x0); +} + +CGLM_INLINE +void +glm_mat2_transp_sse2(mat2 m, mat2 dest) { + /* d c b a */ + /* d b c a */ + glmm_store(dest[0], glmm_shuff1(glmm_load(m[0]), 3, 1, 2, 0)); +} + +#endif +#endif /* cglm_mat2_sse_h */ diff --git a/external/cglm/simd/sse2/mat3.h b/external/cglm/simd/sse2/mat3.h new file mode 100644 index 0000000..f07320c --- /dev/null +++ b/external/cglm/simd/sse2/mat3.h @@ -0,0 +1,76 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_mat3_sse_h +#define cglm_mat3_sse_h +#if defined( __SSE__ ) || defined( __SSE2__ ) + +#include "../../common.h" +#include "../intrin.h" + +CGLM_INLINE +void +glm_mat3_mul_sse2(mat3 m1, mat3 m2, mat3 dest) { + __m128 l0, l1, l2, r0, r1, r2, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9; + + l0 = _mm_loadu_ps(m1[0]); + l1 = _mm_loadu_ps(&m1[1][1]); + + r0 = _mm_loadu_ps(m2[0]); + r1 = _mm_loadu_ps(&m2[1][1]); + + x8 = glmm_shuff1(l0, 0, 2, 1, 0); /* a00 a02 a01 a00 */ + x1 = glmm_shuff1(r0, 3, 0, 0, 0); /* b10 b00 b00 b00 */ + x2 = _mm_shuffle_ps(l0, l1, _MM_SHUFFLE(1, 0, 3, 3)); /* a12 a11 a10 a10 */ + x3 = _mm_shuffle_ps(r0, r1, _MM_SHUFFLE(2, 0, 3, 1)); /* b20 b11 b10 b01 */ + x0 = _mm_mul_ps(x8, x1); + + x6 = glmm_shuff1(l0, 1, 0, 2, 1); /* a01 a00 a02 a01 */ + x7 = glmm_shuff1(x3, 3, 3, 1, 1); /* b20 b20 b10 b10 */ + l2 = _mm_load_ss(&m1[2][2]); + r2 = _mm_load_ss(&m2[2][2]); + x1 = _mm_mul_ps(x6, x7); + l2 = glmm_shuff1(l2, 0, 0, 1, 0); /* a22 a22 0.f a22 */ + r2 = glmm_shuff1(r2, 0, 0, 1, 0); /* b22 b22 0.f b22 */ + + x4 = glmm_shuff1(x2, 0, 3, 2, 0); /* a10 a12 a11 a10 */ + x5 = glmm_shuff1(x2, 2, 0, 3, 2); /* a11 a10 a12 a11 */ + x6 = glmm_shuff1(x3, 2, 0, 0, 0); /* b11 b01 b01 b01 */ + x2 = glmm_shuff1(r1, 3, 3, 0, 0); /* b21 b21 b11 b11 */ + + x8 = _mm_unpackhi_ps(x8, x4); /* a10 a00 a12 a02 */ + x9 = _mm_unpackhi_ps(x7, x2); /* b21 b20 b21 b20 */ + + x0 = glmm_fmadd(x4, x6, x0); + x1 = glmm_fmadd(x5, x2, x1); + + x2 = _mm_movehl_ps(l2, l1); /* a22 a22 a21 a20 */ + x3 = glmm_shuff1(x2, 0, 2, 1, 0); /* a20 a22 a21 a20 */ + x2 = glmm_shuff1(x2, 1, 0, 2, 1); /* a21 a20 a22 a21 */ + x4 = _mm_shuffle_ps(r0, r1, _MM_SHUFFLE(1, 1, 2, 2)); /* b12 b12 b02 b02 */ + + x5 = glmm_shuff1(x4, 3, 0, 0, 0); /* b12 b02 b02 b02 */ + x4 = _mm_movehl_ps(r2, x4); /* b22 b22 b12 b12 */ + x0 = glmm_fmadd(x3, x5, x0); + x1 = glmm_fmadd(x2, x4, x1); + + /* + Dot Product : dest[2][2] = a02 * b20 + + a12 * b21 + + a22 * b22 + + 0 * 00 */ + x2 = _mm_movelh_ps(x8, l2); /* 0.f a22 a12 a02 */ + x3 = _mm_movelh_ps(x9, r2); /* 0.f b22 b21 b20 */ + x2 = glmm_vdots(x2, x3); + + _mm_storeu_ps(&dest[0][0], x0); + _mm_storeu_ps(&dest[1][1], x1); + _mm_store_ss (&dest[2][2], x2); +} + +#endif +#endif /* cglm_mat3_sse_h */ diff --git a/external/cglm/simd/sse2/mat4.h b/external/cglm/simd/sse2/mat4.h new file mode 100644 index 0000000..2127e72 --- /dev/null +++ b/external/cglm/simd/sse2/mat4.h @@ -0,0 +1,573 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_mat_sse_h +#define cglm_mat_sse_h +#if defined( __SSE__ ) || defined( __SSE2__ ) + +#include "../../common.h" +#include "../intrin.h" + +#define glm_mat4_inv_precise_sse2(mat, dest) glm_mat4_inv_sse2(mat, dest) + +CGLM_INLINE +void +glm_mat4_scale_sse2(mat4 m, float s) { + __m128 x0; + x0 = glmm_set1(s); + + glmm_store(m[0], _mm_mul_ps(glmm_load(m[0]), x0)); + glmm_store(m[1], _mm_mul_ps(glmm_load(m[1]), x0)); + glmm_store(m[2], _mm_mul_ps(glmm_load(m[2]), x0)); + glmm_store(m[3], _mm_mul_ps(glmm_load(m[3]), x0)); +} + +CGLM_INLINE +void +glm_mat4_transp_sse2(mat4 m, mat4 dest) { + __m128 r0, r1, r2, r3; + + r0 = glmm_load(m[0]); + r1 = glmm_load(m[1]); + r2 = glmm_load(m[2]); + r3 = glmm_load(m[3]); + + _MM_TRANSPOSE4_PS(r0, r1, r2, r3); + + glmm_store(dest[0], r0); + glmm_store(dest[1], r1); + glmm_store(dest[2], r2); + glmm_store(dest[3], r3); +} + +CGLM_INLINE +void +glm_mat4_mul_sse2(mat4 m1, mat4 m2, mat4 dest) { + /* D = R * L (Column-Major) */ + + glmm_128 l, r0, r1, r2, r3, v0, v1, v2, v3; + + l = glmm_load(m1[0]); + r0 = glmm_load(m2[0]); + r1 = glmm_load(m2[1]); + r2 = glmm_load(m2[2]); + r3 = glmm_load(m2[3]); + + v0 = _mm_mul_ps(glmm_splat_x(r0), l); + v1 = _mm_mul_ps(glmm_splat_x(r1), l); + v2 = _mm_mul_ps(glmm_splat_x(r2), l); + v3 = _mm_mul_ps(glmm_splat_x(r3), l); + + l = glmm_load(m1[1]); + v0 = glmm_fmadd(glmm_splat_y(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_y(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_y(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_y(r3), l, v3); + + l = glmm_load(m1[2]); + v0 = glmm_fmadd(glmm_splat_z(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_z(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_z(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_z(r3), l, v3); + + l = glmm_load(m1[3]); + v0 = glmm_fmadd(glmm_splat_w(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_w(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_w(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_w(r3), l, v3); + + glmm_store(dest[0], v0); + glmm_store(dest[1], v1); + glmm_store(dest[2], v2); + glmm_store(dest[3], v3); +} + +CGLM_INLINE +void +glm_mat4_mulv_sse2(mat4 m, vec4 v, vec4 dest) { + __m128 x0, x1, m0, m1, m2, m3, v0, v1, v2, v3; + + m0 = glmm_load(m[0]); + m1 = glmm_load(m[1]); + m2 = glmm_load(m[2]); + m3 = glmm_load(m[3]); + + x0 = glmm_load(v); + v0 = glmm_splat_x(x0); + v1 = glmm_splat_y(x0); + v2 = glmm_splat_z(x0); + v3 = glmm_splat_w(x0); + + x1 = _mm_mul_ps(m3, v3); + x1 = glmm_fmadd(m2, v2, x1); + x1 = glmm_fmadd(m1, v1, x1); + x1 = glmm_fmadd(m0, v0, x1); + + glmm_store(dest, x1); +} + +CGLM_INLINE +float +glm_mat4_det_sse2(mat4 mat) { + __m128 r0, r1, r2, r3, x0, x1, x2; + + /* 127 <- 0, [square] det(A) = det(At) */ + r0 = glmm_load(mat[0]); /* d c b a */ + r1 = glmm_load(mat[1]); /* h g f e */ + r2 = glmm_load(mat[2]); /* l k j i */ + r3 = glmm_load(mat[3]); /* p o n m */ + + /* + t[1] = j * p - n * l; + t[2] = j * o - n * k; + t[3] = i * p - m * l; + t[4] = i * o - m * k; + */ + x0 = glmm_fnmadd(glmm_shuff1(r3, 0, 0, 1, 1), glmm_shuff1(r2, 2, 3, 2, 3), + _mm_mul_ps(glmm_shuff1(r2, 0, 0, 1, 1), + glmm_shuff1(r3, 2, 3, 2, 3))); + /* + t[0] = k * p - o * l; + t[0] = k * p - o * l; + t[5] = i * n - m * j; + t[5] = i * n - m * j; + */ + x1 = glmm_fnmadd(glmm_shuff1(r3, 0, 0, 2, 2), glmm_shuff1(r2, 1, 1, 3, 3), + _mm_mul_ps(glmm_shuff1(r2, 0, 0, 2, 2), + glmm_shuff1(r3, 1, 1, 3, 3))); + + /* + a * (f * t[0] - g * t[1] + h * t[2]) + - b * (e * t[0] - g * t[3] + h * t[4]) + + c * (e * t[1] - f * t[3] + h * t[5]) + - d * (e * t[2] - f * t[4] + g * t[5]) + */ + x2 = glmm_fnmadd(glmm_shuff1(r1, 1, 1, 2, 2), glmm_shuff1(x0, 3, 2, 2, 0), + _mm_mul_ps(glmm_shuff1(r1, 0, 0, 0, 1), + _mm_shuffle_ps(x1, x0, _MM_SHUFFLE(1, 0, 0, 0)))); + x2 = glmm_fmadd(glmm_shuff1(r1, 2, 3, 3, 3), + _mm_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 2, 3, 1)), + x2); + + x2 = _mm_xor_ps(x2, glmm_float32x4_SIGNMASK_NPNP); + + return glmm_hadd(_mm_mul_ps(x2, r0)); +} + +CGLM_INLINE +void +glm_mat4_inv_fast_sse2(mat4 mat, mat4 dest) { + __m128 r0, r1, r2, r3, + v0, v1, v2, v3, + t0, t1, t2, t3, t4, t5, + x0, x1, x2, x3, x4, x5, x6, x7, x8, x9; + + /* x8 = _mm_set_ps(-0.f, 0.f, -0.f, 0.f); */ + x8 = glmm_float32x4_SIGNMASK_NPNP; + x9 = glmm_shuff1(x8, 2, 1, 2, 1); + + /* 127 <- 0 */ + r0 = glmm_load(mat[0]); /* d c b a */ + r1 = glmm_load(mat[1]); /* h g f e */ + r2 = glmm_load(mat[2]); /* l k j i */ + r3 = glmm_load(mat[3]); /* p o n m */ + + x0 = _mm_movehl_ps(r3, r2); /* p o l k */ + x3 = _mm_movelh_ps(r2, r3); /* n m j i */ + x1 = glmm_shuff1(x0, 1, 3, 3 ,3); /* l p p p */ + x2 = glmm_shuff1(x0, 0, 2, 2, 2); /* k o o o */ + x4 = glmm_shuff1(x3, 1, 3, 3, 3); /* j n n n */ + x7 = glmm_shuff1(x3, 0, 2, 2, 2); /* i m m m */ + + x6 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(0, 0, 0, 0)); /* e e i i */ + x5 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(1, 1, 1, 1)); /* f f j j */ + x3 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(2, 2, 2, 2)); /* g g k k */ + x0 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(3, 3, 3, 3)); /* h h l l */ + + t0 = _mm_mul_ps(x3, x1); + t1 = _mm_mul_ps(x5, x1); + t2 = _mm_mul_ps(x5, x2); + t3 = _mm_mul_ps(x6, x1); + t4 = _mm_mul_ps(x6, x2); + t5 = _mm_mul_ps(x6, x4); + + /* t1[0] = k * p - o * l; + t1[0] = k * p - o * l; + t2[0] = g * p - o * h; + t3[0] = g * l - k * h; */ + t0 = glmm_fnmadd(x2, x0, t0); + + /* t1[1] = j * p - n * l; + t1[1] = j * p - n * l; + t2[1] = f * p - n * h; + t3[1] = f * l - j * h; */ + t1 = glmm_fnmadd(x4, x0, t1); + + /* t1[2] = j * o - n * k + t1[2] = j * o - n * k; + t2[2] = f * o - n * g; + t3[2] = f * k - j * g; */ + t2 = glmm_fnmadd(x4, x3, t2); + + /* t1[3] = i * p - m * l; + t1[3] = i * p - m * l; + t2[3] = e * p - m * h; + t3[3] = e * l - i * h; */ + t3 = glmm_fnmadd(x7, x0, t3); + + /* t1[4] = i * o - m * k; + t1[4] = i * o - m * k; + t2[4] = e * o - m * g; + t3[4] = e * k - i * g; */ + t4 = glmm_fnmadd(x7, x3, t4); + + /* t1[5] = i * n - m * j; + t1[5] = i * n - m * j; + t2[5] = e * n - m * f; + t3[5] = e * j - i * f; */ + t5 = glmm_fnmadd(x7, x5, t5); + + x4 = _mm_movelh_ps(r0, r1); /* f e b a */ + x5 = _mm_movehl_ps(r1, r0); /* h g d c */ + + x0 = glmm_shuff1(x4, 0, 0, 0, 2); /* a a a e */ + x1 = glmm_shuff1(x4, 1, 1, 1, 3); /* b b b f */ + x2 = glmm_shuff1(x5, 0, 0, 0, 2); /* c c c g */ + x3 = glmm_shuff1(x5, 1, 1, 1, 3); /* d d d h */ + + v2 = _mm_mul_ps(x0, t1); + v1 = _mm_mul_ps(x0, t0); + v3 = _mm_mul_ps(x0, t2); + v0 = _mm_mul_ps(x1, t0); + + v2 = glmm_fnmadd(x1, t3, v2); + v3 = glmm_fnmadd(x1, t4, v3); + v0 = glmm_fnmadd(x2, t1, v0); + v1 = glmm_fnmadd(x2, t3, v1); + + v3 = glmm_fmadd(x2, t5, v3); + v0 = glmm_fmadd(x3, t2, v0); + v2 = glmm_fmadd(x3, t5, v2); + v1 = glmm_fmadd(x3, t4, v1); + + /* + dest[0][0] = f * t1[0] - g * t1[1] + h * t1[2]; + dest[0][1] =-(b * t1[0] - c * t1[1] + d * t1[2]); + dest[0][2] = b * t2[0] - c * t2[1] + d * t2[2]; + dest[0][3] =-(b * t3[0] - c * t3[1] + d * t3[2]); */ + v0 = _mm_xor_ps(v0, x8); + + /* + dest[2][0] = e * t1[1] - f * t1[3] + h * t1[5]; + dest[2][1] =-(a * t1[1] - b * t1[3] + d * t1[5]); + dest[2][2] = a * t2[1] - b * t2[3] + d * t2[5]; + dest[2][3] =-(a * t3[1] - b * t3[3] + d * t3[5]);*/ + v2 = _mm_xor_ps(v2, x8); + + /* + dest[1][0] =-(e * t1[0] - g * t1[3] + h * t1[4]); + dest[1][1] = a * t1[0] - c * t1[3] + d * t1[4]; + dest[1][2] =-(a * t2[0] - c * t2[3] + d * t2[4]); + dest[1][3] = a * t3[0] - c * t3[3] + d * t3[4]; */ + v1 = _mm_xor_ps(v1, x9); + + /* + dest[3][0] =-(e * t1[2] - f * t1[4] + g * t1[5]); + dest[3][1] = a * t1[2] - b * t1[4] + c * t1[5]; + dest[3][2] =-(a * t2[2] - b * t2[4] + c * t2[5]); + dest[3][3] = a * t3[2] - b * t3[4] + c * t3[5]; */ + v3 = _mm_xor_ps(v3, x9); + + /* determinant */ + x0 = _mm_shuffle_ps(v0, v1, _MM_SHUFFLE(0, 0, 0, 0)); + x1 = _mm_shuffle_ps(v2, v3, _MM_SHUFFLE(0, 0, 0, 0)); + x0 = _mm_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 0, 2, 0)); + + x0 = _mm_rcp_ps(glmm_vhadd(_mm_mul_ps(x0, r0))); + + glmm_store(dest[0], _mm_mul_ps(v0, x0)); + glmm_store(dest[1], _mm_mul_ps(v1, x0)); + glmm_store(dest[2], _mm_mul_ps(v2, x0)); + glmm_store(dest[3], _mm_mul_ps(v3, x0)); +} + +/* old one */ +#if 0 +CGLM_INLINE +void +glm_mat4_inv_sse2(mat4 mat, mat4 dest) { + __m128 r0, r1, r2, r3, + v0, v1, v2, v3, + t0, t1, t2, t3, t4, t5, + x0, x1, x2, x3, x4, x5, x6, x7, x8, x9; + + /* x8 = _mm_set_ps(-0.f, 0.f, -0.f, 0.f); */ + x8 = glmm_float32x4_SIGNMASK_NPNP; + x9 = glmm_shuff1(x8, 2, 1, 2, 1); + + /* 127 <- 0 */ + r0 = glmm_load(mat[0]); /* d c b a */ + r1 = glmm_load(mat[1]); /* h g f e */ + r2 = glmm_load(mat[2]); /* l k j i */ + r3 = glmm_load(mat[3]); /* p o n m */ + + x0 = _mm_movehl_ps(r3, r2); /* p o l k */ + x3 = _mm_movelh_ps(r2, r3); /* n m j i */ + x1 = glmm_shuff1(x0, 1, 3, 3 ,3); /* l p p p */ + x2 = glmm_shuff1(x0, 0, 2, 2, 2); /* k o o o */ + x4 = glmm_shuff1(x3, 1, 3, 3, 3); /* j n n n */ + x7 = glmm_shuff1(x3, 0, 2, 2, 2); /* i m m m */ + + x6 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(0, 0, 0, 0)); /* e e i i */ + x5 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(1, 1, 1, 1)); /* f f j j */ + x3 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(2, 2, 2, 2)); /* g g k k */ + x0 = _mm_shuffle_ps(r2, r1, _MM_SHUFFLE(3, 3, 3, 3)); /* h h l l */ + + t0 = _mm_mul_ps(x3, x1); + t1 = _mm_mul_ps(x5, x1); + t2 = _mm_mul_ps(x5, x2); + t3 = _mm_mul_ps(x6, x1); + t4 = _mm_mul_ps(x6, x2); + t5 = _mm_mul_ps(x6, x4); + + /* t1[0] = k * p - o * l; + t1[0] = k * p - o * l; + t2[0] = g * p - o * h; + t3[0] = g * l - k * h; */ + t0 = glmm_fnmadd(x2, x0, t0); + + /* t1[1] = j * p - n * l; + t1[1] = j * p - n * l; + t2[1] = f * p - n * h; + t3[1] = f * l - j * h; */ + t1 = glmm_fnmadd(x4, x0, t1); + + /* t1[2] = j * o - n * k + t1[2] = j * o - n * k; + t2[2] = f * o - n * g; + t3[2] = f * k - j * g; */ + t2 = glmm_fnmadd(x4, x3, t2); + + /* t1[3] = i * p - m * l; + t1[3] = i * p - m * l; + t2[3] = e * p - m * h; + t3[3] = e * l - i * h; */ + t3 = glmm_fnmadd(x7, x0, t3); + + /* t1[4] = i * o - m * k; + t1[4] = i * o - m * k; + t2[4] = e * o - m * g; + t3[4] = e * k - i * g; */ + t4 = glmm_fnmadd(x7, x3, t4); + + /* t1[5] = i * n - m * j; + t1[5] = i * n - m * j; + t2[5] = e * n - m * f; + t3[5] = e * j - i * f; */ + t5 = glmm_fnmadd(x7, x5, t5); + + x4 = _mm_movelh_ps(r0, r1); /* f e b a */ + x5 = _mm_movehl_ps(r1, r0); /* h g d c */ + + x0 = glmm_shuff1(x4, 0, 0, 0, 2); /* a a a e */ + x1 = glmm_shuff1(x4, 1, 1, 1, 3); /* b b b f */ + x2 = glmm_shuff1(x5, 0, 0, 0, 2); /* c c c g */ + x3 = glmm_shuff1(x5, 1, 1, 1, 3); /* d d d h */ + + v2 = _mm_mul_ps(x0, t1); + v1 = _mm_mul_ps(x0, t0); + v3 = _mm_mul_ps(x0, t2); + v0 = _mm_mul_ps(x1, t0); + + v2 = glmm_fnmadd(x1, t3, v2); + v3 = glmm_fnmadd(x1, t4, v3); + v0 = glmm_fnmadd(x2, t1, v0); + v1 = glmm_fnmadd(x2, t3, v1); + + v3 = glmm_fmadd(x2, t5, v3); + v0 = glmm_fmadd(x3, t2, v0); + v2 = glmm_fmadd(x3, t5, v2); + v1 = glmm_fmadd(x3, t4, v1); + + /* + dest[0][0] = f * t1[0] - g * t1[1] + h * t1[2]; + dest[0][1] =-(b * t1[0] - c * t1[1] + d * t1[2]); + dest[0][2] = b * t2[0] - c * t2[1] + d * t2[2]; + dest[0][3] =-(b * t3[0] - c * t3[1] + d * t3[2]); */ + v0 = _mm_xor_ps(v0, x8); + + /* + dest[2][0] = e * t1[1] - f * t1[3] + h * t1[5]; + dest[2][1] =-(a * t1[1] - b * t1[3] + d * t1[5]); + dest[2][2] = a * t2[1] - b * t2[3] + d * t2[5]; + dest[2][3] =-(a * t3[1] - b * t3[3] + d * t3[5]);*/ + v2 = _mm_xor_ps(v2, x8); + + /* + dest[1][0] =-(e * t1[0] - g * t1[3] + h * t1[4]); + dest[1][1] = a * t1[0] - c * t1[3] + d * t1[4]; + dest[1][2] =-(a * t2[0] - c * t2[3] + d * t2[4]); + dest[1][3] = a * t3[0] - c * t3[3] + d * t3[4]; */ + v1 = _mm_xor_ps(v1, x9); + + /* + dest[3][0] =-(e * t1[2] - f * t1[4] + g * t1[5]); + dest[3][1] = a * t1[2] - b * t1[4] + c * t1[5]; + dest[3][2] =-(a * t2[2] - b * t2[4] + c * t2[5]); + dest[3][3] = a * t3[2] - b * t3[4] + c * t3[5]; */ + v3 = _mm_xor_ps(v3, x9); + + /* determinant */ + x0 = _mm_shuffle_ps(v0, v1, _MM_SHUFFLE(0, 0, 0, 0)); + x1 = _mm_shuffle_ps(v2, v3, _MM_SHUFFLE(0, 0, 0, 0)); + x0 = _mm_shuffle_ps(x0, x1, _MM_SHUFFLE(2, 0, 2, 0)); + + x0 = _mm_div_ps(glmm_set1(1.0f), glmm_vhadd(_mm_mul_ps(x0, r0))); + + glmm_store(dest[0], _mm_mul_ps(v0, x0)); + glmm_store(dest[1], _mm_mul_ps(v1, x0)); + glmm_store(dest[2], _mm_mul_ps(v2, x0)); + glmm_store(dest[3], _mm_mul_ps(v3, x0)); +} +#endif + +CGLM_INLINE +void +glm_mat4_inv_sse2(mat4 mat, mat4 dest) { + __m128 r0, r1, r2, r3, s1, s2, + v0, v1, v2, v3, v4, v5, + t0, t1, t2, + x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13; + + /* s1 = _mm_set_ps(-0.f, 0.f, -0.f, 0.f); */ + s1 = glmm_float32x4_SIGNMASK_NPNP; + s2 = glmm_shuff1(s1, 2, 1, 2, 1); + + /* 127 <- 0 */ + r1 = glmm_load(mat[1]); /* h g f e */ + r0 = glmm_load(mat[0]); /* d c b a */ + r3 = glmm_load(mat[3]); /* p o n m */ + r2 = glmm_load(mat[2]); /* l k j i */ + + x4 = _mm_unpackhi_ps(r0, r2); /* l d k c */ + x5 = _mm_unpacklo_ps(r0, r2); /* j b i a */ + x6 = _mm_unpackhi_ps(r1, r3); /* p h o g */ + x7 = _mm_unpacklo_ps(r1, r3); /* n f m e */ + + x0 = _mm_unpackhi_ps(x7, x5); /* j n b f */ + x1 = _mm_unpacklo_ps(x7, x5); /* i m a e */ + x2 = _mm_unpackhi_ps(x6, x4); /* l p d h */ + x3 = _mm_unpacklo_ps(x6, x4); /* k o c g */ + + /* c2 = c * h - d * g c12 = a * g - c * e c8 = a * f - b * e + c1 = k * p - l * o c11 = i * o - k * m c7 = i * n - j * m + c4 = a * h - d * e c6 = b * h - d * f c10 = b * g - c * f + c3 = i * p - l * m c5 = j * p - l * n c9 = j * o - k * n */ + + x8 = _mm_shuffle_ps(x0, x3, _MM_SHUFFLE(3, 1, 3, 1)); /* k c j b */ + x9 = _mm_shuffle_ps(x0, x3, _MM_SHUFFLE(2, 0, 2, 0)); /* o g n f */ + + x10 = glmm_shuff1(x2, 2, 0, 2, 0); /* p h p h */ + x11 = glmm_shuff1(x2, 3, 1, 3, 1); /* l d l d */ + +#if 0 /* TODO measure both */ + x12 = _mm_shuffle_ps(x4, x5, _MM_SHUFFLE(1, 0, 1, 0)); /* i a k c */ + x13 = _mm_shuffle_ps(x6, x7, _MM_SHUFFLE(1, 0, 1, 0)); /* m e o g */ +#else + x12 = _mm_movelh_ps(x4, x5); /* i a k c */ + x13 = _mm_movelh_ps(x6, x7); /* m e o g */ +#endif + + t0 = _mm_mul_ps(x12, x10); + t1 = _mm_mul_ps(x5, x6); + t2 = _mm_mul_ps(x5, x9); + + t0 = glmm_fnmadd(x11, x13, t0); + t1 = glmm_fnmadd(x4, x7, t1); + t2 = glmm_fnmadd(x8, x7, t2); + + /* det */ + /* v0: c3 * c10 + c4 * c9 + c1 * c8 + c2 * c7 */ + /* v1: c5 * c12 + c6 * c11 */ + + v5 = glmm_set1_rval(1.0f); + v0 = glmm_shuff1(t2, 2, 3, 0, 1); + v1 = glmm_shuff1(t1, 0, 1, 2, 3); + v0 = _mm_mul_ps(t0, v0); + v1 = _mm_mul_ps(t1, v1); + v2 = glmm_shuff1(v1, 1, 0, 0, 1); + v3 = glmm_shuff1(v0, 0, 1, 2, 3); + v1 = _mm_add_ps(v1, v2); + v0 = _mm_add_ps(v0, v3); + v2 = glmm_shuff1(v0, 1, 0, 0, 1); + v0 = _mm_add_ps(v0, v2); + + v0 = _mm_sub_ps(v0, v1); /* det */ + v0 = _mm_div_ps(v5, v0); /* idt */ + + /* multiply t0,t1,t2 by idt to reduce 1mul below: 2eor+4mul vs 3mul+4eor */ + t0 = _mm_mul_ps(t0, v0); + t1 = _mm_mul_ps(t1, v0); + t2 = _mm_mul_ps(t2, v0); + + v0 = glmm_shuff1(t0, 0, 0, 1, 1); /* c2 c2 c1 c1 */ + v1 = glmm_shuff1(t0, 2, 2, 3, 3); /* c4 c4 c3 c3 */ + v2 = glmm_shuff1(t1, 0, 0, 1, 1); /* c12 c12 c11 c11 */ + v3 = glmm_shuff1(t1, 2, 2, 3, 3); /* c6 c6 c5 c5 */ + v4 = glmm_shuff1(t2, 0, 0, 1, 1); /* c8 c8 c7 c7 */ + v5 = glmm_shuff1(t2, 2, 2, 3, 3); /* c10 c10 c9 c9 */ + + /* result */ + + /* dest[0][0] = (f * c1 - g * c5 + h * c9) * idt; + dest[0][1] = (b * c1 - c * c5 + d * c9) * ndt; + dest[0][2] = (n * c2 - o * c6 + p * c10) * idt; + dest[0][3] = (j * c2 - k * c6 + l * c10) * ndt; + + dest[1][0] = (e * c1 - g * c3 + h * c11) * ndt; + dest[1][1] = (a * c1 - c * c3 + d * c11) * idt; + dest[1][2] = (m * c2 - o * c4 + p * c12) * ndt; + dest[1][3] = (i * c2 - k * c4 + l * c12) * idt; + + dest[2][0] = (e * c5 - f * c3 + h * c7) * idt; + dest[2][1] = (a * c5 - b * c3 + d * c7) * ndt; + dest[2][2] = (m * c6 - n * c4 + p * c8) * idt; + dest[2][3] = (i * c6 - j * c4 + l * c8) * ndt; + + dest[3][0] = (e * c9 - f * c11 + g * c7) * ndt; + dest[3][1] = (a * c9 - b * c11 + c * c7) * idt; + dest[3][2] = (m * c10 - n * c12 + o * c8) * ndt; + dest[3][3] = (i * c10 - j * c12 + k * c8) * idt; */ + + r0 = _mm_mul_ps(x0, v0); + r1 = _mm_mul_ps(x1, v0); + r2 = _mm_mul_ps(x1, v3); + r3 = _mm_mul_ps(x1, v5); + + r0 = glmm_fnmadd(x3, v3, r0); + r1 = glmm_fnmadd(x3, v1, r1); + r2 = glmm_fnmadd(x0, v1, r2); + r3 = glmm_fnmadd(x0, v2, r3); + + r0 = glmm_fmadd(x2, v5, r0); + r1 = glmm_fmadd(x2, v2, r1); + r2 = glmm_fmadd(x2, v4, r2); + r3 = glmm_fmadd(x3, v4, r3); + + /* 4xor may be fastart then 4mul, see above */ + r0 = _mm_xor_ps(r0, s1); + r1 = _mm_xor_ps(r1, s2); + r2 = _mm_xor_ps(r2, s1); + r3 = _mm_xor_ps(r3, s2); + + glmm_store(dest[0], r0); + glmm_store(dest[1], r1); + glmm_store(dest[2], r2); + glmm_store(dest[3], r3); +} +#endif +#endif /* cglm_mat_sse_h */ diff --git a/external/cglm/simd/sse2/quat.h b/external/cglm/simd/sse2/quat.h new file mode 100644 index 0000000..def0fe2 --- /dev/null +++ b/external/cglm/simd/sse2/quat.h @@ -0,0 +1,54 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_quat_simd_h +#define cglm_quat_simd_h +#if defined( __SSE__ ) || defined( __SSE2__ ) + +#include "../../common.h" +#include "../intrin.h" + +CGLM_INLINE +void +glm_quat_mul_sse2(versor p, versor q, versor dest) { + /* + + (a1 b2 + b1 a2 + c1 d2 − d1 c2)i + + (a1 c2 − b1 d2 + c1 a2 + d1 b2)j + + (a1 d2 + b1 c2 − c1 b2 + d1 a2)k + a1 a2 − b1 b2 − c1 c2 − d1 d2 + */ + + __m128 xp, xq, x1, x2, x3, r, x, y, z; + + xp = glmm_load(p); /* 3 2 1 0 */ + xq = glmm_load(q); + x1 = glmm_float32x4_SIGNMASK_NPNP; /* TODO: _mm_set1_ss() + shuff ? */ + r = _mm_mul_ps(glmm_splat_w(xp), xq); + + x2 = _mm_unpackhi_ps(x1, x1); + x3 = glmm_shuff1(x1, 3, 2, 0, 1); + x = glmm_splat_x(xp); + y = glmm_splat_y(xp); + z = glmm_splat_z(xp); + + x = _mm_xor_ps(x, x1); + y = _mm_xor_ps(y, x2); + z = _mm_xor_ps(z, x3); + + x1 = glmm_shuff1(xq, 0, 1, 2, 3); + x2 = glmm_shuff1(xq, 1, 0, 3, 2); + x3 = glmm_shuff1(xq, 2, 3, 0, 1); + + r = glmm_fmadd(x, x1, r); + r = glmm_fmadd(y, x2, r); + r = glmm_fmadd(z, x3, r); + + glmm_store(dest, r); +} + +#endif +#endif /* cglm_quat_simd_h */ diff --git a/external/cglm/simd/wasm.h b/external/cglm/simd/wasm.h new file mode 100644 index 0000000..2ced51f --- /dev/null +++ b/external/cglm/simd/wasm.h @@ -0,0 +1,198 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_simd_wasm_h +#define cglm_simd_wasm_h +#include "intrin.h" +#ifdef CGLM_SIMD_WASM +#include + +#define glmm_load(p) wasm_v128_load(p) +#define glmm_store(p, a) wasm_v128_store(p, (a)) + +#define glmm_set1(x) wasm_f32x4_splat(x) +#define glmm_set1_ptr(x) wasm_f32x4_splat(*x) +#define glmm_set1_rval(x) wasm_f32x4_splat(x) +#define glmm_128 v128_t + +#define glmm_shuff1(xmm, z, y, x, w) wasm_i32x4_shuffle(xmm, xmm, w, x, y, z) + +#define glmm_splat(x, lane) glmm_shuff1(x, lane, lane, lane, lane) + +#define glmm_splat_x(x) glmm_splat(x, 0) +#define glmm_splat_y(x) glmm_splat(x, 1) +#define glmm_splat_z(x) glmm_splat(x, 2) +#define glmm_splat_w(x) glmm_splat(x, 3) + +#define GLMM_NEGZEROf 0x80000000 /* 0x80000000 ---> -0.0f */ + +/* _mm_set_ps(X, Y, Z, W); */ +#define GLMM__SIGNMASKf(X, Y, Z, W) wasm_i32x4_const(X, Y, Z, W) + +#define glmm_float32x4_SIGNMASK_PNPN GLMM__SIGNMASKf(0, GLMM_NEGZEROf, 0, GLMM_NEGZEROf) +#define glmm_float32x4_SIGNMASK_NPNP GLMM__SIGNMASKf(GLMM_NEGZEROf, 0, GLMM_NEGZEROf, 0) +#define glmm_float32x4_SIGNMASK_NPPN GLMM__SIGNMASKf(GLMM_NEGZEROf, 0, 0, GLMM_NEGZEROf) +#define glmm_float32x4_SIGNMASK_NEG wasm_i32x4_const_splat(GLMM_NEGZEROf) + +static inline glmm_128 glmm_abs(glmm_128 x) { return wasm_f32x4_abs(x); } +static inline glmm_128 glmm_min(glmm_128 a, glmm_128 b) { return wasm_f32x4_pmin(b, a); } +static inline glmm_128 glmm_max(glmm_128 a, glmm_128 b) { return wasm_f32x4_pmax(b, a); } + +static inline +glmm_128 +glmm_vhadd(glmm_128 v) { + glmm_128 x0; + x0 = wasm_f32x4_add(v, glmm_shuff1(v, 0, 1, 2, 3)); + x0 = wasm_f32x4_add(x0, glmm_shuff1(x0, 1, 0, 0, 1)); + return x0; +} + +static inline +glmm_128 +glmm_vhadds(glmm_128 v) { + glmm_128 shuf, sums; + shuf = glmm_shuff1(v, 2, 3, 0, 1); + sums = wasm_f32x4_add(v, shuf); + /* shuf = _mm_movehl_ps(shuf, sums); */ + shuf = wasm_i32x4_shuffle(shuf, sums, 6, 7, 2, 3); + sums = wasm_i32x4_shuffle(sums, wasm_f32x4_add(sums, shuf), 4, 1, 2, 3); + return sums; +} + +static inline +float +glmm_hadd(glmm_128 v) { + return wasm_f32x4_extract_lane(glmm_vhadds(v), 0); +} + +static inline +glmm_128 +glmm_vhmin(glmm_128 v) { + glmm_128 x0, x1, x2; + x0 = glmm_shuff1(v, 2, 3, 2, 3); /* [2, 3, 2, 3] */ + x1 = wasm_f32x4_pmin(x0, v); /* [0|2, 1|3, 2|2, 3|3] */ + x2 = glmm_splat(x1, 1); /* [1|3, 1|3, 1|3, 1|3] */ + return wasm_f32x4_pmin(x1, x2); +} + +static inline +float +glmm_hmin(glmm_128 v) { + return wasm_f32x4_extract_lane(glmm_vhmin(v), 0); +} + +static inline +glmm_128 +glmm_vhmax(glmm_128 v) { + glmm_128 x0, x1, x2; + x0 = glmm_shuff1(v, 2, 3, 2, 3); /* [2, 3, 2, 3] */ + x1 = wasm_f32x4_pmax(x0, v); /* [0|2, 1|3, 2|2, 3|3] */ + x2 = glmm_splat(x1, 1); /* [1|3, 1|3, 1|3, 1|3] */ + /* _mm_max_ss */ + return wasm_i32x4_shuffle(x1, wasm_f32x4_pmax(x1, x2), 4, 1, 2, 3); +} + +static inline +float +glmm_hmax(glmm_128 v) { + return wasm_f32x4_extract_lane(glmm_vhmax(v), 0); +} + +static inline +glmm_128 +glmm_vdots(glmm_128 a, glmm_128 b) { + return glmm_vhadds(wasm_f32x4_mul(a, b)); +} + +static inline +glmm_128 +glmm_vdot(glmm_128 a, glmm_128 b) { + glmm_128 x0; + x0 = wasm_f32x4_mul(a, b); + x0 = wasm_f32x4_add(x0, glmm_shuff1(x0, 1, 0, 3, 2)); + return wasm_f32x4_add(x0, glmm_shuff1(x0, 0, 1, 0, 1)); +} + +static inline +float +glmm_dot(glmm_128 a, glmm_128 b) { + return wasm_f32x4_extract_lane(glmm_vdots(a, b), 0); +} + +static inline +float +glmm_norm(glmm_128 a) { + glmm_128 x0; + x0 = glmm_vhadds(wasm_f32x4_mul(a, a)); + return wasm_f32x4_extract_lane( + wasm_i32x4_shuffle(x0, wasm_f32x4_sqrt(x0),4, 1, 2, 3), 0); +} + +static inline +float +glmm_norm2(glmm_128 a) { + return wasm_f32x4_extract_lane(glmm_vhadds(wasm_f32x4_mul(a, a)), 0); +} + +static inline +float +glmm_norm_one(glmm_128 a) { + return wasm_f32x4_extract_lane(glmm_vhadds(glmm_abs(a)), 0); +} + +static inline +float +glmm_norm_inf(glmm_128 a) { + return wasm_f32x4_extract_lane(glmm_vhmax(glmm_abs(a)), 0); +} + +static inline +glmm_128 +glmm_load3(float v[3]) { + glmm_128 xy = wasm_v128_load64_zero(v); + return wasm_f32x4_replace_lane(xy, 2, v[2]); +} + +static inline +void +glmm_store3(float v[3], glmm_128 vx) { + wasm_v128_store64_lane(v, vx, 0); + wasm_v128_store32_lane(&v[2], vx, 2); +} + +static inline +glmm_128 +glmm_div(glmm_128 a, glmm_128 b) { + return wasm_f32x4_div(a, b); +} + +static inline +glmm_128 +glmm_fmadd(glmm_128 a, glmm_128 b, glmm_128 c) { + return wasm_f32x4_add(c, wasm_f32x4_mul(a, b)); +} + +static inline +glmm_128 +glmm_fnmadd(glmm_128 a, glmm_128 b, glmm_128 c) { + return wasm_f32x4_sub(c, wasm_f32x4_mul(a, b)); +} + +static inline +glmm_128 +glmm_fmsub(glmm_128 a, glmm_128 b, glmm_128 c) { + return wasm_f32x4_sub(wasm_f32x4_mul(a, b), c); +} + +static inline +glmm_128 +glmm_fnmsub(glmm_128 a, glmm_128 b, glmm_128 c) { + return wasm_f32x4_neg(wasm_f32x4_add(wasm_f32x4_mul(a, b), c)); +} + +#endif +#endif /* cglm_simd_wasm_h */ diff --git a/external/cglm/simd/wasm/affine.h b/external/cglm/simd/wasm/affine.h new file mode 100644 index 0000000..80b98fb --- /dev/null +++ b/external/cglm/simd/wasm/affine.h @@ -0,0 +1,127 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_affine_mat_wasm_h +#define cglm_affine_mat_wasm_h +#if defined(__wasm__) && defined(__wasm_simd128__) + +#include "../../common.h" +#include "../intrin.h" + +CGLM_INLINE +void +glm_mul_wasm(mat4 m1, mat4 m2, mat4 dest) { + /* D = R * L (Column-Major) */ + glmm_128 l, r0, r1, r2, r3, v0, v1, v2, v3; + + l = glmm_load(m1[0]); + r0 = glmm_load(m2[0]); + r1 = glmm_load(m2[1]); + r2 = glmm_load(m2[2]); + r3 = glmm_load(m2[3]); + + v0 = wasm_f32x4_mul(glmm_splat_x(r0), l); + v1 = wasm_f32x4_mul(glmm_splat_x(r1), l); + v2 = wasm_f32x4_mul(glmm_splat_x(r2), l); + v3 = wasm_f32x4_mul(glmm_splat_x(r3), l); + + l = glmm_load(m1[1]); + v0 = glmm_fmadd(glmm_splat_y(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_y(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_y(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_y(r3), l, v3); + + l = glmm_load(m1[2]); + v0 = glmm_fmadd(glmm_splat_z(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_z(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_z(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_z(r3), l, v3); + + l = glmm_load(m1[3]); + v3 = glmm_fmadd(glmm_splat_w(r3), l, v3); + + glmm_store(dest[0], v0); + glmm_store(dest[1], v1); + glmm_store(dest[2], v2); + glmm_store(dest[3], v3); +} + +CGLM_INLINE +void +glm_mul_rot_wasm(mat4 m1, mat4 m2, mat4 dest) { + /* D = R * L (Column-Major) */ + + glmm_128 l, r0, r1, r2, v0, v1, v2; + + l = glmm_load(m1[0]); + r0 = glmm_load(m2[0]); + r1 = glmm_load(m2[1]); + r2 = glmm_load(m2[2]); + + v0 = wasm_f32x4_mul(glmm_splat_x(r0), l); + v1 = wasm_f32x4_mul(glmm_splat_x(r1), l); + v2 = wasm_f32x4_mul(glmm_splat_x(r2), l); + + l = glmm_load(m1[1]); + v0 = glmm_fmadd(glmm_splat_y(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_y(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_y(r2), l, v2); + + l = glmm_load(m1[2]); + v0 = glmm_fmadd(glmm_splat_z(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_z(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_z(r2), l, v2); + + glmm_store(dest[0], v0); + glmm_store(dest[1], v1); + glmm_store(dest[2], v2); + glmm_store(dest[3], glmm_load(m1[3])); +} + +CGLM_INLINE +void +glm_inv_tr_wasm(mat4 mat) { + glmm_128 r0, r1, r2, r3, x0, x1, x2, x3, x4, x5; + + r0 = glmm_load(mat[0]); + r1 = glmm_load(mat[1]); + r2 = glmm_load(mat[2]); + r3 = glmm_load(mat[3]); + x1 = wasm_f32x4_const(0.0f, 0.0f, 0.0f, 1.0f); + + /* _MM_TRANSPOSE4_PS(r0, r1, r2, x1); */ + x2 = wasm_i32x4_shuffle(r0, r1, 0, 4, 1, 5); + x3 = wasm_i32x4_shuffle(r0, r1, 2, 6, 3, 7); + x4 = wasm_i32x4_shuffle(r2, x1, 0, 4, 1, 5); + x5 = wasm_i32x4_shuffle(r2, x1, 2, 6, 3, 7); + /* r0 = _mm_movelh_ps(x2, x4); */ + r0 = wasm_i32x4_shuffle(x2, x4, 0, 1, 4, 5); + /* r1 = _mm_movehl_ps(x4, x2); */ + r1 = wasm_i32x4_shuffle(x4, x2, 6, 7, 2, 3); + /* r2 = _mm_movelh_ps(x3, x5); */ + r2 = wasm_i32x4_shuffle(x3, x5, 0, 1, 4, 5); + /* x1 = _mm_movehl_ps(x5, x3); */ + x1 = wasm_i32x4_shuffle(x5, x3, 6, 7, 2, 3); + + x2 = glmm_shuff1(r3, 0, 0, 0, 0); + x3 = glmm_shuff1(r3, 1, 1, 1, 1); + x4 = glmm_shuff1(r3, 2, 2, 2, 2); + + x0 = glmm_fmadd(r0, x2, + glmm_fmadd(r1, x3, wasm_f32x4_mul(r2, x4))); + x0 = wasm_f32x4_neg(x0); + + x0 = wasm_f32x4_add(x0, x1); + + glmm_store(mat[0], r0); + glmm_store(mat[1], r1); + glmm_store(mat[2], r2); + glmm_store(mat[3], x0); +} + +#endif +#endif /* cglm_affine_mat_wasm_h */ diff --git a/external/cglm/simd/wasm/mat2.h b/external/cglm/simd/wasm/mat2.h new file mode 100644 index 0000000..80ce0fb --- /dev/null +++ b/external/cglm/simd/wasm/mat2.h @@ -0,0 +1,50 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_mat2_wasm_h +#define cglm_mat2_wasm_h +#if defined(__wasm__) && defined(__wasm_simd128__) + +#include "../../common.h" +#include "../intrin.h" + +CGLM_INLINE +void +glm_mat2_mul_wasm(mat2 m1, mat2 m2, mat2 dest) { + glmm_128 x0, x1, x2, x3, x4; + + x1 = glmm_load(m1[0]); /* d c b a */ + x2 = glmm_load(m2[0]); /* h g f e */ + + x3 = glmm_shuff1(x2, 2, 2, 0, 0); + x4 = glmm_shuff1(x2, 3, 3, 1, 1); + /* x0 = _mm_movelh_ps(x1, x1); */ + x0 = wasm_i32x4_shuffle(x1, x1, 0, 1, 4, 5); + /* x2 = _mm_movehl_ps(x1, x1); */ + x2 = wasm_i32x4_shuffle(x1, x1, 6, 7, 2, 3); + + /* + dest[0][0] = a * e + c * f; + dest[0][1] = b * e + d * f; + dest[1][0] = a * g + c * h; + dest[1][1] = b * g + d * h; + */ + x0 = glmm_fmadd(x0, x3, wasm_f32x4_mul(x2, x4)); + + glmm_store(dest[0], x0); +} + +CGLM_INLINE +void +glm_mat2_transp_wasm(mat2 m, mat2 dest) { + /* d c b a */ + /* d b c a */ + glmm_store(dest[0], glmm_shuff1(glmm_load(m[0]), 3, 1, 2, 0)); +} + +#endif +#endif /* cglm_mat2_wasm_h */ diff --git a/external/cglm/simd/wasm/mat3.h b/external/cglm/simd/wasm/mat3.h new file mode 100644 index 0000000..dfe192d --- /dev/null +++ b/external/cglm/simd/wasm/mat3.h @@ -0,0 +1,85 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_mat3_wasm_h +#define cglm_mat3_wasm_h +#if defined(__wasm__) && defined(__wasm_simd128__) + +#include "../../common.h" +#include "../intrin.h" + +CGLM_INLINE +void +glm_mat3_mul_wasm(mat3 m1, mat3 m2, mat3 dest) { + glmm_128 l0, l1, l2, r0, r1, r2, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9; + + l0 = wasm_v128_load(m1[0]); + l1 = wasm_v128_load(&m1[1][1]); + + r0 = wasm_v128_load(m2[0]); + r1 = wasm_v128_load(&m2[1][1]); + + x8 = glmm_shuff1(l0, 0, 2, 1, 0); /* a00 a02 a01 a00 */ + x1 = glmm_shuff1(r0, 3, 0, 0, 0); /* b10 b00 b00 b00 */ + x2 = wasm_i32x4_shuffle(l0, l1, 3, 3, 4, 5); /* a12 a11 a10 a10 */ + x3 = wasm_i32x4_shuffle(r0, r1, 1, 3, 4, 6); /* b20 b11 b10 b01 */ + x0 = wasm_f32x4_mul(x8, x1); + + x6 = glmm_shuff1(l0, 1, 0, 2, 1); /* a01 a00 a02 a01 */ + x7 = glmm_shuff1(x3, 3, 3, 1, 1); /* b20 b20 b10 b10 */ + l2 = wasm_v128_load32_zero(&m1[2][2]); + r2 = wasm_v128_load32_zero(&m2[2][2]); + x1 = wasm_f32x4_mul(x6, x7); + l2 = glmm_shuff1(l2, 0, 0, 1, 0); /* a22 a22 0.f a22 */ + r2 = glmm_shuff1(r2, 0, 0, 1, 0); /* b22 b22 0.f b22 */ + + x4 = glmm_shuff1(x2, 0, 3, 2, 0); /* a10 a12 a11 a10 */ + x5 = glmm_shuff1(x2, 2, 0, 3, 2); /* a11 a10 a12 a11 */ + x6 = glmm_shuff1(x3, 2, 0, 0, 0); /* b11 b01 b01 b01 */ + x2 = glmm_shuff1(r1, 3, 3, 0, 0); /* b21 b21 b11 b11 */ + + /* x8 = _mm_unpackhi_ps(x8, x4); */ + /* x9 = _mm_unpackhi_ps(x7, x2); */ + x8 = wasm_i32x4_shuffle(x8, x4, 2, 6, 3, 7); /* a10 a00 a12 a02 */ + x9 = wasm_i32x4_shuffle(x7, x2, 2, 6, 3, 7); /* b21 b20 b21 b20 */ + + x0 = glmm_fmadd(x4, x6, x0); + x1 = glmm_fmadd(x5, x2, x1); + + /* x2 = _mm_movehl_ps(l2, l1); */ + x2 = wasm_i32x4_shuffle(l2, l1, 6, 7, 2, 3); /* a22 a22 a21 a20 */ + x3 = glmm_shuff1(x2, 0, 2, 1, 0); /* a20 a22 a21 a20 */ + x2 = glmm_shuff1(x2, 1, 0, 2, 1); /* a21 a20 a22 a21 */ + x4 = wasm_i32x4_shuffle(r0, r1, 2, 2, 5, 5); /* b12 b12 b02 b02 */ + + x5 = glmm_shuff1(x4, 3, 0, 0, 0); /* b12 b02 b02 b02 */ + /* x4 = _mm_movehl_ps(r2, x4); */ + x4 = wasm_i32x4_shuffle(r2, x4, 6, 7, 2, 3); /* b22 b22 b12 b12 */ + x0 = glmm_fmadd(x3, x5, x0); + x1 = glmm_fmadd(x2, x4, x1); + + /* + Dot Product : dest[2][2] = a02 * b20 + + a12 * b21 + + a22 * b22 + + 0 * 00 */ + /* x2 = _mm_movelh_ps(x8, l2); */ + /* x3 = _mm_movelh_ps(x9, r2); */ + x2 = wasm_i32x4_shuffle(x8, l2, 0, 1, 4, 5); /* 0.f a22 a12 a02 */ + x3 = wasm_i32x4_shuffle(x9, r2, 0, 1, 4, 5); /* 0.f b22 b21 b20 */ + x2 = glmm_vdots(x2, x3); + + /* _mm_storeu_ps(&dest[0][0], x0); */ + wasm_v128_store(&dest[0][0], x0); + /* _mm_storeu_ps(&dest[1][1], x1); */ + wasm_v128_store(&dest[1][1], x1); + /* _mm_store_ss (&dest[2][2], x2); */ + wasm_v128_store32_lane(&dest[2][2], x2, 0); +} + +#endif +#endif /* cglm_mat3_wasm_h */ diff --git a/external/cglm/simd/wasm/mat4.h b/external/cglm/simd/wasm/mat4.h new file mode 100644 index 0000000..79ed688 --- /dev/null +++ b/external/cglm/simd/wasm/mat4.h @@ -0,0 +1,454 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_mat_wasm_h +#define cglm_mat_wasm_h +#if defined(__wasm__) && defined(__wasm_simd128__) + +#include "../../common.h" +#include "../intrin.h" + +#define glm_mat4_inv_precise_wasm(mat, dest) glm_mat4_inv_wasm(mat, dest) + +CGLM_INLINE +void +glm_mat4_scale_wasm(mat4 m, float s) { + glmm_128 x0; + x0 = wasm_f32x4_splat(s); + + glmm_store(m[0], wasm_f32x4_mul(glmm_load(m[0]), x0)); + glmm_store(m[1], wasm_f32x4_mul(glmm_load(m[1]), x0)); + glmm_store(m[2], wasm_f32x4_mul(glmm_load(m[2]), x0)); + glmm_store(m[3], wasm_f32x4_mul(glmm_load(m[3]), x0)); +} + +CGLM_INLINE +void +glm_mat4_transp_wasm(mat4 m, mat4 dest) { + glmm_128 r0, r1, r2, r3, tmp0, tmp1, tmp2, tmp3; + + r0 = glmm_load(m[0]); + r1 = glmm_load(m[1]); + r2 = glmm_load(m[2]); + r3 = glmm_load(m[3]); + + /* _MM_TRANSPOSE4_PS(r0, r1, r2, r3); */ + tmp0 = wasm_i32x4_shuffle(r0, r1, 0, 4, 1, 5); + tmp1 = wasm_i32x4_shuffle(r0, r1, 2, 6, 3, 7); + tmp2 = wasm_i32x4_shuffle(r2, r3, 0, 4, 1, 5); + tmp3 = wasm_i32x4_shuffle(r2, r3, 2, 6, 3, 7); + /* r0 = _mm_movelh_ps(tmp0, tmp2); */ + r0 = wasm_i32x4_shuffle(tmp0, tmp2, 0, 1, 4, 5); + /* r1 = _mm_movehl_ps(tmp2, tmp0); */ + r1 = wasm_i32x4_shuffle(tmp2, tmp0, 6, 7, 2, 3); + /* r2 = _mm_movelh_ps(tmp1, tmp3); */ + r2 = wasm_i32x4_shuffle(tmp1, tmp3, 0, 1, 4, 5); + /* r3 = _mm_movehl_ps(tmp3, tmp1); */ + r3 = wasm_i32x4_shuffle(tmp3, tmp1, 6, 7, 2, 3); + + glmm_store(dest[0], r0); + glmm_store(dest[1], r1); + glmm_store(dest[2], r2); + glmm_store(dest[3], r3); +} + +CGLM_INLINE +void +glm_mat4_mul_wasm(mat4 m1, mat4 m2, mat4 dest) { + /* D = R * L (Column-Major) */ + + glmm_128 l, r0, r1, r2, r3, v0, v1, v2, v3; + + l = glmm_load(m1[0]); + r0 = glmm_load(m2[0]); + r1 = glmm_load(m2[1]); + r2 = glmm_load(m2[2]); + r3 = glmm_load(m2[3]); + + v0 = wasm_f32x4_mul(glmm_splat_x(r0), l); + v1 = wasm_f32x4_mul(glmm_splat_x(r1), l); + v2 = wasm_f32x4_mul(glmm_splat_x(r2), l); + v3 = wasm_f32x4_mul(glmm_splat_x(r3), l); + + l = glmm_load(m1[1]); + v0 = glmm_fmadd(glmm_splat_y(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_y(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_y(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_y(r3), l, v3); + + l = glmm_load(m1[2]); + v0 = glmm_fmadd(glmm_splat_z(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_z(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_z(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_z(r3), l, v3); + + l = glmm_load(m1[3]); + v0 = glmm_fmadd(glmm_splat_w(r0), l, v0); + v1 = glmm_fmadd(glmm_splat_w(r1), l, v1); + v2 = glmm_fmadd(glmm_splat_w(r2), l, v2); + v3 = glmm_fmadd(glmm_splat_w(r3), l, v3); + + glmm_store(dest[0], v0); + glmm_store(dest[1], v1); + glmm_store(dest[2], v2); + glmm_store(dest[3], v3); +} + +CGLM_INLINE +void +glm_mat4_mulv_wasm(mat4 m, vec4 v, vec4 dest) { + glmm_128 x0, x1, m0, m1, m2, m3, v0, v1, v2, v3; + + m0 = glmm_load(m[0]); + m1 = glmm_load(m[1]); + m2 = glmm_load(m[2]); + m3 = glmm_load(m[3]); + + x0 = glmm_load(v); + v0 = glmm_splat_x(x0); + v1 = glmm_splat_y(x0); + v2 = glmm_splat_z(x0); + v3 = glmm_splat_w(x0); + + x1 = wasm_f32x4_mul(m3, v3); + x1 = glmm_fmadd(m2, v2, x1); + x1 = glmm_fmadd(m1, v1, x1); + x1 = glmm_fmadd(m0, v0, x1); + + glmm_store(dest, x1); +} + +CGLM_INLINE +float +glm_mat4_det_wasm(mat4 mat) { + glmm_128 r0, r1, r2, r3, x0, x1, x2; + + /* 127 <- 0, [square] det(A) = det(At) */ + r0 = glmm_load(mat[0]); /* d c b a */ + r1 = glmm_load(mat[1]); /* h g f e */ + r2 = glmm_load(mat[2]); /* l k j i */ + r3 = glmm_load(mat[3]); /* p o n m */ + + /* + t[1] = j * p - n * l; + t[2] = j * o - n * k; + t[3] = i * p - m * l; + t[4] = i * o - m * k; + */ + x0 = glmm_fnmadd(glmm_shuff1(r3, 0, 0, 1, 1), glmm_shuff1(r2, 2, 3, 2, 3), + wasm_f32x4_mul(glmm_shuff1(r2, 0, 0, 1, 1), + glmm_shuff1(r3, 2, 3, 2, 3))); + /* + t[0] = k * p - o * l; + t[0] = k * p - o * l; + t[5] = i * n - m * j; + t[5] = i * n - m * j; + */ + x1 = glmm_fnmadd(glmm_shuff1(r3, 0, 0, 2, 2), glmm_shuff1(r2, 1, 1, 3, 3), + wasm_f32x4_mul(glmm_shuff1(r2, 0, 0, 2, 2), + glmm_shuff1(r3, 1, 1, 3, 3))); + + /* + a * (f * t[0] - g * t[1] + h * t[2]) + - b * (e * t[0] - g * t[3] + h * t[4]) + + c * (e * t[1] - f * t[3] + h * t[5]) + - d * (e * t[2] - f * t[4] + g * t[5]) + */ + x2 = glmm_fnmadd(glmm_shuff1(r1, 1, 1, 2, 2), glmm_shuff1(x0, 3, 2, 2, 0), + wasm_f32x4_mul(glmm_shuff1(r1, 0, 0, 0, 1), + wasm_i32x4_shuffle(x1, x0, 0, 0, 4, 5))); + x2 = glmm_fmadd(glmm_shuff1(r1, 2, 3, 3, 3), + wasm_i32x4_shuffle(x0, x1, 1, 3, 6, 6), + x2); + /* x2 = wasm_v128_xor(x2, wasm_f32x4_const(0.f, -0.f, 0.f, -0.f)); */ + x2 = wasm_v128_xor(x2, glmm_float32x4_SIGNMASK_PNPN); + + return glmm_hadd(wasm_f32x4_mul(x2, r0)); +} + +CGLM_INLINE +void +glm_mat4_inv_fast_wasm(mat4 mat, mat4 dest) { + glmm_128 r0, r1, r2, r3, + v0, v1, v2, v3, + t0, t1, t2, t3, t4, t5, + x0, x1, x2, x3, x4, x5, x6, x7, x8, x9; + + /* x8 = wasm_f32x4_const(0.f, -0.f, 0.f, -0.f); */ + x8 = glmm_float32x4_SIGNMASK_PNPN; + x9 = glmm_shuff1(x8, 2, 1, 2, 1); + + /* 127 <- 0 */ + r0 = glmm_load(mat[0]); /* d c b a */ + r1 = glmm_load(mat[1]); /* h g f e */ + r2 = glmm_load(mat[2]); /* l k j i */ + r3 = glmm_load(mat[3]); /* p o n m */ + /* x0 = _mm_movehl_ps(r3, r2); */ + x0 = wasm_i32x4_shuffle(r3, r2, 6, 7, 2, 3); /* p o l k */ + /* x3 = _mm_movelh_ps(r2, r3); */ + x3 = wasm_i32x4_shuffle(r2, r3, 0, 1, 4, 5); /* n m j i */ + x1 = glmm_shuff1(x0, 1, 3, 3 ,3); /* l p p p */ + x2 = glmm_shuff1(x0, 0, 2, 2, 2); /* k o o o */ + x4 = glmm_shuff1(x3, 1, 3, 3, 3); /* j n n n */ + x7 = glmm_shuff1(x3, 0, 2, 2, 2); /* i m m m */ + + x6 = wasm_i32x4_shuffle(r2, r1, 0, 0, 4, 4); /* e e i i */ + x5 = wasm_i32x4_shuffle(r2, r1, 1, 1, 5, 5); /* f f j j */ + x3 = wasm_i32x4_shuffle(r2, r1, 2, 2, 6, 6); /* g g k k */ + x0 = wasm_i32x4_shuffle(r2, r1, 3, 3, 7, 7); /* h h l l */ + + t0 = wasm_f32x4_mul(x3, x1); + t1 = wasm_f32x4_mul(x5, x1); + t2 = wasm_f32x4_mul(x5, x2); + t3 = wasm_f32x4_mul(x6, x1); + t4 = wasm_f32x4_mul(x6, x2); + t5 = wasm_f32x4_mul(x6, x4); + + /* t1[0] = k * p - o * l; + t1[0] = k * p - o * l; + t2[0] = g * p - o * h; + t3[0] = g * l - k * h; */ + t0 = glmm_fnmadd(x2, x0, t0); + + /* t1[1] = j * p - n * l; + t1[1] = j * p - n * l; + t2[1] = f * p - n * h; + t3[1] = f * l - j * h; */ + t1 = glmm_fnmadd(x4, x0, t1); + + /* t1[2] = j * o - n * k + t1[2] = j * o - n * k; + t2[2] = f * o - n * g; + t3[2] = f * k - j * g; */ + t2 = glmm_fnmadd(x4, x3, t2); + + /* t1[3] = i * p - m * l; + t1[3] = i * p - m * l; + t2[3] = e * p - m * h; + t3[3] = e * l - i * h; */ + t3 = glmm_fnmadd(x7, x0, t3); + + /* t1[4] = i * o - m * k; + t1[4] = i * o - m * k; + t2[4] = e * o - m * g; + t3[4] = e * k - i * g; */ + t4 = glmm_fnmadd(x7, x3, t4); + + /* t1[5] = i * n - m * j; + t1[5] = i * n - m * j; + t2[5] = e * n - m * f; + t3[5] = e * j - i * f; */ + t5 = glmm_fnmadd(x7, x5, t5); + /* x4 = _mm_movelh_ps(r0, r1); */ + x4 = wasm_i32x4_shuffle(r0, r1, 0, 1, 4, 5); /* f e b a */ + /* x5 = _mm_movehl_ps(r1, r0); */ + x5 = wasm_i32x4_shuffle(r1, r0, 6, 7, 2, 3); /* h g d c */ + + x0 = glmm_shuff1(x4, 0, 0, 0, 2); /* a a a e */ + x1 = glmm_shuff1(x4, 1, 1, 1, 3); /* b b b f */ + x2 = glmm_shuff1(x5, 0, 0, 0, 2); /* c c c g */ + x3 = glmm_shuff1(x5, 1, 1, 1, 3); /* d d d h */ + + v2 = wasm_f32x4_mul(x0, t1); + v1 = wasm_f32x4_mul(x0, t0); + v3 = wasm_f32x4_mul(x0, t2); + v0 = wasm_f32x4_mul(x1, t0); + + v2 = glmm_fnmadd(x1, t3, v2); + v3 = glmm_fnmadd(x1, t4, v3); + v0 = glmm_fnmadd(x2, t1, v0); + v1 = glmm_fnmadd(x2, t3, v1); + + v3 = glmm_fmadd(x2, t5, v3); + v0 = glmm_fmadd(x3, t2, v0); + v2 = glmm_fmadd(x3, t5, v2); + v1 = glmm_fmadd(x3, t4, v1); + + /* + dest[0][0] = f * t1[0] - g * t1[1] + h * t1[2]; + dest[0][1] =-(b * t1[0] - c * t1[1] + d * t1[2]); + dest[0][2] = b * t2[0] - c * t2[1] + d * t2[2]; + dest[0][3] =-(b * t3[0] - c * t3[1] + d * t3[2]); */ + v0 = wasm_v128_xor(v0, x8); + + /* + dest[2][0] = e * t1[1] - f * t1[3] + h * t1[5]; + dest[2][1] =-(a * t1[1] - b * t1[3] + d * t1[5]); + dest[2][2] = a * t2[1] - b * t2[3] + d * t2[5]; + dest[2][3] =-(a * t3[1] - b * t3[3] + d * t3[5]);*/ + v2 = wasm_v128_xor(v2, x8); + + /* + dest[1][0] =-(e * t1[0] - g * t1[3] + h * t1[4]); + dest[1][1] = a * t1[0] - c * t1[3] + d * t1[4]; + dest[1][2] =-(a * t2[0] - c * t2[3] + d * t2[4]); + dest[1][3] = a * t3[0] - c * t3[3] + d * t3[4]; */ + v1 = wasm_v128_xor(v1, x9); + + /* + dest[3][0] =-(e * t1[2] - f * t1[4] + g * t1[5]); + dest[3][1] = a * t1[2] - b * t1[4] + c * t1[5]; + dest[3][2] =-(a * t2[2] - b * t2[4] + c * t2[5]); + dest[3][3] = a * t3[2] - b * t3[4] + c * t3[5]; */ + v3 = wasm_v128_xor(v3, x9); + + /* determinant */ + x0 = wasm_i32x4_shuffle(v0, v1, 0, 0, 4, 4); + x1 = wasm_i32x4_shuffle(v2, v3, 0, 0, 4, 4); + x0 = wasm_i32x4_shuffle(x0, x1, 0, 2, 4, 6); + + /* x0 = _mm_rcp_ps(glmm_vhadd(wasm_f32x4_mul(x0, r0))); */ + x0 = wasm_f32x4_div(wasm_f32x4_const_splat(1.0f), + glmm_vhadd(wasm_f32x4_mul(x0, r0))); + + glmm_store(dest[0], wasm_f32x4_mul(v0, x0)); + glmm_store(dest[1], wasm_f32x4_mul(v1, x0)); + glmm_store(dest[2], wasm_f32x4_mul(v2, x0)); + glmm_store(dest[3], wasm_f32x4_mul(v3, x0)); +} + +CGLM_INLINE +void +glm_mat4_inv_wasm(mat4 mat, mat4 dest) { + glmm_128 r0, r1, r2, r3, + v0, v1, v2, v3, + t0, t1, t2, t3, t4, t5, + x0, x1, x2, x3, x4, x5, x6, x7, x8, x9; + + /* x8 = wasm_f32x4_const(0.f, -0.f, 0.f, -0.f); */ + x8 = glmm_float32x4_SIGNMASK_PNPN; + x9 = glmm_shuff1(x8, 2, 1, 2, 1); + + /* 127 <- 0 */ + r0 = glmm_load(mat[0]); /* d c b a */ + r1 = glmm_load(mat[1]); /* h g f e */ + r2 = glmm_load(mat[2]); /* l k j i */ + r3 = glmm_load(mat[3]); /* p o n m */ + /* x0 = _mm_movehl_ps(r3, r2); */ + x0 = wasm_i32x4_shuffle(r3, r2, 6, 7, 2, 3); /* p o l k */ + /* x3 = _mm_movelh_ps(r2, r3); */ + x3 = wasm_i32x4_shuffle(r2, r3, 0, 1, 4, 5); /* n m j i */ + x1 = glmm_shuff1(x0, 1, 3, 3 ,3); /* l p p p */ + x2 = glmm_shuff1(x0, 0, 2, 2, 2); /* k o o o */ + x4 = glmm_shuff1(x3, 1, 3, 3, 3); /* j n n n */ + x7 = glmm_shuff1(x3, 0, 2, 2, 2); /* i m m m */ + + x6 = wasm_i32x4_shuffle(r2, r1, 0, 0, 4, 4); /* e e i i */ + x5 = wasm_i32x4_shuffle(r2, r1, 1, 1, 5, 5); /* f f j j */ + x3 = wasm_i32x4_shuffle(r2, r1, 2, 2, 6, 6); /* g g k k */ + x0 = wasm_i32x4_shuffle(r2, r1, 3, 3, 7, 7); /* h h l l */ + + t0 = wasm_f32x4_mul(x3, x1); + t1 = wasm_f32x4_mul(x5, x1); + t2 = wasm_f32x4_mul(x5, x2); + t3 = wasm_f32x4_mul(x6, x1); + t4 = wasm_f32x4_mul(x6, x2); + t5 = wasm_f32x4_mul(x6, x4); + + /* t1[0] = k * p - o * l; + t1[0] = k * p - o * l; + t2[0] = g * p - o * h; + t3[0] = g * l - k * h; */ + t0 = glmm_fnmadd(x2, x0, t0); + + /* t1[1] = j * p - n * l; + t1[1] = j * p - n * l; + t2[1] = f * p - n * h; + t3[1] = f * l - j * h; */ + t1 = glmm_fnmadd(x4, x0, t1); + + /* t1[2] = j * o - n * k + t1[2] = j * o - n * k; + t2[2] = f * o - n * g; + t3[2] = f * k - j * g; */ + t2 = glmm_fnmadd(x4, x3, t2); + + /* t1[3] = i * p - m * l; + t1[3] = i * p - m * l; + t2[3] = e * p - m * h; + t3[3] = e * l - i * h; */ + t3 = glmm_fnmadd(x7, x0, t3); + + /* t1[4] = i * o - m * k; + t1[4] = i * o - m * k; + t2[4] = e * o - m * g; + t3[4] = e * k - i * g; */ + t4 = glmm_fnmadd(x7, x3, t4); + + /* t1[5] = i * n - m * j; + t1[5] = i * n - m * j; + t2[5] = e * n - m * f; + t3[5] = e * j - i * f; */ + t5 = glmm_fnmadd(x7, x5, t5); + /* x4 = _mm_movelh_ps(r0, r1); */ + x4 = wasm_i32x4_shuffle(r0, r1, 0, 1, 4, 5); /* f e b a */ + /* x5 = _mm_movehl_ps(r1, r0); */ + x5 = wasm_i32x4_shuffle(r1, r0, 6, 7, 2, 3); /* h g d c */ + + x0 = glmm_shuff1(x4, 0, 0, 0, 2); /* a a a e */ + x1 = glmm_shuff1(x4, 1, 1, 1, 3); /* b b b f */ + x2 = glmm_shuff1(x5, 0, 0, 0, 2); /* c c c g */ + x3 = glmm_shuff1(x5, 1, 1, 1, 3); /* d d d h */ + + v2 = wasm_f32x4_mul(x0, t1); + v1 = wasm_f32x4_mul(x0, t0); + v3 = wasm_f32x4_mul(x0, t2); + v0 = wasm_f32x4_mul(x1, t0); + + v2 = glmm_fnmadd(x1, t3, v2); + v3 = glmm_fnmadd(x1, t4, v3); + v0 = glmm_fnmadd(x2, t1, v0); + v1 = glmm_fnmadd(x2, t3, v1); + + v3 = glmm_fmadd(x2, t5, v3); + v0 = glmm_fmadd(x3, t2, v0); + v2 = glmm_fmadd(x3, t5, v2); + v1 = glmm_fmadd(x3, t4, v1); + + /* + dest[0][0] = f * t1[0] - g * t1[1] + h * t1[2]; + dest[0][1] =-(b * t1[0] - c * t1[1] + d * t1[2]); + dest[0][2] = b * t2[0] - c * t2[1] + d * t2[2]; + dest[0][3] =-(b * t3[0] - c * t3[1] + d * t3[2]); */ + v0 = wasm_v128_xor(v0, x8); + + /* + dest[2][0] = e * t1[1] - f * t1[3] + h * t1[5]; + dest[2][1] =-(a * t1[1] - b * t1[3] + d * t1[5]); + dest[2][2] = a * t2[1] - b * t2[3] + d * t2[5]; + dest[2][3] =-(a * t3[1] - b * t3[3] + d * t3[5]);*/ + v2 = wasm_v128_xor(v2, x8); + + /* + dest[1][0] =-(e * t1[0] - g * t1[3] + h * t1[4]); + dest[1][1] = a * t1[0] - c * t1[3] + d * t1[4]; + dest[1][2] =-(a * t2[0] - c * t2[3] + d * t2[4]); + dest[1][3] = a * t3[0] - c * t3[3] + d * t3[4]; */ + v1 = wasm_v128_xor(v1, x9); + + /* + dest[3][0] =-(e * t1[2] - f * t1[4] + g * t1[5]); + dest[3][1] = a * t1[2] - b * t1[4] + c * t1[5]; + dest[3][2] =-(a * t2[2] - b * t2[4] + c * t2[5]); + dest[3][3] = a * t3[2] - b * t3[4] + c * t3[5]; */ + v3 = wasm_v128_xor(v3, x9); + + /* determinant */ + x0 = wasm_i32x4_shuffle(v0, v1, 0, 0, 4, 4); + x1 = wasm_i32x4_shuffle(v2, v3, 0, 0, 4, 4); + x0 = wasm_i32x4_shuffle(x0, x1, 0, 2, 4, 6); + + x0 = wasm_f32x4_div(wasm_f32x4_splat(1.0f), glmm_vhadd(wasm_f32x4_mul(x0, r0))); + + glmm_store(dest[0], wasm_f32x4_mul(v0, x0)); + glmm_store(dest[1], wasm_f32x4_mul(v1, x0)); + glmm_store(dest[2], wasm_f32x4_mul(v2, x0)); + glmm_store(dest[3], wasm_f32x4_mul(v3, x0)); +} + +#endif +#endif /* cglm_mat_wasm_h */ diff --git a/external/cglm/simd/wasm/quat.h b/external/cglm/simd/wasm/quat.h new file mode 100644 index 0000000..8d72546 --- /dev/null +++ b/external/cglm/simd/wasm/quat.h @@ -0,0 +1,55 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_quat_wasm_h +#define cglm_quat_wasm_h +#if defined(__wasm__) && defined(__wasm_simd128__) + +#include "../../common.h" +#include "../intrin.h" + +CGLM_INLINE +void +glm_quat_mul_wasm(versor p, versor q, versor dest) { + /* + + (a1 b2 + b1 a2 + c1 d2 − d1 c2)i + + (a1 c2 − b1 d2 + c1 a2 + d1 b2)j + + (a1 d2 + b1 c2 − c1 b2 + d1 a2)k + a1 a2 − b1 b2 − c1 c2 − d1 d2 + */ + + glmm_128 xp, xq, x1, x2, x3, r, x, y, z; + + xp = glmm_load(p); /* 3 2 1 0 */ + xq = glmm_load(q); + /* x1 = wasm_f32x4_const(0.f, -0.f, 0.f, -0.f); */ + x1 = glmm_float32x4_SIGNMASK_PNPN; /* TODO: _mm_set1_ss() + shuff ? */ + r = wasm_f32x4_mul(glmm_splat_w(xp), xq); + /* x2 = _mm_unpackhi_ps(x1, x1); */ + x2 = wasm_i32x4_shuffle(x1, x1, 2, 6, 3, 7); + x3 = glmm_shuff1(x1, 3, 2, 0, 1); + x = glmm_splat_x(xp); + y = glmm_splat_y(xp); + z = glmm_splat_z(xp); + + x = wasm_v128_xor(x, x1); + y = wasm_v128_xor(y, x2); + z = wasm_v128_xor(z, x3); + + x1 = glmm_shuff1(xq, 0, 1, 2, 3); + x2 = glmm_shuff1(xq, 1, 0, 3, 2); + x3 = glmm_shuff1(xq, 2, 3, 0, 1); + + r = glmm_fmadd(x, x1, r); + r = glmm_fmadd(y, x2, r); + r = glmm_fmadd(z, x3, r); + + glmm_store(dest, r); +} + +#endif +#endif /* cglm_quat_wasm_h */ diff --git a/external/cglm/simd/x86.h b/external/cglm/simd/x86.h new file mode 100644 index 0000000..2410d0f --- /dev/null +++ b/external/cglm/simd/x86.h @@ -0,0 +1,365 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_simd_x86_h +#define cglm_simd_x86_h +#include "intrin.h" +#ifdef CGLM_SIMD_x86 + +#ifdef CGLM_ALL_UNALIGNED +# define glmm_load(p) _mm_loadu_ps(p) +# define glmm_store(p, a) _mm_storeu_ps(p, a) +#else +# define glmm_load(p) _mm_load_ps(p) +# define glmm_store(p, a) _mm_store_ps(p, a) +#endif + +#define glmm_128 __m128 + +#ifdef __AVX__ +# define glmm_shuff1(xmm, z, y, x, w) \ + _mm_permute_ps((xmm), _MM_SHUFFLE(z, y, x, w)) +#else +# if !defined(CGLM_NO_INT_DOMAIN) && defined(__SSE2__) +# define glmm_shuff1(xmm, z, y, x, w) \ + _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(xmm), \ + _MM_SHUFFLE(z, y, x, w))) +# else +# define glmm_shuff1(xmm, z, y, x, w) \ + _mm_shuffle_ps(xmm, xmm, _MM_SHUFFLE(z, y, x, w)) +# endif +#endif + +#define glmm_splat(x, lane) glmm_shuff1(x, lane, lane, lane, lane) + +#ifdef __AVX__ +# define glmm_set1(x) _mm_broadcast_ss(&x) +# define glmm_set1_ptr(x) _mm_broadcast_ss(x) +# define glmm_set1_rval(x) _mm_set1_ps(x) +# ifdef __AVX2__ +# define glmm_splat_x(x) _mm_broadcastss_ps(x) +# else +# define glmm_splat_x(x) _mm_permute_ps(x, _MM_SHUFFLE(0, 0, 0, 0)) +# endif +# define glmm_splat_y(x) _mm_permute_ps(x, _MM_SHUFFLE(1, 1, 1, 1)) +# define glmm_splat_z(x) _mm_permute_ps(x, _MM_SHUFFLE(2, 2, 2, 2)) +# define glmm_splat_w(x) _mm_permute_ps(x, _MM_SHUFFLE(3, 3, 3, 3)) +#else +# define glmm_set1(x) _mm_set1_ps(x) +# define glmm_set1_ptr(x) _mm_set1_ps(*x) +# define glmm_set1_rval(x) _mm_set1_ps(x) + +# define glmm_splat_x(x) glmm_splat(x, 0) +# define glmm_splat_y(x) glmm_splat(x, 1) +# define glmm_splat_z(x) glmm_splat(x, 2) +# define glmm_splat_w(x) glmm_splat(x, 3) +#endif + +#ifdef __AVX__ +# ifdef CGLM_ALL_UNALIGNED +# define glmm_load256(p) _mm256_loadu_ps(p) +# define glmm_store256(p, a) _mm256_storeu_ps(p, a) +# else +# define glmm_load256(p) _mm256_load_ps(p) +# define glmm_store256(p, a) _mm256_store_ps(p, a) +# endif +#endif + +/* Note that `0x80000000` corresponds to `INT_MIN` for a 32-bit int. */ + +#if defined(__SSE2__) +# define GLMM_NEGZEROf ((int)0x80000000) /* 0x80000000 ---> -0.0f */ +# define GLMM_POSZEROf ((int)0x00000000) /* 0x00000000 ---> +0.0f */ +#else +# ifdef CGLM_FAST_MATH + union { int i; float f; } static GLMM_NEGZEROf_TU = { .i = (int)0x80000000 }; +# define GLMM_NEGZEROf GLMM_NEGZEROf_TU.f +# define GLMM_POSZEROf 0.0f +# else +# define GLMM_NEGZEROf -0.0f +# define GLMM_POSZEROf 0.0f +# endif +#endif + +#if defined(__SSE2__) +# define GLMM__SIGNMASKf(X, Y, Z, W) \ + _mm_castsi128_ps(_mm_set_epi32(X, Y, Z, W)) + /* _mm_set_ps(X, Y, Z, W); */ +#else +# define GLMM__SIGNMASKf(X, Y, Z, W) _mm_set_ps(X, Y, Z, W) +#endif + +#define glmm_float32x4_SIGNMASK_PNPN GLMM__SIGNMASKf(GLMM_POSZEROf, GLMM_NEGZEROf, GLMM_POSZEROf, GLMM_NEGZEROf) +#define glmm_float32x4_SIGNMASK_NPNP GLMM__SIGNMASKf(GLMM_NEGZEROf, GLMM_POSZEROf, GLMM_NEGZEROf, GLMM_POSZEROf) +#define glmm_float32x4_SIGNMASK_NPPN GLMM__SIGNMASKf(GLMM_NEGZEROf, GLMM_POSZEROf, GLMM_POSZEROf, GLMM_NEGZEROf) + +/* fasth math prevents -0.0f to work */ +#if defined(__SSE2__) +# define glmm_float32x4_SIGNMASK_NEG _mm_castsi128_ps(_mm_set1_epi32(GLMM_NEGZEROf)) /* _mm_set1_ps(-0.0f) */ +#else +# define glmm_float32x4_SIGNMASK_NEG glmm_set1(GLMM_NEGZEROf) +#endif + +#define glmm_float32x8_SIGNMASK_NEG _mm256_castsi256_ps(_mm256_set1_epi32(GLMM_NEGZEROf)) + +static inline +__m128 +glmm_abs(__m128 x) { + return _mm_andnot_ps(glmm_float32x4_SIGNMASK_NEG, x); +} + +static inline __m128 glmm_min(__m128 a, __m128 b) { return _mm_min_ps(a, b); } +static inline __m128 glmm_max(__m128 a, __m128 b) { return _mm_max_ps(a, b); } + +static inline +__m128 +glmm_vhadd(__m128 v) { + __m128 x0; + x0 = _mm_add_ps(v, glmm_shuff1(v, 0, 1, 2, 3)); + x0 = _mm_add_ps(x0, glmm_shuff1(x0, 1, 0, 0, 1)); + return x0; +} + +static inline +__m128 +glmm_vhadds(__m128 v) { +#if defined(__SSE3__) + __m128 shuf, sums; + shuf = _mm_movehdup_ps(v); + sums = _mm_add_ps(v, shuf); + shuf = _mm_movehl_ps(shuf, sums); + sums = _mm_add_ss(sums, shuf); + return sums; +#else + __m128 shuf, sums; + shuf = glmm_shuff1(v, 2, 3, 0, 1); + sums = _mm_add_ps(v, shuf); + shuf = _mm_movehl_ps(shuf, sums); + sums = _mm_add_ss(sums, shuf); + return sums; +#endif +} + +static inline +float +glmm_hadd(__m128 v) { + return _mm_cvtss_f32(glmm_vhadds(v)); +} + +static inline +__m128 +glmm_vhmin(__m128 v) { + __m128 x0, x1, x2; + x0 = _mm_movehl_ps(v, v); /* [2, 3, 2, 3] */ + x1 = _mm_min_ps(x0, v); /* [0|2, 1|3, 2|2, 3|3] */ + x2 = glmm_splat(x1, 1); /* [1|3, 1|3, 1|3, 1|3] */ + return _mm_min_ss(x1, x2); +} + +static inline +float +glmm_hmin(__m128 v) { + return _mm_cvtss_f32(glmm_vhmin(v)); +} + +static inline +__m128 +glmm_vhmax(__m128 v) { + __m128 x0, x1, x2; + x0 = _mm_movehl_ps(v, v); /* [2, 3, 2, 3] */ + x1 = _mm_max_ps(x0, v); /* [0|2, 1|3, 2|2, 3|3] */ + x2 = glmm_splat(x1, 1); /* [1|3, 1|3, 1|3, 1|3] */ + return _mm_max_ss(x1, x2); +} + +static inline +float +glmm_hmax(__m128 v) { + return _mm_cvtss_f32(glmm_vhmax(v)); +} + +static inline +__m128 +glmm_vdots(__m128 a, __m128 b) { +#if (defined(__SSE4_1__) || defined(__SSE4_2__)) && defined(CGLM_SSE4_DOT) + return _mm_dp_ps(a, b, 0xFF); +#elif defined(__SSE3__) && defined(CGLM_SSE3_DOT) + __m128 x0, x1; + x0 = _mm_mul_ps(a, b); + x1 = _mm_hadd_ps(x0, x0); + return _mm_hadd_ps(x1, x1); +#else + return glmm_vhadds(_mm_mul_ps(a, b)); +#endif +} + +static inline +__m128 +glmm_vdot(__m128 a, __m128 b) { +#if (defined(__SSE4_1__) || defined(__SSE4_2__)) && defined(CGLM_SSE4_DOT) + return _mm_dp_ps(a, b, 0xFF); +#elif defined(__SSE3__) && defined(CGLM_SSE3_DOT) + __m128 x0, x1; + x0 = _mm_mul_ps(a, b); + x1 = _mm_hadd_ps(x0, x0); + return _mm_hadd_ps(x1, x1); +#else + __m128 x0; + x0 = _mm_mul_ps(a, b); + x0 = _mm_add_ps(x0, glmm_shuff1(x0, 1, 0, 3, 2)); + return _mm_add_ps(x0, glmm_shuff1(x0, 0, 1, 0, 1)); +#endif +} + +static inline +float +glmm_dot(__m128 a, __m128 b) { + return _mm_cvtss_f32(glmm_vdots(a, b)); +} + +static inline +float +glmm_norm(__m128 a) { + return _mm_cvtss_f32(_mm_sqrt_ss(glmm_vhadds(_mm_mul_ps(a, a)))); +} + +static inline +float +glmm_norm2(__m128 a) { + return _mm_cvtss_f32(glmm_vhadds(_mm_mul_ps(a, a))); +} + +static inline +float +glmm_norm_one(__m128 a) { + return _mm_cvtss_f32(glmm_vhadds(glmm_abs(a))); +} + +static inline +float +glmm_norm_inf(__m128 a) { + return _mm_cvtss_f32(glmm_vhmax(glmm_abs(a))); +} + +#if defined(__SSE2__) +static inline +__m128 +glmm_load3(float v[3]) { + __m128i xy; + __m128 z; + + xy = _mm_loadl_epi64(CGLM_CASTPTR_ASSUME_ALIGNED(v, const __m128i)); + z = _mm_load_ss(&v[2]); + + return _mm_movelh_ps(_mm_castsi128_ps(xy), z); +} + +static inline +void +glmm_store3(float v[3], __m128 vx) { + _mm_storel_pi(CGLM_CASTPTR_ASSUME_ALIGNED(v, __m64), vx); + _mm_store_ss(&v[2], glmm_shuff1(vx, 2, 2, 2, 2)); +} +#endif + +static inline +__m128 +glmm_div(__m128 a, __m128 b) { + return _mm_div_ps(a, b); +} + +/* enable FMA macro for MSVC? */ +#if defined(_MSC_VER) && !defined(__FMA__) && defined(__AVX2__) +# define __FMA__ 1 +#endif + +static inline +__m128 +glmm_fmadd(__m128 a, __m128 b, __m128 c) { +#ifdef __FMA__ + return _mm_fmadd_ps(a, b, c); +#else + return _mm_add_ps(c, _mm_mul_ps(a, b)); +#endif +} + +static inline +__m128 +glmm_fnmadd(__m128 a, __m128 b, __m128 c) { +#ifdef __FMA__ + return _mm_fnmadd_ps(a, b, c); +#else + return _mm_sub_ps(c, _mm_mul_ps(a, b)); +#endif +} + +static inline +__m128 +glmm_fmsub(__m128 a, __m128 b, __m128 c) { +#ifdef __FMA__ + return _mm_fmsub_ps(a, b, c); +#else + return _mm_sub_ps(_mm_mul_ps(a, b), c); +#endif +} + +static inline +__m128 +glmm_fnmsub(__m128 a, __m128 b, __m128 c) { +#ifdef __FMA__ + return _mm_fnmsub_ps(a, b, c); +#else + return _mm_xor_ps(_mm_add_ps(_mm_mul_ps(a, b), c), + glmm_float32x4_SIGNMASK_NEG); +#endif +} + +#if defined(__AVX__) +static inline +__m256 +glmm256_fmadd(__m256 a, __m256 b, __m256 c) { +#ifdef __FMA__ + return _mm256_fmadd_ps(a, b, c); +#else + return _mm256_add_ps(c, _mm256_mul_ps(a, b)); +#endif +} + +static inline +__m256 +glmm256_fnmadd(__m256 a, __m256 b, __m256 c) { +#ifdef __FMA__ + return _mm256_fnmadd_ps(a, b, c); +#else + return _mm256_sub_ps(c, _mm256_mul_ps(a, b)); +#endif +} + +static inline +__m256 +glmm256_fmsub(__m256 a, __m256 b, __m256 c) { +#ifdef __FMA__ + return _mm256_fmsub_ps(a, b, c); +#else + return _mm256_sub_ps(_mm256_mul_ps(a, b), c); +#endif +} + +static inline +__m256 +glmm256_fnmsub(__m256 a, __m256 b, __m256 c) { +#ifdef __FMA__ + return _mm256_fmsub_ps(a, b, c); +#else + return _mm256_xor_ps(_mm256_sub_ps(_mm256_mul_ps(a, b), c), + glmm_float32x8_SIGNMASK_NEG); +#endif +} +#endif + +#endif +#endif /* cglm_simd_x86_h */ diff --git a/external/cglm/sphere.h b/external/cglm/sphere.h new file mode 100644 index 0000000..334b83a --- /dev/null +++ b/external/cglm/sphere.h @@ -0,0 +1,99 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_sphere_h +#define cglm_sphere_h + +#include "common.h" +#include "mat4.h" + +/* + Sphere Representation in cglm: [center.x, center.y, center.z, radii] + + You could use this representation or you can convert it to vec4 before call + any function + */ + +/*! + * @brief helper for getting sphere radius + * + * @param[in] s sphere + * + * @return returns radii + */ +CGLM_INLINE +float +glm_sphere_radii(vec4 s) { + return s[3]; +} + +/*! + * @brief apply transform to sphere, it is just wrapper for glm_mat4_mulv3 + * + * @param[in] s sphere + * @param[in] m transform matrix + * @param[out] dest transformed sphere + */ +CGLM_INLINE +void +glm_sphere_transform(vec4 s, mat4 m, vec4 dest) { + glm_mat4_mulv3(m, s, 1.0f, dest); + dest[3] = s[3]; +} + +/*! + * @brief merges two spheres and creates a new one + * + * two sphere must be in same space, for instance if one in world space then + * the other must be in world space too, not in local space. + * + * @param[in] s1 sphere 1 + * @param[in] s2 sphere 2 + * @param[out] dest merged/extended sphere + */ +CGLM_INLINE +void +glm_sphere_merge(vec4 s1, vec4 s2, vec4 dest) { + float dist, radii; + + dist = glm_vec3_distance(s1, s2); + radii = dist + s1[3] + s2[3]; + + radii = glm_max(radii, s1[3]); + radii = glm_max(radii, s2[3]); + + glm_vec3_center(s1, s2, dest); + dest[3] = radii; +} + +/*! + * @brief check if two sphere intersects + * + * @param[in] s1 sphere + * @param[in] s2 other sphere + */ +CGLM_INLINE +bool +glm_sphere_sphere(vec4 s1, vec4 s2) { + return glm_vec3_distance2(s1, s2) <= glm_pow2(s1[3] + s2[3]); +} + +/*! + * @brief check if sphere intersects with point + * + * @param[in] s sphere + * @param[in] point point + */ +CGLM_INLINE +bool +glm_sphere_point(vec4 s, vec3 point) { + float rr; + rr = s[3] * s[3]; + return glm_vec3_distance2(point, s) <= rr; +} + +#endif /* cglm_sphere_h */ diff --git a/external/cglm/struct.h b/external/cglm/struct.h new file mode 100644 index 0000000..31ca4e2 --- /dev/null +++ b/external/cglm/struct.h @@ -0,0 +1,50 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_structs_h +#define cglm_structs_h +#ifdef __cplusplus +extern "C" { +#endif + +#include "cglm.h" +#include "types-struct.h" +#include "struct/vec2.h" +#include "struct/vec3.h" +#include "struct/vec4.h" +#include "struct/ivec2.h" +#include "struct/ivec3.h" +#include "struct/ivec4.h" +#include "struct/mat2.h" +#include "struct/mat2x3.h" +#include "struct/mat2x4.h" +#include "struct/mat3.h" +#include "struct/mat3x2.h" +#include "struct/mat3x4.h" +#include "struct/mat4.h" +#include "struct/mat4x2.h" +#include "struct/mat4x3.h" +#include "struct/affine.h" +#include "struct/frustum.h" +#include "struct/plane.h" +#include "struct/noise.h" +#include "struct/box.h" +#include "struct/color.h" +#include "struct/io.h" +#include "struct/cam.h" +#include "struct/quat.h" +#include "struct/euler.h" +#include "struct/project.h" +#include "struct/sphere.h" +#include "struct/curve.h" +#include "struct/affine2d.h" +#include "struct/ray.h" + +#ifdef __cplusplus +} +#endif +#endif /* cglm_structs_h */ diff --git a/external/cglm/struct/aabb2d.h b/external/cglm/struct/aabb2d.h new file mode 100644 index 0000000..9077069 --- /dev/null +++ b/external/cglm/struct/aabb2d.h @@ -0,0 +1,253 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglms_aabb2ds_h +#define cglms_aabb2ds_h + +#include "../common.h" +#include "../types-struct.h" +#include "../aabb2d.h" +#include "vec2.h" +#include "vec4.h" +#include "mat4.h" + +/* api definition */ +#define glms_aabb2d_(NAME) CGLM_STRUCTAPI(aabb2d, NAME) + +/*! + * @brief apply transform to Axis-Aligned Bounding Box + * + * @param[in] aabb bounding box + * @param[in] m transform matrix + * @param[out] dest transformed bounding box + */ +CGLM_INLINE +void +glms_aabb2d_(transform)(vec2s aabb[2], mat3s m, vec2s dest[2]) { + vec2 rawAabb[2]; + vec2 rawDest[2]; + + glms_vec2_(unpack)(rawAabb, aabb, 2); + glm_aabb2d_transform(rawAabb, m.raw, rawDest); + glms_vec2_(pack)(dest, rawDest, 2); +} + +/*! + * @brief merges two AABB bounding box and creates new one + * + * two box must be in same space, if one of box is in different space then + * you should consider to convert it's space by glm_box_space + * + * @param[in] aabb1 bounding box 1 + * @param[in] aabb2 bounding box 2 + * @param[out] dest merged bounding box + */ +CGLM_INLINE +void +glms_aabb2d_(merge)(vec2s aabb1[2], vec2s aabb2[2], vec2s dest[2]) { + vec2 rawAabb1[2]; + vec2 rawAabb2[2]; + vec2 rawDest[2]; + + glms_vec2_(unpack)(rawAabb1, aabb1, 2); + glms_vec2_(unpack)(rawAabb2, aabb2, 2); + glm_aabb2d_merge(rawAabb1, rawAabb2, rawDest); + glms_vec2_(pack)(dest, rawDest, 2); +} + +/*! + * @brief crops a bounding box with another one. + * + * this could be useful for getting a bbox which fits with view frustum and + * object bounding boxes. In this case you crop view frustum box with objects + * box + * + * @param[in] aabb bounding box 1 + * @param[in] cropAabb crop box + * @param[out] dest cropped bounding box + */ +CGLM_INLINE +void +glms_aabb2d_(crop)(vec2s aabb[2], vec2s cropAabb[2], vec2s dest[2]) { + vec2 rawAabb[2]; + vec2 rawCropAabb[2]; + vec2 rawDest[2]; + + glms_vec2_(unpack)(rawAabb, aabb, 2); + glms_vec2_(unpack)(rawCropAabb, cropAabb, 2); + glm_aabb2d_crop(rawAabb, rawCropAabb, rawDest); + glms_vec2_(pack)(dest, rawDest, 2); +} + +/*! + * @brief crops a bounding box with another one. + * + * this could be useful for getting a bbox which fits with view frustum and + * object bounding boxes. In this case you crop view frustum box with objects + * box + * + * @param[in] aabb bounding box + * @param[in] cropAabb crop box + * @param[in] clampAabb minimum box + * @param[out] dest cropped bounding box + */ +CGLM_INLINE +void +glms_aabb2d_(crop_until)(vec2s aabb[2], + vec2s cropAabb[2], + vec2s clampAabb[2], + vec2s dest[2]) { + glms_aabb2d_(crop)(aabb, cropAabb, dest); + glms_aabb2d_(merge)(clampAabb, dest, dest); +} + +/*! + * @brief invalidate AABB min and max values + * + * @param[in, out] aabb bounding box + */ +CGLM_INLINE +void +glms_aabb2d_(invalidate)(vec2s box[2]) { + box[0] = glms_vec2_(fill)(FLT_MAX); + box[1] = glms_vec2_(fill)(-FLT_MAX); +} + +/*! + * @brief check if AABB is valid or not + * + * @param[in] aabb bounding box + */ +CGLM_INLINE +bool +glms_aabb2d_(isvalid)(vec2s aabb[2]) { + vec2 rawAabb[2]; + glms_vec2_(unpack)(rawAabb, aabb, 2); + return glm_aabb2d_isvalid(rawAabb); +} + +/*! + * @brief distance between of min and max + * + * @param[in] aabb bounding box + */ +CGLM_INLINE +float +glms_aabb2d_(diag)(vec2s aabb[2]) { + vec2 rawAabb[2]; + glms_vec2_(unpack)(rawAabb, aabb, 2); + return glm_aabb2d_diag(rawAabb); +} + + +/*! + * @brief size of aabb + * + * @param[in] aabb bounding aabb + * @param[out] dest size + */ +CGLM_INLINE +vec2s +glms_aabb2d_(sizev)(vec2s aabb[2]) { + vec2s size; + vec2 rawAabb[2]; + glms_vec2_(unpack)(rawAabb, aabb, 2); + glm_aabb2d_sizev(rawAabb, size.raw); + return size; +} + +/*! + * @brief radius of sphere which surrounds AABB + * + * @param[in] aabb bounding box + */ +CGLM_INLINE +float +glms_aabb2d_(radius)(vec2s aabb[2]) { + return glms_aabb2d_(size)(aabb) * 0.5f; +} + +/*! + * @brief computes center point of AABB + * + * @param[in] aabb bounding box + * @returns center of bounding box + */ +CGLM_INLINE +vec2s +glms_aabb2d_(center)(vec2s aabb[2]) { + return glms_vec2_(center)(aabb[0], aabb[1]); +} + +/*! + * @brief check if two AABB intersects + * + * @param[in] aabb bounding box + * @param[in] other other bounding box + */ +CGLM_INLINE +bool +glms_aabb2d_(aabb)(vec2s aabb[2], vec2s other[2]) { + vec2 rawAabb[2]; + vec2 rawOther[2]; + + glms_vec2_(unpack)(rawAabb, aabb, 2); + glms_vec2_(unpack)(rawOther, other, 2); + return glm_aabb2d_aabb(rawAabb, rawOther); +} + +/*! + * @brief check if AABB intersects with a circle + * + * https://github.com/erich666/GraphicsGems/blob/master/gems/BoxSphere.c + * Solid Box - Solid Sphere test. + * + * @param[in] aabb solid bounding box + * @param[in] s solid sphere + */ +CGLM_INLINE +bool +glms_aabb2d_(circle)(vec2s aabb[2], vec3s c) { + vec2 rawAabb[2]; + + glms_vec2_(unpack)(rawAabb, aabb, 2); + return glm_aabb2d_circle(rawAabb, c.raw); +} + +/*! + * @brief check if point is inside of AABB + * + * @param[in] aabb bounding box + * @param[in] point point + */ +CGLM_INLINE +bool +glms_aabb2d_(point)(vec2s aabb[2], vec2s point) { + vec2 rawAabb[2]; + + glms_vec2_(unpack)(rawAabb, aabb, 2); + return glm_aabb2d_point(rawAabb, point.raw); +} + +/*! + * @brief check if AABB contains other AABB + * + * @param[in] box bounding box + * @param[in] other other bounding box + */ +CGLM_INLINE +bool +glms_aabb2d_(contains)(vec2s aabb[2], vec2s other[2]) { + vec2 rawAabb[2]; + vec2 rawOther[2]; + + glms_vec2_(unpack)(rawAabb, aabb, 2); + glms_vec2_(unpack)(rawOther, other, 2); + return glm_aabb2d_contains(rawAabb, rawOther); +} + +#endif /* cglms_aabb2ds_h */ diff --git a/external/cglm/struct/affine-mat.h b/external/cglm/struct/affine-mat.h new file mode 100644 index 0000000..e1d4ff3 --- /dev/null +++ b/external/cglm/struct/affine-mat.h @@ -0,0 +1,90 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_mul(mat4 m1, mat4 m2); + CGLM_INLINE mat4s glms_mul_rot(mat4 m1, mat4 m2); + CGLM_INLINE mat4s glms_inv_tr(); + */ + +#ifndef cglms_affine_mat_h +#define cglms_affine_mat_h + +#include "../common.h" +#include "../types-struct.h" +#include "../affine-mat.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" + +/*! + * @brief this is similar to glms_mat4_mul but specialized to affine transform + * + * Matrix format should be: + * R R R X + * R R R Y + * R R R Z + * 0 0 0 W + * + * this reduces some multiplications. It should be faster than mat4_mul. + * if you are not sure about matrix format then DON'T use this! use mat4_mul + * + * @param[in] m1 affine matrix 1 + * @param[in] m2 affine matrix 2 + * @returns destination matrix + */ +CGLM_INLINE +mat4s +glms_mul(mat4s m1, mat4s m2){ + mat4s r; + glm_mul(m1.raw, m2.raw, r.raw); + return r; +} + +/*! + * @brief this is similar to glm_mat4_mul but specialized to affine transform + * + * Right Matrix format should be: + * R R R 0 + * R R R 0 + * R R R 0 + * 0 0 0 1 + * + * this reduces some multiplications. It should be faster than mat4_mul. + * if you are not sure about matrix format then DON'T use this! use mat4_mul + * + * @param[in] m1 affine matrix 1 + * @param[in] m2 affine matrix 2 + * @returns destination matrix + */ +CGLM_INLINE +mat4s +glms_mul_rot(mat4s m1, mat4s m2){ + mat4s r; + glm_mul_rot(m1.raw, m2.raw, r.raw); + return r; +} + +/*! + * @brief inverse orthonormal rotation + translation matrix (ridig-body) + * + * @code + * X = | R T | X' = | R' -R'T | + * | 0 1 | | 0 1 | + * @endcode + * + * @param[in] m matrix + * @returns destination matrix + */ +CGLM_INLINE +mat4s +glms_inv_tr(mat4s m){ + glm_inv_tr(m.raw); + return m; +} +#endif /* cglms_affine_mat_h */ diff --git a/external/cglm/struct/affine-post.h b/external/cglm/struct/affine-post.h new file mode 100644 index 0000000..e155660 --- /dev/null +++ b/external/cglm/struct/affine-post.h @@ -0,0 +1,184 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_translated(mat4s m, vec3s v); + CGLM_INLINE mat4s glms_translated_x(mat4s m, float x); + CGLM_INLINE mat4s glms_translated_y(mat4s m, float y); + CGLM_INLINE mat4s glms_translated_z(mat4s m, float z); + CGLM_INLINE mat4s glms_rotated_x(mat4s m, float angle); + CGLM_INLINE mat4s glms_rotated_y(mat4s m, float angle); + CGLM_INLINE mat4s glms_rotated_z(mat4s m, float angle); + CGLM_INLINE mat4s glms_rotated(mat4s m, float angle, vec3s axis); + CGLM_INLINE mat4s glms_rotated_at(mat4s m, vec3s pivot, float angle, vec3s axis); + CGLM_INLINE mat4s glms_spinned(mat4s m, float angle, vec3s axis); + */ + +#ifndef cglms_affines_post_h +#define cglms_affines_post_h + +#include "../common.h" +#include "../types-struct.h" +#include "../affine.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" + +/*! + * @brief translate existing transform matrix by v vector + * and stores result in same matrix + * + * @param[in] m affine transform + * @param[in] v translate vector [x, y, z] + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_translated(mat4s m, vec3s v) { + glm_translated(m.raw, v.raw); + return m; +} + +/*! + * @brief translate existing transform matrix by x factor + * + * @param[in] m affine transform + * @param[in] x x factor + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_translated_x(mat4s m, float x) { + glm_translated_x(m.raw, x); + return m; +} + +/*! + * @brief translate existing transform matrix by y factor + * + * @param[in] m affine transform + * @param[in] y y factor + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_translated_y(mat4s m, float y) { + glm_translated_y(m.raw, y); + return m; +} + +/*! + * @brief translate existing transform matrix by z factor + * + * @param[in] m affine transform + * @param[in] z z factor + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_translated_z(mat4s m, float z) { + glm_translated_z(m.raw, z); + return m; +} + +/*! + * @brief rotate existing transform matrix around X axis by angle + * and store result in dest + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @returns rotated matrix + */ +CGLM_INLINE +mat4s +glms_rotated_x(mat4s m, float angle) { + mat4s r; + glm_rotated_x(m.raw, angle, r.raw); + return r; +} + +/*! + * @brief rotate existing transform matrix around Y axis by angle + * and store result in dest + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @returns rotated matrix + */ +CGLM_INLINE +mat4s +glms_rotated_y(mat4s m, float angle) { + mat4s r; + glm_rotated_y(m.raw, angle, r.raw); + return r; +} + +/*! + * @brief rotate existing transform matrix around Z axis by angle + * and store result in dest + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @returns rotated matrix + */ +CGLM_INLINE +mat4s +glms_rotated_z(mat4s m, float angle) { + mat4s r; + glm_rotated_z(m.raw, angle, r.raw); + return r; +} + +/*! + * @brief rotate existing transform matrix around given axis by angle + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @param[in] axis axis + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_rotated(mat4s m, float angle, vec3s axis) { + glm_rotated(m.raw, angle, axis.raw); + return m; +} + +/*! + * @brief rotate existing transform + * around given axis by angle at given pivot point (rotation center) + * + * @param[in] m affine transform + * @param[in] pivot rotation center + * @param[in] angle angle (radians) + * @param[in] axis axis + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_rotated_at(mat4s m, vec3s pivot, float angle, vec3s axis) { + glm_rotated_at(m.raw, pivot.raw, angle, axis.raw); + return m; +} + +/*! + * @brief rotate existing transform matrix around given axis by angle around self (doesn't affected by position) + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @param[in] axis axis + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_spinned(mat4s m, float angle, vec3s axis) { + glm_spinned(m.raw, angle, axis.raw); + return m; +} + +#endif /* cglms_affines_post_h */ diff --git a/external/cglm/struct/affine-pre.h b/external/cglm/struct/affine-pre.h new file mode 100644 index 0000000..e323ffa --- /dev/null +++ b/external/cglm/struct/affine-pre.h @@ -0,0 +1,184 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_translate(mat4s m, vec3s v); + CGLM_INLINE mat4s glms_translate_x(mat4s m, float x); + CGLM_INLINE mat4s glms_translate_y(mat4s m, float y); + CGLM_INLINE mat4s glms_translate_z(mat4s m, float z); + CGLM_INLINE mat4s glms_rotate_x(mat4s m, float angle); + CGLM_INLINE mat4s glms_rotate_y(mat4s m, float angle); + CGLM_INLINE mat4s glms_rotate_z(mat4s m, float angle); + CGLM_INLINE mat4s glms_rotate(mat4s m, float angle, vec3s axis); + CGLM_INLINE mat4s glms_rotate_at(mat4s m, vec3s pivot, float angle, vec3s axis); + CGLM_INLINE mat4s glms_spin(mat4s m, float angle, vec3s axis); + */ + +#ifndef cglms_affines_pre_h +#define cglms_affines_pre_h + +#include "../common.h" +#include "../types-struct.h" +#include "../affine.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" + +/*! + * @brief translate existing transform matrix by v vector + * and stores result in same matrix + * + * @param[in] m affine transform + * @param[in] v translate vector [x, y, z] + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_translate(mat4s m, vec3s v) { + glm_translate(m.raw, v.raw); + return m; +} + +/*! + * @brief translate existing transform matrix by x factor + * + * @param[in] m affine transform + * @param[in] x x factor + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_translate_x(mat4s m, float x) { + glm_translate_x(m.raw, x); + return m; +} + +/*! + * @brief translate existing transform matrix by y factor + * + * @param[in] m affine transform + * @param[in] y y factor + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_translate_y(mat4s m, float y) { + glm_translate_y(m.raw, y); + return m; +} + +/*! + * @brief translate existing transform matrix by z factor + * + * @param[in] m affine transform + * @param[in] z z factor + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_translate_z(mat4s m, float z) { + glm_translate_z(m.raw, z); + return m; +} + +/*! + * @brief rotate existing transform matrix around X axis by angle + * and store result in dest + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @returns rotated matrix + */ +CGLM_INLINE +mat4s +glms_rotate_x(mat4s m, float angle) { + mat4s r; + glm_rotate_x(m.raw, angle, r.raw); + return r; +} + +/*! + * @brief rotate existing transform matrix around Y axis by angle + * and store result in dest + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @returns rotated matrix + */ +CGLM_INLINE +mat4s +glms_rotate_y(mat4s m, float angle) { + mat4s r; + glm_rotate_y(m.raw, angle, r.raw); + return r; +} + +/*! + * @brief rotate existing transform matrix around Z axis by angle + * and store result in dest + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @returns rotated matrix + */ +CGLM_INLINE +mat4s +glms_rotate_z(mat4s m, float angle) { + mat4s r; + glm_rotate_z(m.raw, angle, r.raw); + return r; +} + +/*! + * @brief rotate existing transform matrix around given axis by angle + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @param[in] axis axis + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_rotate(mat4s m, float angle, vec3s axis) { + glm_rotate(m.raw, angle, axis.raw); + return m; +} + +/*! + * @brief rotate existing transform + * around given axis by angle at given pivot point (rotation center) + * + * @param[in] m affine transform + * @param[in] pivot rotation center + * @param[in] angle angle (radians) + * @param[in] axis axis + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_rotate_at(mat4s m, vec3s pivot, float angle, vec3s axis) { + glm_rotate_at(m.raw, pivot.raw, angle, axis.raw); + return m; +} + +/*! + * @brief rotate existing transform matrix around given axis by angle around self (doesn't affected by position) + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @param[in] axis axis + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_spin(mat4s m, float angle, vec3s axis) { + glm_spin(m.raw, angle, axis.raw); + return m; +} + +#endif /* cglms_affines_pre_h */ diff --git a/external/cglm/struct/affine.h b/external/cglm/struct/affine.h new file mode 100644 index 0000000..37f11be --- /dev/null +++ b/external/cglm/struct/affine.h @@ -0,0 +1,201 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_translate(mat4s m, vec3s v); + CGLM_INLINE mat4s glms_translate_x(mat4s m, float x); + CGLM_INLINE mat4s glms_translate_y(mat4s m, float y); + CGLM_INLINE mat4s glms_translate_z(mat4s m, float z); + CGLM_INLINE mat4s glms_translate_make(vec3s v); + CGLM_INLINE mat4s glms_scale_to(mat4s m, vec3s v); + CGLM_INLINE mat4s glms_scale_make(vec3s v); + CGLM_INLINE mat4s glms_scale(mat4s m, vec3s v); + CGLM_INLINE mat4s glms_scale_uni(mat4s m, float s); + CGLM_INLINE mat4s glms_rotate_x(mat4s m, float angle); + CGLM_INLINE mat4s glms_rotate_y(mat4s m, float angle); + CGLM_INLINE mat4s glms_rotate_z(mat4s m, float angle); + CGLM_INLINE mat4s glms_rotate_make(float angle, vec3s axis); + CGLM_INLINE mat4s glms_rotate(mat4s m, float angle, vec3s axis); + CGLM_INLINE mat4s glms_rotate_at(mat4s m, vec3s pivot, float angle, vec3s axis); + CGLM_INLINE mat4s glms_rotate_atm(vec3s pivot, float angle, vec3s axis); + CGLM_INLINE mat4s glms_spin(mat4s m, float angle, vec3s axis); + CGLM_INLINE vec3s glms_decompose_scalev(mat4s m); + CGLM_INLINE bool glms_uniscaled(mat4s m); + CGLM_INLINE void glms_decompose_rs(mat4s m, mat4s * r, vec3s * s); + CGLM_INLINE void glms_decompose(mat4s m, vec4s t, mat4s * r, vec3s * s); + */ + +#ifndef cglms_affines_h +#define cglms_affines_h + +#include "../common.h" +#include "../types-struct.h" +#include "../affine.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" +#include "affine-mat.h" + +/*! + * @brief creates NEW translate transform matrix by v vector + * + * @param[in] v translate vector [x, y, z] + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_translate_make(vec3s v) { + mat4s m; + glm_translate_make(m.raw, v.raw); + return m; +} + +/*! + * @brief creates NEW scale matrix by v vector + * + * @param[in] v scale vector [x, y, z] + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_scale_make(vec3s v) { + mat4s m; + glm_scale_make(m.raw, v.raw); + return m; +} + +/*! + * @brief scales existing transform matrix by v vector + * and stores result in same matrix + * + * @param[in] m affine transform + * @param[in] v scale vector [x, y, z] + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_scale(mat4s m, vec3s v) { + mat4s r; + glm_scale_to(m.raw, v.raw, r.raw); + return r; +} + +/*! + * @brief applies uniform scale to existing transform matrix v = [s, s, s] + * and stores result in same matrix + * + * @param[in] m affine transform + * @param[in] s scale factor + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_scale_uni(mat4s m, float s) { + glm_scale_uni(m.raw, s); + return m; +} + +/*! + * @brief creates NEW rotation matrix by angle and axis + * + * axis will be normalized so you don't need to normalize it + * + * @param[in] angle angle (radians) + * @param[in] axis axis + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_rotate_make(float angle, vec3s axis) { + mat4s m; + glm_rotate_make(m.raw, angle, axis.raw); + return m; +} + +/*! + * @brief creates NEW rotation matrix by angle and axis at given point + * + * this creates rotation matrix, it assumes you don't have a matrix + * + * this should work faster than glm_rotate_at because it reduces + * one glm_translate. + * + * @param[in] pivot rotation center + * @param[in] angle angle (radians) + * @param[in] axis axis + * @returns affine transform + */ +CGLM_INLINE +mat4s +glms_rotate_atm(vec3s pivot, float angle, vec3s axis) { + mat4s m; + glm_rotate_atm(m.raw, pivot.raw, angle, axis.raw); + return m; +} + +/*! + * @brief decompose scale vector + * + * @param[in] m affine transform + * @returns scale vector (Sx, Sy, Sz) + */ +CGLM_INLINE +vec3s +glms_decompose_scalev(mat4s m) { + vec3s r; + glm_decompose_scalev(m.raw, r.raw); + return r; +} + +/*! + * @brief returns true if matrix is uniform scaled. This is helpful for + * creating normal matrix. + * + * @param[in] m m + * + * @return boolean + */ +CGLM_INLINE +bool +glms_uniscaled(mat4s m) { + return glm_uniscaled(m.raw); +} + +/*! + * @brief decompose rotation matrix (mat4) and scale vector [Sx, Sy, Sz] + * DON'T pass projected matrix here + * + * @param[in] m affine transform + * @param[out] r rotation matrix + * @param[out] s scale matrix + */ +CGLM_INLINE +void +glms_decompose_rs(mat4s m, mat4s * __restrict r, vec3s * __restrict s) { + glm_decompose_rs(m.raw, r->raw, s->raw); +} + +/*! + * @brief decompose affine transform, TODO: extract shear factors. + * DON'T pass projected matrix here + * + * @param[in] m affine transform + * @param[out] t translation vector + * @param[out] r rotation matrix (mat4) + * @param[out] s scaling vector [X, Y, Z] + */ +CGLM_INLINE +void +glms_decompose(mat4s m, vec4s * __restrict t, mat4s * __restrict r, vec3s * __restrict s) { + glm_decompose(m.raw, t->raw, r->raw, s->raw); +} + +#include "affine-pre.h" +#include "affine-post.h" + +#endif /* cglms_affines_h */ diff --git a/external/cglm/struct/affine2d.h b/external/cglm/struct/affine2d.h new file mode 100644 index 0000000..ade7c32 --- /dev/null +++ b/external/cglm/struct/affine2d.h @@ -0,0 +1,177 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat3s glms_translate2d(mat3 m, vec2 v) + CGLM_INLINE mat3s glms_translate2d_x(mat3s m, float x) + CGLM_INLINE mat3s glms_translate2d_y(mat3s m, float y) + CGLM_INLINE mat3s glms_translate2d_make(vec2s v) + CGLM_INLINE mat3s glms_scale2d_make(vec2s v) + CGLM_INLINE mat3s glms_scale2d(mat3s m, vec2s v) + CGLM_INLINE mat3s glms_scale2d_uni(mat3s m, float s) + CGLM_INLINE mat3s glms_rotate2d_make(float angle) + CGLM_INLINE mat3s glms_rotate2d(mat3s m, float angle) + CGLM_INLINE mat3s glms_rotate2d_to(mat3s m, float angle) + */ + +#ifndef cglms_affine2ds_h +#define cglms_affine2ds_h + +#include "../common.h" +#include "../types-struct.h" +#include "../affine2d.h" +#include "vec3.h" +#include "mat3.h" + +/*! + * @brief translate existing 2d transform matrix by v vector + * and stores result in same matrix + * + * @param[in] m affine transform + * @param[in] v translate vector [x, y] + * @returns affine transform + */ +CGLM_INLINE +mat3s +glms_translate2d(mat3s m, vec2s v) { + glm_translate2d(m.raw, v.raw); + return m; +} + +/*! + * @brief translate existing 2d transform matrix by x factor + * + * @param[in] m affine transform + * @param[in] x x factor + * @returns affine transform + */ +CGLM_INLINE +mat3s +glms_translate2d_x(mat3s m, float x) { + glm_translate2d_x(m.raw, x); + return m; +} + +/*! + * @brief translate existing 2d transform matrix by y factor + * + * @param[in] m affine transform + * @param[in] y y factor + * @returns affine transform + */ +CGLM_INLINE +mat3s +glms_translate2d_y(mat3s m, float y) { + glm_translate2d_y(m.raw, y); + return m; +} + +/*! + * @brief creates NEW translate 2d transform matrix by v vector + * + * @param[in] v translate vector [x, y] + * @returns affine transform + */ +CGLM_INLINE +mat3s +glms_translate2d_make(vec2s v) { + mat3s m; + glm_translate2d_make(m.raw, v.raw); + return m; +} + +/*! + * @brief creates NEW 2d scale matrix by v vector + * + * @param[in] v scale vector [x, y] + * @returns affine transform + */ +CGLM_INLINE +mat3s +glms_scale2d_make(vec2s v) { + mat3s m; + glm_scale2d_make(m.raw, v.raw); + return m; +} + +/*! + * @brief scales existing 2d transform matrix by v vector + * and stores result in same matrix + * + * @param[in] m affine transform + * @param[in] v scale vector [x, y, z] + * @returns affine transform + */ +CGLM_INLINE +mat3s +glms_scale2d(mat3s m, vec2s v) { + mat3s r; + glm_scale2d_to(m.raw, v.raw, r.raw); + return r; +} + +/*! + * @brief applies uniform scale to existing 2d transform matrix v = [s, s, s] + * and stores result in same matrix + * + * @param[in] m affine transform + * @param[in] s scale factor + * @returns affine transform + */ +CGLM_INLINE +mat3s +glms_scale2d_uni(mat3s m, float s) { + glm_scale2d_uni(m.raw, s); + return m; +} + +/*! + * @brief creates NEW 2d rotation matrix by angle and axis + * + * axis will be normalized so you don't need to normalize it + * + * @param[in] angle angle (radians) + * @returns affine transform + */ +CGLM_INLINE +mat3s +glms_rotate2d_make(float angle) { + mat3s m; + glm_rotate2d_make(m.raw, angle); + return m; +} + +/*! + * @brief rotate existing 2d transform matrix around given axis by angle + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @returns affine transform + */ +CGLM_INLINE +mat3s +glms_rotate2d(mat3s m, float angle) { + glm_rotate2d(m.raw, angle); + return m; +} + +/*! + * @brief rotate existing 2d transform matrix around given axis by angle + * + * @param[in] m affine transform + * @param[in] angle angle (radians) + * @returns affine transform + */ +CGLM_INLINE +mat3s +glms_rotate2d_to(mat3s m, float angle) { + glm_rotate2d(m.raw, angle); + return m; +} + +#endif /* cglms_affine2ds_h */ diff --git a/external/cglm/struct/box.h b/external/cglm/struct/box.h new file mode 100644 index 0000000..ac32328 --- /dev/null +++ b/external/cglm/struct/box.h @@ -0,0 +1,259 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglms_boxs_h +#define cglms_boxs_h + +#include "../common.h" +#include "../types-struct.h" +#include "../box.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" + +/* api definition */ +#define glms_aabb_(NAME) CGLM_STRUCTAPI(aabb, NAME) + +/*! + * @brief apply transform to Axis-Aligned Bounding Box + * + * @param[in] box bounding box + * @param[in] m transform matrix + * @param[out] dest transformed bounding box + */ +CGLM_INLINE +void +glms_aabb_(transform)(vec3s box[2], mat4s m, vec3s dest[2]) { + vec3 rawBox[2]; + vec3 rawDest[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glm_aabb_transform(rawBox, m.raw, rawDest); + glms_vec3_(pack)(dest, rawDest, 2); +} + +/*! + * @brief merges two AABB bounding box and creates new one + * + * two box must be in same space, if one of box is in different space then + * you should consider to convert it's space by glm_box_space + * + * @param[in] box1 bounding box 1 + * @param[in] box2 bounding box 2 + * @param[out] dest merged bounding box + */ +CGLM_INLINE +void +glms_aabb_(merge)(vec3s box1[2], vec3s box2[2], vec3s dest[2]) { + vec3 rawBox1[2]; + vec3 rawBox2[2]; + vec3 rawDest[2]; + + glms_vec3_(unpack)(rawBox1, box1, 2); + glms_vec3_(unpack)(rawBox2, box2, 2); + glm_aabb_merge(rawBox1, rawBox2, rawDest); + glms_vec3_(pack)(dest, rawDest, 2); +} + +/*! + * @brief crops a bounding box with another one. + * + * this could be useful for getting a bbox which fits with view frustum and + * object bounding boxes. In this case you crop view frustum box with objects + * box + * + * @param[in] box bounding box 1 + * @param[in] cropBox crop box + * @param[out] dest cropped bounding box + */ +CGLM_INLINE +void +glms_aabb_(crop)(vec3s box[2], vec3s cropBox[2], vec3s dest[2]) { + vec3 rawBox[2]; + vec3 rawCropBox[2]; + vec3 rawDest[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glms_vec3_(unpack)(rawCropBox, cropBox, 2); + glm_aabb_crop(rawBox, rawCropBox, rawDest); + glms_vec3_(pack)(dest, rawDest, 2); +} + +/*! + * @brief crops a bounding box with another one. + * + * this could be useful for getting a bbox which fits with view frustum and + * object bounding boxes. In this case you crop view frustum box with objects + * box + * + * @param[in] box bounding box + * @param[in] cropBox crop box + * @param[in] clampBox minimum box + * @param[out] dest cropped bounding box + */ +CGLM_INLINE +void +glms_aabb_(crop_until)(vec3s box[2], + vec3s cropBox[2], + vec3s clampBox[2], + vec3s dest[2]) { + glms_aabb_(crop)(box, cropBox, dest); + glms_aabb_(merge)(clampBox, dest, dest); +} + +/*! + * @brief check if AABB intersects with frustum planes + * + * this could be useful for frustum culling using AABB. + * + * OPTIMIZATION HINT: + * if planes order is similar to LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR + * then this method should run even faster because it would only use two + * planes if object is not inside the two planes + * fortunately cglm extracts planes as this order! just pass what you got! + * + * @param[in] box bounding box + * @param[in] planes frustum planes + */ +CGLM_INLINE +bool +glms_aabb_(frustum)(vec3s box[2], vec4s planes[6]) { + vec3 rawBox[2]; + vec4 rawPlanes[6]; + + glms_vec3_(unpack)(rawBox, box, 2); + glms_vec4_(unpack)(rawPlanes, planes, 6); + return glm_aabb_frustum(rawBox, rawPlanes); +} + +/*! + * @brief invalidate AABB min and max values + * + * @param[in, out] box bounding box + */ +CGLM_INLINE +void +glms_aabb_(invalidate)(vec3s box[2]) { + box[0] = glms_vec3_(broadcast)(FLT_MAX); + box[1] = glms_vec3_(broadcast)(-FLT_MAX); +} + +/*! + * @brief check if AABB is valid or not + * + * @param[in] box bounding box + */ +CGLM_INLINE +bool +glms_aabb_(isvalid)(vec3s box[2]) { + vec3 rawBox[2]; + glms_vec3_(unpack)(rawBox, box, 2); + return glm_aabb_isvalid(rawBox); +} + +/*! + * @brief distance between of min and max + * + * @param[in] box bounding box + */ +CGLM_INLINE +float +glms_aabb_(size)(vec3s box[2]) { + return glm_vec3_distance(box[0].raw, box[1].raw); +} + +/*! + * @brief radius of sphere which surrounds AABB + * + * @param[in] box bounding box + */ +CGLM_INLINE +float +glms_aabb_(radius)(vec3s box[2]) { + return glms_aabb_(size)(box) * 0.5f; +} + +/*! + * @brief computes center point of AABB + * + * @param[in] box bounding box + * @returns center of bounding box + */ +CGLM_INLINE +vec3s +glms_aabb_(center)(vec3s box[2]) { + return glms_vec3_(center)(box[0], box[1]); +} + +/*! + * @brief check if two AABB intersects + * + * @param[in] box bounding box + * @param[in] other other bounding box + */ +CGLM_INLINE +bool +glms_aabb_(aabb)(vec3s box[2], vec3s other[2]) { + vec3 rawBox[2]; + vec3 rawOther[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glms_vec3_(unpack)(rawOther, other, 2); + return glm_aabb_aabb(rawBox, rawOther); +} + +/*! + * @brief check if AABB intersects with sphere + * + * https://github.com/erich666/GraphicsGems/blob/master/gems/BoxSphere.c + * Solid Box - Solid Sphere test. + * + * @param[in] box solid bounding box + * @param[in] s solid sphere + */ +CGLM_INLINE +bool +glms_aabb_(sphere)(vec3s box[2], vec4s s) { + vec3 rawBox[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + return glm_aabb_sphere(rawBox, s.raw); +} + +/*! + * @brief check if point is inside of AABB + * + * @param[in] box bounding box + * @param[in] point point + */ +CGLM_INLINE +bool +glms_aabb_(point)(vec3s box[2], vec3s point) { + vec3 rawBox[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + return glm_aabb_point(rawBox, point.raw); +} + +/*! + * @brief check if AABB contains other AABB + * + * @param[in] box bounding box + * @param[in] other other bounding box + */ +CGLM_INLINE +bool +glms_aabb_(contains)(vec3s box[2], vec3s other[2]) { + vec3 rawBox[2]; + vec3 rawOther[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glms_vec3_(unpack)(rawOther, other, 2); + return glm_aabb_contains(rawBox, rawOther); +} + +#endif /* cglms_boxs_h */ diff --git a/external/cglm/struct/cam.h b/external/cglm/struct/cam.h new file mode 100644 index 0000000..ab6cbbb --- /dev/null +++ b/external/cglm/struct/cam.h @@ -0,0 +1,646 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_frustum(float left, float right, + float bottom, float top, + float nearZ, float farZ) + CGLM_INLINE mat4s glms_ortho(float left, float right, + float bottom, float top, + float nearZ, float farZ) + CGLM_INLINE mat4s glms_ortho_aabb(vec3s box[2]); + CGLM_INLINE mat4s glms_ortho_aabb_p(vec3s box[2], float padding); + CGLM_INLINE mat4s glms_ortho_aabb_pz(vec3s box[2], float padding); + CGLM_INLINE mat4s glms_ortho_default(float aspect) + CGLM_INLINE mat4s glms_ortho_default_s(float aspect, float size) + CGLM_INLINE mat4s glms_perspective(float fovy, + float aspect, + float nearZ, + float farZ) + CGLM_INLINE void glms_persp_move_far(mat4s proj, float deltaFar) + CGLM_INLINE mat4s glms_perspective_default(float aspect) + CGLM_INLINE void glms_perspective_resize(mat4s proj, float aspect) + CGLM_INLINE mat4s glms_lookat(vec3s eye, vec3s center, vec3s up) + CGLM_INLINE mat4s glms_look(vec3s eye, vec3s dir, vec3s up) + CGLM_INLINE mat4s glms_look_anyup(vec3s eye, vec3s dir) + CGLM_INLINE void glms_persp_decomp(mat4s proj, + float *nearv, float *farv, + float *top, float *bottom, + float *left, float *right) + CGLM_INLINE void glms_persp_decompv(mat4s proj, float dest[6]) + CGLM_INLINE void glms_persp_decomp_x(mat4s proj, float *left, float *right) + CGLM_INLINE void glms_persp_decomp_y(mat4s proj, float *top, float *bottom) + CGLM_INLINE void glms_persp_decomp_z(mat4s proj, float *nearv, float *farv) + CGLM_INLINE void glms_persp_decomp_far(mat4s proj, float *farZ) + CGLM_INLINE void glms_persp_decomp_near(mat4s proj, float *nearZ) + CGLM_INLINE float glms_persp_fovy(mat4s proj) + CGLM_INLINE float glms_persp_aspect(mat4s proj) + CGLM_INLINE vec4s glms_persp_sizes(mat4s proj, float fovy) + */ + +#ifndef cglms_cam_h +#define cglms_cam_h + +#include "../common.h" +#include "../types-struct.h" +#include "../plane.h" +#include "../cam.h" + +#ifndef CGLM_CLIPSPACE_INCLUDE_ALL +# if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO +# include "clipspace/ortho_lh_zo.h" +# include "clipspace/persp_lh_zo.h" +# include "clipspace/view_lh_zo.h" +# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO +# include "clipspace/ortho_lh_no.h" +# include "clipspace/persp_lh_no.h" +# include "clipspace/view_lh_no.h" +# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO +# include "clipspace/ortho_rh_zo.h" +# include "clipspace/persp_rh_zo.h" +# include "clipspace/view_rh_zo.h" +# elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO +# include "clipspace/ortho_rh_no.h" +# include "clipspace/persp_rh_no.h" +# include "clipspace/view_rh_no.h" +# endif +#else +# include "clipspace/ortho_lh_zo.h" +# include "clipspace/persp_lh_zo.h" +# include "clipspace/ortho_lh_no.h" +# include "clipspace/persp_lh_no.h" +# include "clipspace/ortho_rh_zo.h" +# include "clipspace/persp_rh_zo.h" +# include "clipspace/ortho_rh_no.h" +# include "clipspace/persp_rh_no.h" +# include "clipspace/view_lh_zo.h" +# include "clipspace/view_lh_no.h" +# include "clipspace/view_rh_zo.h" +# include "clipspace/view_rh_no.h" +#endif + +/*! + * @brief set up perspective peprojection matrix + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_frustum(float left, float right, + float bottom, float top, + float nearZ, float farZ) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_frustum_lh_zo(left, right, bottom, top, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_frustum_lh_no(left, right, bottom, top, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_frustum_rh_zo(left, right, bottom, top, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_frustum_rh_no(left, right, bottom, top, nearZ, farZ); +#endif +} + +/*! + * @brief set up orthographic projection matrix + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho(float left, float right, + float bottom, float top, + float nearZ, float farZ) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_ortho_lh_zo(left, right, bottom, top, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_ortho_lh_no(left, right, bottom, top, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_ortho_rh_zo(left, right, bottom, top, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_ortho_rh_no(left, right, bottom, top, nearZ, farZ); +#endif +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb(vec3s box[2]) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_ortho_aabb_lh_zo(box); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_ortho_aabb_lh_no(box); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_ortho_aabb_rh_zo(box); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_ortho_aabb_rh_no(box); +#endif +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb_p(vec3s box[2], float padding) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_ortho_aabb_p_lh_zo(box, padding); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_ortho_aabb_p_lh_no(box, padding); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_ortho_aabb_p_rh_zo(box, padding); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_ortho_aabb_p_rh_no(box, padding); +#endif +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding for near and far + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb_pz(vec3s box[2], float padding) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_ortho_aabb_pz_lh_zo(box, padding); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_ortho_aabb_pz_lh_no(box, padding); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_ortho_aabb_pz_rh_zo(box, padding); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_ortho_aabb_pz_rh_no(box, padding); +#endif +} + +/*! + * @brief set up unit orthographic projection matrix + * + * @param[in] aspect aspect ration ( width / height ) + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_default(float aspect) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_ortho_default_lh_zo(aspect); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_ortho_default_lh_no(aspect); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_ortho_default_rh_zo(aspect); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_ortho_default_rh_no(aspect); +#endif +} + +/*! + * @brief set up orthographic projection matrix with given CUBE size + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] size cube size + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_default_s(float aspect, float size) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_ortho_default_s_lh_zo(aspect, size); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_ortho_default_s_lh_no(aspect, size); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_ortho_default_s_rh_zo(aspect, size); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_ortho_default_s_rh_no(aspect, size); +#endif +} + +/*! + * @brief set up perspective projection matrix + * + * @param[in] fovy field of view angle + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping planes + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_perspective(float fovy, float aspect, float nearZ, float farZ) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_perspective_lh_zo(fovy, aspect, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_perspective_lh_no(fovy, aspect, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_perspective_rh_zo(fovy, aspect, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_perspective_rh_no(fovy, aspect, nearZ, farZ); +#endif +} + +/*! + * @brief extend perspective projection matrix's far distance + * + * NOTE: if you dodn't want to create new matrix then use array api on struct.raw + * like glm_persp_move_far(prooj.raw, deltaFar) to avoid create new mat4 + * each time + * + * this function does not guarantee far >= near, be aware of that! + * + * @param[in, out] proj projection matrix to extend + * @param[in] deltaFar distance from existing far (negative to shink) + */ +CGLM_INLINE +mat4s +glms_persp_move_far(mat4s proj, float deltaFar) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_persp_move_far_lh_zo(proj, deltaFar); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_persp_move_far_lh_no(proj, deltaFar); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_persp_move_far_rh_zo(proj, deltaFar); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_persp_move_far_rh_no(proj, deltaFar); +#endif +} + +/*! + * @brief set up perspective projection matrix with default near/far + * and angle values + * + * @param[in] aspect aspect ratio ( width / height ) + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_perspective_default(float aspect) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_perspective_default_lh_zo(aspect); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_perspective_default_lh_no(aspect); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_perspective_default_rh_zo(aspect); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_perspective_default_rh_no(aspect); +#endif +} + +/*! + * @brief resize perspective matrix by aspect ratio ( width / height ) + * this makes very easy to resize proj matrix when window /viewport + * reized + * + * NOTE: if you dodn't want to create new matrix then use array api on struct.raw + * like glms_perspective_resize(proj.raw, aspect) to avoid create new mat4 + * each time + * + * @param[in, out] proj perspective projection matrix + * @param[in] aspect aspect ratio ( width / height ) + */ +CGLM_INLINE +mat4s +glms_perspective_resize(mat4s proj, float aspect) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_perspective_resize_lh_zo(proj, aspect); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_perspective_resize_lh_no(proj, aspect); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_perspective_resize_rh_zo(proj, aspect); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_perspective_resize_rh_no(proj, aspect); +#endif +} + +/*! + * @brief set up view matrix + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] center center vector + * @param[in] up up vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_lookat(vec3s eye, vec3s center, vec3s up) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_lookat_lh_zo(eye, center, up); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_lookat_lh_no(eye, center, up); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_lookat_rh_zo(eye, center, up); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_lookat_rh_no(eye, center, up); +#endif +} + +/*! + * @brief set up view matrix + * + * convenient wrapper for lookat: if you only have direction not target self + * then this might be useful. Because you need to get target from direction. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[in] up up vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_look(vec3s eye, vec3s dir, vec3s up) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_look_lh_zo(eye, dir, up); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_look_lh_no(eye, dir, up); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_look_rh_zo(eye, dir, up); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_look_rh_no(eye, dir, up); +#endif +} + +/*! + * @brief set up view matrix + * + * convenient wrapper for look: if you only have direction and if you don't + * care what UP vector is then this might be useful to create view matrix + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_look_anyup(vec3s eye, vec3s dir) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_look_anyup_lh_zo(eye, dir); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_look_anyup_lh_no(eye, dir); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_look_anyup_rh_zo(eye, dir); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_look_anyup_rh_no(eye, dir); +#endif +} + +/*! + * @brief decomposes frustum values of perspective projection. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + * @param[out] top top + * @param[out] bottom bottom + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glms_persp_decomp(mat4s proj, + float * __restrict nearZ, float * __restrict farZ, + float * __restrict top, float * __restrict bottom, + float * __restrict left, float * __restrict right) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glms_persp_decomp_lh_zo(proj, nearZ, farZ, top, bottom, left, right); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glms_persp_decomp_lh_no(proj, nearZ, farZ, top, bottom, left, right); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glms_persp_decomp_rh_zo(proj, nearZ, farZ, top, bottom, left, right); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glms_persp_decomp_rh_no(proj, nearZ, farZ, top, bottom, left, right); +#endif +} + +/*! + * @brief decomposes frustum values of perspective projection. + * this makes easy to get all values at once + * + * @param[in] proj perspective projection matrix + * @param[out] dest array + */ +CGLM_INLINE +void +glms_persp_decompv(mat4s proj, float dest[6]) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glms_persp_decompv_lh_zo(proj, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glms_persp_decompv_lh_no(proj, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glms_persp_decompv_rh_zo(proj, dest); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glms_persp_decompv_rh_no(proj, dest); +#endif +} + +/*! + * @brief decomposes left and right values of perspective projection. + * x stands for x axis (left / right axis) + * + * @param[in] proj perspective projection matrix + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glms_persp_decomp_x(mat4s proj, + float * __restrict left, + float * __restrict right) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glms_persp_decomp_x_lh_zo(proj, left, right); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glms_persp_decomp_x_lh_no(proj, left, right); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glms_persp_decomp_x_rh_zo(proj, left, right); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glms_persp_decomp_x_rh_no(proj, left, right); +#endif +} + +/*! + * @brief decomposes top and bottom values of perspective projection. + * y stands for y axis (top / bottom axis) + * + * @param[in] proj perspective projection matrix + * @param[out] top top + * @param[out] bottom bottom + */ +CGLM_INLINE +void +glms_persp_decomp_y(mat4s proj, + float * __restrict top, + float * __restrict bottom) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glms_persp_decomp_y_lh_zo(proj, top, bottom); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glms_persp_decomp_y_lh_no(proj, top, bottom); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glms_persp_decomp_y_rh_zo(proj, top, bottom); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glms_persp_decomp_y_rh_no(proj, top, bottom); +#endif +} + +/*! + * @brief decomposes near and far values of perspective projection. + * z stands for z axis (near / far axis) + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + */ +CGLM_INLINE +void +glms_persp_decomp_z(mat4s proj, + float * __restrict nearZ, + float * __restrict farZ) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glms_persp_decomp_z_lh_zo(proj, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glms_persp_decomp_z_lh_no(proj, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glms_persp_decomp_z_rh_zo(proj, nearZ, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glms_persp_decomp_z_rh_no(proj, nearZ, farZ); +#endif +} + +/*! + * @brief decomposes far value of perspective projection. + * + * @param[in] proj perspective projection matrix + * @param[out] farZ far + */ +CGLM_INLINE +void +glms_persp_decomp_far(mat4s proj, float * __restrict farZ) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glms_persp_decomp_far_lh_zo(proj, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glms_persp_decomp_far_lh_no(proj, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glms_persp_decomp_far_rh_zo(proj, farZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glms_persp_decomp_far_rh_no(proj, farZ); +#endif +} + +/*! + * @brief decomposes near value of perspective projection. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + */ +CGLM_INLINE +void +glms_persp_decomp_near(mat4s proj, float * __restrict nearZ) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + glms_persp_decomp_near_lh_zo(proj, nearZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + glms_persp_decomp_near_lh_no(proj, nearZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + glms_persp_decomp_near_rh_zo(proj, nearZ); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + glms_persp_decomp_near_rh_no(proj, nearZ); +#endif +} + +/*! + * @brief returns field of view angle along the Y-axis (in radians) + * + * if you need to degrees, use glm_deg to convert it or use this: + * fovy_deg = glm_deg(glm_persp_fovy(projMatrix)) + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glms_persp_fovy(mat4s proj) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_persp_fovy_lh_zo(proj); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_persp_fovy_lh_no(proj); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_persp_fovy_rh_zo(proj); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_persp_fovy_rh_no(proj); +#endif +} + +/*! + * @brief returns aspect ratio of perspective projection + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glms_persp_aspect(mat4s proj) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_persp_aspect_lh_zo(proj); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_persp_aspect_lh_no(proj); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_persp_aspect_rh_zo(proj); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_persp_aspect_rh_no(proj); +#endif +} + +/*! + * @brief returns sizes of near and far planes of perspective projection + * + * @param[in] proj perspective projection matrix + * @param[in] fovy fovy (see brief) + * @returns sizes as vector, sizes order: [Wnear, Hnear, Wfar, Hfar] + */ +CGLM_INLINE +vec4s +glms_persp_sizes(mat4s proj, float fovy) { +#if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO + return glms_persp_sizes_lh_zo(proj, fovy); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO + return glms_persp_sizes_lh_no(proj, fovy); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO + return glms_persp_sizes_rh_zo(proj, fovy); +#elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO + return glms_persp_sizes_rh_no(proj, fovy); +#endif +} + +#endif /* cglms_cam_h */ diff --git a/external/cglm/struct/clipspace/ortho_lh_no.h b/external/cglm/struct/clipspace/ortho_lh_no.h new file mode 100644 index 0000000..a743fdf --- /dev/null +++ b/external/cglm/struct/clipspace/ortho_lh_no.h @@ -0,0 +1,154 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_ortho_lh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ) + CGLM_INLINE mat4s glms_ortho_aabb_lh_no(vec3s box[2]); + CGLM_INLINE mat4s glms_ortho_aabb_p_lh_no(vec3s box[2], float padding); + CGLM_INLINE mat4s glms_ortho_aabb_pz_lh_no(vec3s box[2], float padding); + CGLM_INLINE mat4s glms_ortho_default_lh_no(float aspect) + CGLM_INLINE mat4s glms_ortho_default_s_lh_no(float aspect, float size) + */ + +#ifndef cglms_ortho_lh_no_h +#define cglms_ortho_lh_no_h + +#include "../../common.h" +#include "../../types-struct.h" +#include "../../plane.h" +#include "../../cam.h" +#include "../vec3.h" +#include "../../clipspace/ortho_lh_no.h" + +/*! + * @brief set up orthographic projection matrix + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_lh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ) { + mat4s dest; + glm_ortho_lh_no(left, right, bottom, top, nearZ, farZ, dest.raw); + return dest; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb_lh_no(vec3s box[2]) { + mat4s dest; + vec3 rawBox[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glm_ortho_aabb_lh_no(rawBox, dest.raw); + + return dest; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb_p_lh_no(vec3s box[2], float padding) { + mat4s dest; + vec3 rawBox[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glm_ortho_aabb_p_lh_no(rawBox, padding, dest.raw); + + return dest; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding for near and far + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb_pz_lh_no(vec3s box[2], float padding) { + mat4s dest; + vec3 rawBox[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glm_ortho_aabb_pz_lh_no(rawBox, padding, dest.raw); + + return dest; +} + +/*! + * @brief set up unit orthographic projection matrix + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] aspect aspect ration ( width / height ) + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_default_lh_no(float aspect) { + mat4s dest; + glm_ortho_default_lh_no(aspect, dest.raw); + return dest; +} + +/*! + * @brief set up orthographic projection matrix with given CUBE size + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] size cube size + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_default_s_lh_no(float aspect, float size) { + mat4s dest; + glm_ortho_default_s_lh_no(aspect, size, dest.raw); + return dest; +} + +#endif /* cglms_ortho_lh_no_h */ diff --git a/external/cglm/struct/clipspace/ortho_lh_zo.h b/external/cglm/struct/clipspace/ortho_lh_zo.h new file mode 100644 index 0000000..4f15656 --- /dev/null +++ b/external/cglm/struct/clipspace/ortho_lh_zo.h @@ -0,0 +1,154 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_ortho_lh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ) + CGLM_INLINE mat4s glms_ortho_aabb_lh_zo(vec3s box[2]); + CGLM_INLINE mat4s glms_ortho_aabb_p_lh_zo(vec3s box[2], float padding); + CGLM_INLINE mat4s glms_ortho_aabb_pz_lh_zo(vec3s box[2], float padding); + CGLM_INLINE mat4s glms_ortho_default_lh_zo(float aspect) + CGLM_INLINE mat4s glms_ortho_default_s_lh_zo(float aspect, float size) + */ + +#ifndef cglms_ortho_lh_zo_h +#define cglms_ortho_lh_zo_h + +#include "../../common.h" +#include "../../types-struct.h" +#include "../../plane.h" +#include "../../cam.h" +#include "../vec3.h" +#include "../../clipspace/ortho_lh_zo.h" + +/*! + * @brief set up orthographic projection matrix + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_lh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ) { + mat4s dest; + glm_ortho_lh_zo(left, right, bottom, top, nearZ, farZ, dest.raw); + return dest; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb_lh_zo(vec3s box[2]) { + mat4s dest; + vec3 rawBox[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glm_ortho_aabb_lh_zo(rawBox, dest.raw); + + return dest; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb_p_lh_zo(vec3s box[2], float padding) { + mat4s dest; + vec3 rawBox[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glm_ortho_aabb_p_lh_zo(rawBox, padding, dest.raw); + + return dest; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding for near and far + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb_pz_lh_zo(vec3s box[2], float padding) { + mat4s dest; + vec3 rawBox[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glm_ortho_aabb_pz_lh_zo(rawBox, padding, dest.raw); + + return dest; +} + +/*! + * @brief set up unit orthographic projection matrix + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] aspect aspect ration ( width / height ) + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_default_lh_zo(float aspect) { + mat4s dest; + glm_ortho_default_lh_zo(aspect, dest.raw); + return dest; +} + +/*! + * @brief set up orthographic projection matrix with given CUBE size + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] size cube size + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_default_s_lh_zo(float aspect, float size) { + mat4s dest; + glm_ortho_default_s_lh_zo(aspect, size, dest.raw); + return dest; +} + +#endif /* cglms_ortho_lh_zo_h */ diff --git a/external/cglm/struct/clipspace/ortho_rh_no.h b/external/cglm/struct/clipspace/ortho_rh_no.h new file mode 100644 index 0000000..ecb4d32 --- /dev/null +++ b/external/cglm/struct/clipspace/ortho_rh_no.h @@ -0,0 +1,154 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_ortho_rh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ) + CGLM_INLINE mat4s glms_ortho_aabb_rh_no(vec3s box[2]); + CGLM_INLINE mat4s glms_ortho_aabb_p_rh_no(vec3s box[2], float padding); + CGLM_INLINE mat4s glms_ortho_aabb_pz_rh_no(vec3s box[2], float padding); + CGLM_INLINE mat4s glms_ortho_default_rh_no(float aspect) + CGLM_INLINE mat4s glms_ortho_default_s_rh_no(float aspect, float size) + */ + +#ifndef cglms_ortho_rh_no_h +#define cglms_ortho_rh_no_h + +#include "../../common.h" +#include "../../types-struct.h" +#include "../../plane.h" +#include "../../cam.h" +#include "../vec3.h" +#include "../../clipspace/ortho_rh_no.h" + +/*! + * @brief set up orthographic projection matrix + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_rh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ) { + mat4s dest; + glm_ortho_rh_no(left, right, bottom, top, nearZ, farZ, dest.raw); + return dest; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb_rh_no(vec3s box[2]) { + mat4s dest; + vec3 rawBox[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glm_ortho_aabb_rh_no(rawBox, dest.raw); + + return dest; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb_p_rh_no(vec3s box[2], float padding) { + mat4s dest; + vec3 rawBox[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glm_ortho_aabb_p_rh_no(rawBox, padding, dest.raw); + + return dest; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding for near and far + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb_pz_rh_no(vec3s box[2], float padding) { + mat4s dest; + vec3 rawBox[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glm_ortho_aabb_pz_rh_no(rawBox, padding, dest.raw); + + return dest; +} + +/*! + * @brief set up unit orthographic projection matrix + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] aspect aspect ration ( width / height ) + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_default_rh_no(float aspect) { + mat4s dest; + glm_ortho_default_rh_no(aspect, dest.raw); + return dest; +} + +/*! + * @brief set up orthographic projection matrix with given CUBE size + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] size cube size + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_default_s_rh_no(float aspect, float size) { + mat4s dest; + glm_ortho_default_s_rh_no(aspect, size, dest.raw); + return dest; +} + +#endif /* cglms_ortho_rh_no_h */ diff --git a/external/cglm/struct/clipspace/ortho_rh_zo.h b/external/cglm/struct/clipspace/ortho_rh_zo.h new file mode 100644 index 0000000..2d50ee1 --- /dev/null +++ b/external/cglm/struct/clipspace/ortho_rh_zo.h @@ -0,0 +1,154 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_ortho_rh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ) + CGLM_INLINE mat4s glms_ortho_aabb_rh_zo(vec3s box[2]); + CGLM_INLINE mat4s glms_ortho_aabb_p_rh_zo(vec3s box[2], float padding); + CGLM_INLINE mat4s glms_ortho_aabb_pz_rh_zo(vec3s box[2], float padding); + CGLM_INLINE mat4s glms_ortho_default_rh_zo(float aspect) + CGLM_INLINE mat4s glms_ortho_default_s_rh_zo(float aspect, float size) + */ + +#ifndef cglms_ortho_rh_zo_h +#define cglms_ortho_rh_zo_h + +#include "../../common.h" +#include "../../types-struct.h" +#include "../../plane.h" +#include "../../cam.h" +#include "../vec3.h" +#include "../../clipspace/ortho_rh_zo.h" + +/*! + * @brief set up orthographic projection matrix + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_rh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ) { + mat4s dest; + glm_ortho_rh_zo(left, right, bottom, top, nearZ, farZ, dest.raw); + return dest; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb_rh_zo(vec3s box[2]) { + mat4s dest; + vec3 rawBox[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glm_ortho_aabb_rh_zo(rawBox, dest.raw); + + return dest; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb_p_rh_zo(vec3s box[2], float padding) { + mat4s dest; + vec3 rawBox[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glm_ortho_aabb_p_rh_zo(rawBox, padding, dest.raw); + + return dest; +} + +/*! + * @brief set up orthographic projection matrix using bounding box + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * bounding box (AABB) must be in view space + * + * @param[in] box AABB + * @param[in] padding padding for near and far + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_aabb_pz_rh_zo(vec3s box[2], float padding) { + mat4s dest; + vec3 rawBox[2]; + + glms_vec3_(unpack)(rawBox, box, 2); + glm_ortho_aabb_pz_rh_zo(rawBox, padding, dest.raw); + + return dest; +} + +/*! + * @brief set up unit orthographic projection matrix + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] aspect aspect ration ( width / height ) + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_default_rh_zo(float aspect) { + mat4s dest; + glm_ortho_default_rh_zo(aspect, dest.raw); + return dest; +} + +/*! + * @brief set up orthographic projection matrix with given CUBE size + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] size cube size + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_ortho_default_s_rh_zo(float aspect, float size) { + mat4s dest; + glm_ortho_default_s_rh_zo(aspect, size, dest.raw); + return dest; +} + +#endif /* cglms_ortho_rh_zo_h */ diff --git a/external/cglm/struct/clipspace/persp_lh_no.h b/external/cglm/struct/clipspace/persp_lh_no.h new file mode 100644 index 0000000..bc35ca0 --- /dev/null +++ b/external/cglm/struct/clipspace/persp_lh_no.h @@ -0,0 +1,312 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_frustum_lh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ) + CGLM_INLINE mat4s glms_perspective_lh_no(float fovy, + float aspect, + float nearZ, + float farZ) + CGLM_INLINE void glms_persp_move_far_lh_no(mat4s proj, float deltaFar) + CGLM_INLINE mat4s glms_perspective_default_lh_no(float aspect) + CGLM_INLINE void glms_perspective_resize_lh_no(mat4s proj, float aspect) + CGLM_INLINE void glms_persp_decomp_lh_no(mat4s proj, + float *nearv, float *farv, + float *top, float *bottom, + float *left, float *right) + CGLM_INLINE void glms_persp_decompv_lh_no(mat4s proj, float dest[6]) + CGLM_INLINE void glms_persp_decomp_x_lh_no(mat4s proj, float *left, float *right) + CGLM_INLINE void glms_persp_decomp_y_lh_no(mat4s proj, float *top, float *bottom) + CGLM_INLINE void glms_persp_decomp_z_lh_no(mat4s proj, float *nearv, float *farv) + CGLM_INLINE void glms_persp_decomp_far_lh_no(mat4s proj, float *farZ) + CGLM_INLINE void glms_persp_decomp_near_lh_no(mat4s proj, float *nearZ) + CGLM_INLINE float glms_persp_fovy_lh_no(mat4s proj) + CGLM_INLINE float glms_persp_aspect_lh_no(mat4s proj) + CGLM_INLINE vec4s glms_persp_sizes_lh_no(mat4s proj, float fovy) + */ + +#ifndef cglms_persp_lh_no_h +#define cglms_persp_lh_no_h + +#include "../../common.h" +#include "../../types-struct.h" +#include "../../plane.h" +#include "../../cam.h" +#include "../../clipspace/persp_lh_no.h" + +/*! + * @brief set up perspective peprojection matrix + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_frustum_lh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ) { + mat4s dest; + glm_frustum_lh_no(left, right, bottom, top, nearZ, farZ, dest.raw); + return dest; +} + +/*! + * @brief set up perspective projection matrix + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] fovy field of view angle + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping planes + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_perspective_lh_no(float fovy, float aspect, float nearZ, float farZ) { + mat4s dest; + glm_perspective_lh_no(fovy, aspect, nearZ, farZ, dest.raw); + return dest; +} + +/*! + * @brief extend perspective projection matrix's far distance + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * NOTE: if you dodn't want to create new matrix then use array api on struct.raw + * like glms_persp_move_far_lh_no(prooj.raw, deltaFar) to avoid create new mat4 + * each time + * + * this function does not guarantee far >= near, be aware of that! + * + * @param[in, out] proj projection matrix to extend + * @param[in] deltaFar distance from existing far (negative to shink) + */ +CGLM_INLINE +mat4s +glms_persp_move_far_lh_no(mat4s proj, float deltaFar) { + mat4s dest; + dest = proj; + glm_persp_move_far_lh_no(dest.raw, deltaFar); + return dest; +} + +/*! + * @brief set up perspective projection matrix with default near/far + * and angle values with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_perspective_default_lh_no(float aspect) { + mat4s dest; + glm_perspective_default_lh_no(aspect, dest.raw); + return dest; +} + +/*! + * @brief resize perspective matrix by aspect ratio ( width / height ) + * this makes very easy to resize proj matrix when window /viewport + * reized with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * NOTE: if you dodn't want to create new matrix then use array api on struct.raw + * like glm_perspective_resize_lh_no(proj.raw, aspect) to avoid create new mat4 + * each time + * + * @param[in, out] proj perspective projection matrix + * @param[in] aspect aspect ratio ( width / height ) + */ +CGLM_INLINE +mat4s +glms_perspective_resize_lh_no(mat4s proj, float aspect) { + mat4s dest; + dest = proj; + glm_perspective_resize_lh_no(aspect, dest.raw); + return dest; +} + +/*! + * @brief decomposes frustum values of perspective projection. + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + * @param[out] top top + * @param[out] bottom bottom + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glms_persp_decomp_lh_no(mat4s proj, + float * __restrict nearZ, float * __restrict farZ, + float * __restrict top, float * __restrict bottom, + float * __restrict left, float * __restrict right) { + glm_persp_decomp_lh_no(proj.raw, nearZ, farZ, top, bottom, left, right); +} + +/*! + * @brief decomposes frustum values of perspective projection. + * this makes easy to get all values at once + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] dest array + */ +CGLM_INLINE +void +glms_persp_decompv_lh_no(mat4s proj, float dest[6]) { + glm_persp_decompv_lh_no(proj.raw, dest); +} + +/*! + * @brief decomposes left and right values of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * x stands for x axis (left / right axis) + * + * @param[in] proj perspective projection matrix + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glms_persp_decomp_x_lh_no(mat4s proj, + float * __restrict left, + float * __restrict right) { + glm_persp_decomp_x_lh_no(proj.raw, left, right); +} + +/*! + * @brief decomposes top and bottom values of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * y stands for y axis (top / bottom axis) + * + * @param[in] proj perspective projection matrix + * @param[out] top top + * @param[out] bottom bottom + */ +CGLM_INLINE +void +glms_persp_decomp_y_lh_no(mat4s proj, + float * __restrict top, + float * __restrict bottom) { + glm_persp_decomp_y_lh_no(proj.raw, top, bottom); +} + +/*! + * @brief decomposes near and far values of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * z stands for z axis (near / far axis) + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + */ +CGLM_INLINE +void +glms_persp_decomp_z_lh_no(mat4s proj, + float * __restrict nearZ, + float * __restrict farZ) { + glm_persp_decomp_z_lh_no(proj.raw, nearZ, farZ); +} + +/*! + * @brief decomposes far value of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] farZ far + */ +CGLM_INLINE +void +glms_persp_decomp_far_lh_no(mat4s proj, float * __restrict farZ) { + glm_persp_decomp_far_lh_no(proj.raw, farZ); +} + +/*! + * @brief decomposes near value of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + */ +CGLM_INLINE +void +glms_persp_decomp_near_lh_no(mat4s proj, float * __restrict nearZ) { + glm_persp_decomp_near_lh_no(proj.raw, nearZ); +} + +/*! + * @brief returns field of view angle along the Y-axis (in radians) + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * if you need to degrees, use glm_deg to convert it or use this: + * fovy_deg = glm_deg(glm_persp_fovy(projMatrix)) + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glms_persp_fovy_lh_no(mat4s proj) { + return glm_persp_fovy_lh_no(proj.raw); +} + +/*! + * @brief returns aspect ratio of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glms_persp_aspect_lh_no(mat4s proj) { + return glm_persp_aspect_lh_no(proj.raw); +} + +/*! + * @brief returns sizes of near and far planes of perspective projection + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[in] fovy fovy (see brief) + * @returns sizes as vector, sizes order: [Wnear, Hnear, Wfar, Hfar] + */ +CGLM_INLINE +vec4s +glms_persp_sizes_lh_no(mat4s proj, float fovy) { + vec4s dest; + glm_persp_sizes_lh_no(proj.raw, fovy, dest.raw); + return dest; +} + +#endif /* cglms_persp_lh_no_h */ diff --git a/external/cglm/struct/clipspace/persp_lh_zo.h b/external/cglm/struct/clipspace/persp_lh_zo.h new file mode 100644 index 0000000..29af065 --- /dev/null +++ b/external/cglm/struct/clipspace/persp_lh_zo.h @@ -0,0 +1,312 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_frustum_lh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ) + CGLM_INLINE mat4s glms_perspective_lh_zo(float fovy, + float aspect, + float nearZ, + float farZ) + CGLM_INLINE void glms_persp_move_far_lh_zo(mat4s proj, float deltaFar) + CGLM_INLINE mat4s glms_perspective_default_lh_zo(float aspect) + CGLM_INLINE void glms_perspective_resize_lh_zo(mat4s proj, float aspect) + CGLM_INLINE void glms_persp_decomp_lh_zo(mat4s proj, + float *nearv, float *farv, + float *top, float *bottom, + float *left, float *right) + CGLM_INLINE void glms_persp_decompv_lh_zo(mat4s proj, float dest[6]) + CGLM_INLINE void glms_persp_decomp_x_lh_zo(mat4s proj, float *left, float *right) + CGLM_INLINE void glms_persp_decomp_y_lh_zo(mat4s proj, float *top, float *bottom) + CGLM_INLINE void glms_persp_decomp_z_lh_zo(mat4s proj, float *nearv, float *farv) + CGLM_INLINE void glms_persp_decomp_far_lh_zo(mat4s proj, float *farZ) + CGLM_INLINE void glms_persp_decomp_near_lh_zo(mat4s proj, float *nearZ) + CGLM_INLINE float glms_persp_fovy_lh_zo(mat4s proj) + CGLM_INLINE float glms_persp_aspect_lh_zo(mat4s proj) + CGLM_INLINE vec4s glms_persp_sizes_lh_zo(mat4s proj, float fovy) + */ + +#ifndef cglms_persp_lh_zo_h +#define cglms_persp_lh_zo_h + +#include "../../common.h" +#include "../../types-struct.h" +#include "../../plane.h" +#include "../../cam.h" +#include "../../clipspace/persp_lh_zo.h" + +/*! + * @brief set up perspective peprojection matrix + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_frustum_lh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ) { + mat4s dest; + glm_frustum_lh_zo(left, right, bottom, top, nearZ, farZ, dest.raw); + return dest; +} + +/*! + * @brief set up perspective projection matrix + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] fovy field of view angle + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping planes + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_perspective_lh_zo(float fovy, float aspect, float nearZ, float farZ) { + mat4s dest; + glm_perspective_lh_zo(fovy, aspect, nearZ, farZ, dest.raw); + return dest; +} + +/*! + * @brief extend perspective projection matrix's far distance + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * NOTE: if you dodn't want to create new matrix then use array api on struct.raw + * like glms_persp_move_far_lh_zo(prooj.raw, deltaFar) to avoid create new mat4 + * each time + * + * this function does not guarantee far >= near, be aware of that! + * + * @param[in, out] proj projection matrix to extend + * @param[in] deltaFar distance from existing far (negative to shink) + */ +CGLM_INLINE +mat4s +glms_persp_move_far_lh_zo(mat4s proj, float deltaFar) { + mat4s dest; + dest = proj; + glm_persp_move_far_lh_zo(dest.raw, deltaFar); + return dest; +} + +/*! + * @brief set up perspective projection matrix with default near/far + * and angle values with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_perspective_default_lh_zo(float aspect) { + mat4s dest; + glm_perspective_default_lh_zo(aspect, dest.raw); + return dest; +} + +/*! + * @brief resize perspective matrix by aspect ratio ( width / height ) + * this makes very easy to resize proj matrix when window /viewport + * reized with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * NOTE: if you dodn't want to create new matrix then use array api on struct.raw + * like glms_perspective_resize_lh_zo(proj.raw, aspect) to avoid create new mat4 + * each time + * + * @param[in, out] proj perspective projection matrix + * @param[in] aspect aspect ratio ( width / height ) + */ +CGLM_INLINE +mat4s +glms_perspective_resize_lh_zo(mat4s proj, float aspect) { + mat4s dest; + dest = proj; + glm_perspective_resize_lh_zo(aspect, dest.raw); + return dest; +} + +/*! + * @brief decomposes frustum values of perspective projection. + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + * @param[out] top top + * @param[out] bottom bottom + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glms_persp_decomp_lh_zo(mat4s proj, + float * __restrict nearZ, float * __restrict farZ, + float * __restrict top, float * __restrict bottom, + float * __restrict left, float * __restrict right) { + glm_persp_decomp_lh_zo(proj.raw, nearZ, farZ, top, bottom, left, right); +} + +/*! + * @brief decomposes frustum values of perspective projection. + * this makes easy to get all values at once + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] dest array + */ +CGLM_INLINE +void +glms_persp_decompv_lh_zo(mat4s proj, float dest[6]) { + glm_persp_decompv_lh_zo(proj.raw, dest); +} + +/*! + * @brief decomposes left and right values of perspective projection + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * x stands for x axis (left / right axis) + * + * @param[in] proj perspective projection matrix + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glms_persp_decomp_x_lh_zo(mat4s proj, + float * __restrict left, + float * __restrict right) { + glm_persp_decomp_x_lh_zo(proj.raw, left, right); +} + +/*! + * @brief decomposes top and bottom values of perspective projection + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * y stands for y axis (top / bottom axis) + * + * @param[in] proj perspective projection matrix + * @param[out] top top + * @param[out] bottom bottom + */ +CGLM_INLINE +void +glms_persp_decomp_y_lh_zo(mat4s proj, + float * __restrict top, + float * __restrict bottom) { + glm_persp_decomp_y_lh_zo(proj.raw, top, bottom); +} + +/*! + * @brief decomposes near and far values of perspective projection + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * z stands for z axis (near / far axis) + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + */ +CGLM_INLINE +void +glms_persp_decomp_z_lh_zo(mat4s proj, + float * __restrict nearZ, + float * __restrict farZ) { + glm_persp_decomp_z_lh_zo(proj.raw, nearZ, farZ); +} + +/*! + * @brief decomposes far value of perspective projection + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] farZ far + */ +CGLM_INLINE +void +glms_persp_decomp_far_lh_zo(mat4s proj, float * __restrict farZ) { + glm_persp_decomp_far_lh_zo(proj.raw, farZ); +} + +/*! + * @brief decomposes near value of perspective projection + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + */ +CGLM_INLINE +void +glms_persp_decomp_near_lh_zo(mat4s proj, float * __restrict nearZ) { + glm_persp_decomp_near_lh_zo(proj.raw, nearZ); +} + +/*! + * @brief returns field of view angle along the Y-axis (in radians) + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * if you need to degrees, use glm_deg to convert it or use this: + * fovy_deg = glm_deg(glm_persp_fovy(projMatrix)) + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glms_persp_fovy_lh_zo(mat4s proj) { + return glm_persp_fovy_lh_zo(proj.raw); +} + +/*! + * @brief returns aspect ratio of perspective projection + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glms_persp_aspect_lh_zo(mat4s proj) { + return glm_persp_aspect_lh_zo(proj.raw); +} + +/*! + * @brief returns sizes of near and far planes of perspective projection + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[in] fovy fovy (see brief) + * @returns sizes as vector, sizes order: [Wnear, Hnear, Wfar, Hfar] + */ +CGLM_INLINE +vec4s +glms_persp_sizes_lh_zo(mat4s proj, float fovy) { + vec4s dest; + glm_persp_sizes_lh_zo(proj.raw, fovy, dest.raw); + return dest; +} + +#endif /* cglms_persp_lh_zo_h */ diff --git a/external/cglm/struct/clipspace/persp_rh_no.h b/external/cglm/struct/clipspace/persp_rh_no.h new file mode 100644 index 0000000..7120fdf --- /dev/null +++ b/external/cglm/struct/clipspace/persp_rh_no.h @@ -0,0 +1,312 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_frustum_rh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ) + CGLM_INLINE mat4s glms_perspective_rh_no(float fovy, + float aspect, + float nearZ, + float farZ) + CGLM_INLINE void glms_persp_move_far_rh_no(mat4s proj, float deltaFar) + CGLM_INLINE mat4s glms_perspective_default_rh_no(float aspect) + CGLM_INLINE void glms_perspective_resize_rh_no(mat4s proj, float aspect) + CGLM_INLINE void glms_persp_decomp_rh_no(mat4s proj, + float *nearv, float *farv, + float *top, float *bottom, + float *left, float *right) + CGLM_INLINE void glms_persp_decompv_rh_no(mat4s proj, float dest[6]) + CGLM_INLINE void glms_persp_decomp_x_rh_no(mat4s proj, float *left, float *right) + CGLM_INLINE void glms_persp_decomp_y_rh_no(mat4s proj, float *top, float *bottom) + CGLM_INLINE void glms_persp_decomp_z_rh_no(mat4s proj, float *nearv, float *farv) + CGLM_INLINE void glms_persp_decomp_far_rh_no(mat4s proj, float *farZ) + CGLM_INLINE void glms_persp_decomp_near_rh_no(mat4s proj, float *nearZ) + CGLM_INLINE float glms_persp_fovy_rh_no(mat4s proj) + CGLM_INLINE float glms_persp_aspect_rh_no(mat4s proj) + CGLM_INLINE vec4s glms_persp_sizes_rh_no(mat4s proj, float fovy) + */ + +#ifndef cglms_persp_rh_no_h +#define cglms_persp_rh_no_h + +#include "../../common.h" +#include "../../types-struct.h" +#include "../../plane.h" +#include "../../cam.h" +#include "../../clipspace/persp_rh_no.h" + +/*! + * @brief set up perspective peprojection matrix + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_frustum_rh_no(float left, float right, + float bottom, float top, + float nearZ, float farZ) { + mat4s dest; + glm_frustum_rh_no(left, right, bottom, top, nearZ, farZ, dest.raw); + return dest; +} + +/*! + * @brief set up perspective projection matrix + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] fovy field of view angle + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping planes + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_perspective_rh_no(float fovy, float aspect, float nearZ, float farZ) { + mat4s dest; + glm_perspective_rh_no(fovy, aspect, nearZ, farZ, dest.raw); + return dest; +} + +/*! + * @brief extend perspective projection matrix's far distance + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * NOTE: if you dodn't want to create new matrix then use array api on struct.raw + * like glms_persp_move_far_rh_no(prooj.raw, deltaFar) to avoid create new mat4 + * each time + * s + * this function does not guarantee far >= near, be aware of that! + * + * @param[in, out] proj projection matrix to extend + * @param[in] deltaFar distance from existing far (negative to shink) + */ +CGLM_INLINE +mat4s +glms_persp_move_far_rh_no(mat4s proj, float deltaFar) { + mat4s dest; + dest = proj; + glm_persp_move_far_rh_no(dest.raw, deltaFar); + return dest; +} + +/*! + * @brief set up perspective projection matrix with default near/far + * and angle values with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_perspective_default_rh_no(float aspect) { + mat4s dest; + glm_perspective_default_rh_no(aspect, dest.raw); + return dest; +} + +/*! + * @brief resize perspective matrix by aspect ratio ( width / height ) + * this makes very easy to resize proj matrix when window /viewport + * reized with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * NOTE: if you dodn't want to create new matrix then use array api on struct.raw + * like glm_perspective_resize_rh_no(proj.raw, aspect) to avoid create new mat4 + * each time + * + * @param[in, out] proj perspective projection matrix + * @param[in] aspect aspect ratio ( width / height ) + */ +CGLM_INLINE +mat4s +glms_perspective_resize_rh_no(mat4s proj, float aspect) { + mat4s dest; + dest = proj; + glm_perspective_resize_rh_no(aspect, dest.raw); + return dest; +} + +/*! + * @brief decomposes frustum values of perspective projection. + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + * @param[out] top top + * @param[out] bottom bottom + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glms_persp_decomp_rh_no(mat4s proj, + float * __restrict nearZ, float * __restrict farZ, + float * __restrict top, float * __restrict bottom, + float * __restrict left, float * __restrict right) { + glm_persp_decomp_rh_no(proj.raw, nearZ, farZ, top, bottom, left, right); +} + +/*! + * @brief decomposes frustum values of perspective projection. + * this makes easy to get all values at once + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] dest array + */ +CGLM_INLINE +void +glms_persp_decompv_rh_no(mat4s proj, float dest[6]) { + glm_persp_decompv_rh_no(proj.raw, dest); +} + +/*! + * @brief decomposes left and right values of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * x stands for x axis (left / right axis) + * + * @param[in] proj perspective projection matrix + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glms_persp_decomp_x_rh_no(mat4s proj, + float * __restrict left, + float * __restrict right) { + glm_persp_decomp_x_rh_no(proj.raw, left, right); +} + +/*! + * @brief decomposes top and bottom values of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * y stands for y axis (top / bottom axis) + * + * @param[in] proj perspective projection matrix + * @param[out] top top + * @param[out] bottom bottom + */ +CGLM_INLINE +void +glms_persp_decomp_y_rh_no(mat4s proj, + float * __restrict top, + float * __restrict bottom) { + glm_persp_decomp_y_rh_no(proj.raw, top, bottom); +} + +/*! + * @brief decomposes near and far values of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * z stands for z axis (near / far axis) + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + */ +CGLM_INLINE +void +glms_persp_decomp_z_rh_no(mat4s proj, + float * __restrict nearZ, + float * __restrict farZ) { + glm_persp_decomp_z_rh_no(proj.raw, nearZ, farZ); +} + +/*! + * @brief decomposes far value of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] farZ far + */ +CGLM_INLINE +void +glms_persp_decomp_far_rh_no(mat4s proj, float * __restrict farZ) { + glm_persp_decomp_far_rh_no(proj.raw, farZ); +} + +/*! + * @brief decomposes near value of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + */ +CGLM_INLINE +void +glms_persp_decomp_near_rh_no(mat4s proj, float * __restrict nearZ) { + glm_persp_decomp_near_rh_no(proj.raw, nearZ); +} + +/*! + * @brief returns field of view angle along the Y-axis (in radians) + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * if you need to degrees, use glm_deg to convert it or use this: + * fovy_deg = glm_deg(glm_persp_fovy(projMatrix)) + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glms_persp_fovy_rh_no(mat4s proj) { + return glm_persp_fovy_rh_no(proj.raw); +} + +/*! + * @brief returns aspect ratio of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glms_persp_aspect_rh_no(mat4s proj) { + return glm_persp_aspect_rh_no(proj.raw); +} + +/*! + * @brief returns sizes of near and far planes of perspective projection + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * @param[in] proj perspective projection matrix + * @param[in] fovy fovy (see brief) + * @returns sizes as vector, sizes order: [Wnear, Hnear, Wfar, Hfar] + */ +CGLM_INLINE +vec4s +glms_persp_sizes_rh_no(mat4s proj, float fovy) { + vec4s dest; + glm_persp_sizes_rh_no(proj.raw, fovy, dest.raw); + return dest; +} + +#endif /* cglms_persp_rh_no_h */ diff --git a/external/cglm/struct/clipspace/persp_rh_zo.h b/external/cglm/struct/clipspace/persp_rh_zo.h new file mode 100644 index 0000000..e3585a2 --- /dev/null +++ b/external/cglm/struct/clipspace/persp_rh_zo.h @@ -0,0 +1,312 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_frustum_rh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ) + CGLM_INLINE mat4s glms_perspective_rh_zo(float fovy, + float aspect, + float nearZ, + float farZ) + CGLM_INLINE void glms_persp_move_far_rh_zo(mat4s proj, float deltaFar) + CGLM_INLINE mat4s glms_perspective_default_rh_zo(float aspect) + CGLM_INLINE void glms_perspective_resize_rh_zo(mat4s proj, float aspect) + CGLM_INLINE void glms_persp_decomp_rh_zo(mat4s proj, + float *nearv, float *farv, + float *top, float *bottom, + float *left, float *right) + CGLM_INLINE void glms_persp_decompv_rh_zo(mat4s proj, float dest[6]) + CGLM_INLINE void glms_persp_decomp_x_rh_zo(mat4s proj, float *left, float *right) + CGLM_INLINE void glms_persp_decomp_y_rh_zo(mat4s proj, float *top, float *bottom) + CGLM_INLINE void glms_persp_decomp_z_rh_zo(mat4s proj, float *nearv, float *farv) + CGLM_INLINE void glms_persp_decomp_far_rh_zo(mat4s proj, float *farZ) + CGLM_INLINE void glms_persp_decomp_near_rh_zo(mat4s proj, float *nearZ) + CGLM_INLINE float glms_persp_fovy_rh_zo(mat4s proj) + CGLM_INLINE float glms_persp_aspect_rh_zo(mat4s proj) + CGLM_INLINE vec4s glms_persp_sizes_rh_zo(mat4s proj, float fovy) + */ + +#ifndef cglms_persp_rh_zo_h +#define cglms_persp_rh_zo_h + +#include "../../common.h" +#include "../../types-struct.h" +#include "../../plane.h" +#include "../../cam.h" +#include "../../clipspace/persp_rh_zo.h" + +/*! + * @brief set up perspective peprojection matrix + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] left viewport.left + * @param[in] right viewport.right + * @param[in] bottom viewport.bottom + * @param[in] top viewport.top + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping plane + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_frustum_rh_zo(float left, float right, + float bottom, float top, + float nearZ, float farZ) { + mat4s dest; + glm_frustum_rh_zo(left, right, bottom, top, nearZ, farZ, dest.raw); + return dest; +} + +/*! + * @brief set up perspective projection matrix + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] fovy field of view angle + * @param[in] aspect aspect ratio ( width / height ) + * @param[in] nearZ near clipping plane + * @param[in] farZ far clipping planes + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_perspective_rh_zo(float fovy, float aspect, float nearZ, float farZ) { + mat4s dest; + glm_perspective_rh_zo(fovy, aspect, nearZ, farZ, dest.raw); + return dest; +} + +/*! + * @brief extend perspective projection matrix's far distance + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * NOTE: if you dodn't want to create new matrix then use array api on struct.raw + * like glms_persp_move_far_rh_zo(prooj.raw, deltaFar) to avoid create new mat4 + * each time + * + * this function does not guarantee far >= near, be aware of that! + * + * @param[in, out] proj projection matrix to extend + * @param[in] deltaFar distance from existing far (negative to shink) + */ +CGLM_INLINE +mat4s +glms_persp_move_far_rh_zo(mat4s proj, float deltaFar) { + mat4s dest; + dest = proj; + glm_persp_move_far_rh_zo(dest.raw, deltaFar); + return dest; +} + +/*! + * @brief set up perspective projection matrix with default near/far + * and angle values with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] aspect aspect ratio ( width / height ) + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_perspective_default_rh_zo(float aspect) { + mat4s dest; + glm_perspective_default_rh_zo(aspect, dest.raw); + return dest; +} + +/*! + * @brief resize perspective matrix by aspect ratio ( width / height ) + * this makes very easy to resize proj matrix when window /viewport + * reized with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * NOTE: if you dodn't want to create new matrix then use array api on struct.raw + * like glm_perspective_resize_rh_zo(proj.raw, aspect) to avoid create new mat4 + * each time + * + * @param[in, out] proj perspective projection matrix + * @param[in] aspect aspect ratio ( width / height ) + */ +CGLM_INLINE +mat4s +glms_perspective_resize_rh_zo(mat4s proj, float aspect) { + mat4s dest; + dest = proj; + glm_perspective_resize_rh_zo(aspect, dest.raw); + return dest; +} + +/*! + * @brief decomposes frustum values of perspective projection. + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + * @param[out] top top + * @param[out] bottom bottom + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glms_persp_decomp_rh_zo(mat4s proj, + float * __restrict nearZ, float * __restrict farZ, + float * __restrict top, float * __restrict bottom, + float * __restrict left, float * __restrict right) { + glm_persp_decomp_rh_zo(proj.raw, nearZ, farZ, top, bottom, left, right); +} + +/*! + * @brief decomposes frustum values of perspective projection. + * this makes easy to get all values at once + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] dest array + */ +CGLM_INLINE +void +glms_persp_decompv_rh_zo(mat4s proj, float dest[6]) { + glm_persp_decompv_rh_zo(proj.raw, dest); +} + +/*! + * @brief decomposes left and right values of perspective projection + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * x stands for x axis (left / right axis) + * + * @param[in] proj perspective projection matrix + * @param[out] left left + * @param[out] right right + */ +CGLM_INLINE +void +glms_persp_decomp_x_rh_zo(mat4s proj, + float * __restrict left, + float * __restrict right) { + glm_persp_decomp_x_rh_zo(proj.raw, left, right); +} + +/*! + * @brief decomposes top and bottom values of perspective projection + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * y stands for y axis (top / bottom axis) + * + * @param[in] proj perspective projection matrix + * @param[out] top top + * @param[out] bottom bottom + */ +CGLM_INLINE +void +glms_persp_decomp_y_rh_zo(mat4s proj, + float * __restrict top, + float * __restrict bottom) { + glm_persp_decomp_y_rh_zo(proj.raw, top, bottom); +} + +/*! + * @brief decomposes near and far values of perspective projection + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * z stands for z axis (near / far axis) + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + * @param[out] farZ far + */ +CGLM_INLINE +void +glms_persp_decomp_z_rh_zo(mat4s proj, + float * __restrict nearZ, + float * __restrict farZ) { + glm_persp_decomp_z_rh_zo(proj.raw, nearZ, farZ); +} + +/*! + * @brief decomposes far value of perspective projection + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] farZ far + */ +CGLM_INLINE +void +glms_persp_decomp_far_rh_zo(mat4s proj, float * __restrict farZ) { + glm_persp_decomp_far_rh_zo(proj.raw, farZ); +} + +/*! + * @brief decomposes near value of perspective projection + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[out] nearZ near + */ +CGLM_INLINE +void +glms_persp_decomp_near_rh_zo(mat4s proj, float * __restrict nearZ) { + glm_persp_decomp_near_rh_zo(proj.raw, nearZ); +} + +/*! + * @brief returns field of view angle along the Y-axis (in radians) + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * if you need to degrees, use glm_deg to convert it or use this: + * fovy_deg = glm_deg(glm_persp_fovy(projMatrix)) + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glms_persp_fovy_rh_zo(mat4s proj) { + return glm_persp_fovy_rh_zo(proj.raw); +} + +/*! + * @brief returns aspect ratio of perspective projection + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + */ +CGLM_INLINE +float +glms_persp_aspect_rh_zo(mat4s proj) { + return glm_persp_aspect_rh_zo(proj.raw); +} + +/*! + * @brief returns sizes of near and far planes of perspective projection + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * @param[in] proj perspective projection matrix + * @param[in] fovy fovy (see brief) + * @returns sizes as vector, sizes order: [Wnear, Hnear, Wfar, Hfar] + */ +CGLM_INLINE +vec4s +glms_persp_sizes_rh_zo(mat4s proj, float fovy) { + vec4s dest; + glm_persp_sizes_rh_zo(proj.raw, fovy, dest.raw); + return dest; +} + +#endif /* cglms_persp_rh_zo_h */ diff --git a/external/cglm/struct/clipspace/project_no.h b/external/cglm/struct/clipspace/project_no.h new file mode 100644 index 0000000..1a28d47 --- /dev/null +++ b/external/cglm/struct/clipspace/project_no.h @@ -0,0 +1,98 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE vec3s glms_unprojecti_no(vec3s pos, mat4s invMat, vec4s vp) + CGLM_INLINE vec3s glms_project_no(vec3s pos, mat4s m, vec4s vp) + CGLM_INLINE float glms_project_z_no(vec3s v, mat4s m) + */ + +#ifndef cglms_project_no_h +#define cglms_project_no_h + +#include "../../common.h" +#include "../../types-struct.h" +#include "../../plane.h" +#include "../../cam.h" +#include "../../clipspace/project_no.h" + +/*! + * @brief maps the specified viewport coordinates into specified space [1] + * the matrix should contain projection matrix. + * + * if you don't have ( and don't want to have ) an inverse matrix then use + * glm_unproject version. You may use existing inverse of matrix in somewhere + * else, this is why glm_unprojecti exists to save save inversion cost + * + * [1] space: + * 1- if m = invProj: View Space + * 2- if m = invViewProj: World Space + * 3- if m = invMVP: Object Space + * + * You probably want to map the coordinates into object space + * so use invMVP as m + * + * Computing viewProj: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * glm_mat4_inv(viewProj, invMVP); + * + * @param[in] pos point/position in viewport coordinates + * @param[in] invMat matrix (see brief) + * @param[in] vp viewport as [x, y, width, height] + * + * @returns unprojected coordinates + */ +CGLM_INLINE +vec3s +glms_unprojecti_no(vec3s pos, mat4s invMat, vec4s vp) { + vec3s dest; + glm_unprojecti_no(pos.raw, invMat.raw, vp.raw, dest.raw); + return dest; +} + +/*! + * @brief map object coordinates to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] pos object coordinates + * @param[in] m MVP matrix + * @param[in] vp viewport as [x, y, width, height] + * + * @returns projected coordinates + */ +CGLM_INLINE +vec3s +glms_project_no(vec3s pos, mat4s m, vec4s vp) { + vec3s dest; + glm_project_no(pos.raw, m.raw, vp.raw, dest.raw); + return dest; +} + +/*! + * @brief map object's z coordinate to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] v object coordinates + * @param[in] m MVP matrix + * + * @returns projected z coordinate + */ +CGLM_INLINE +float +glms_project_z_no(vec3s v, mat4s m) { + return glm_project_z_no(v.raw, m.raw); +} + +#endif /* cglms_project_rh_no_h */ diff --git a/external/cglm/struct/clipspace/project_zo.h b/external/cglm/struct/clipspace/project_zo.h new file mode 100644 index 0000000..13065f1 --- /dev/null +++ b/external/cglm/struct/clipspace/project_zo.h @@ -0,0 +1,98 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE vec3s glms_unprojecti_no(vec3s pos, mat4s invMat, vec4s vp) + CGLM_INLINE vec3s glms_project_no(vec3s pos, mat4s m, vec4s vp) + CGLM_INLINE float glms_project_z_zo(vec3s v, mat4s m) + */ + +#ifndef cglms_project_zo_h +#define cglms_project_zo_h + +#include "../../common.h" +#include "../../types-struct.h" +#include "../../plane.h" +#include "../../cam.h" +#include "../../clipspace/project_zo.h" + +/*! + * @brief maps the specified viewport coordinates into specified space [1] + * the matrix should contain projection matrix. + * + * if you don't have ( and don't want to have ) an inverse matrix then use + * glm_unproject version. You may use existing inverse of matrix in somewhere + * else, this is why glm_unprojecti exists to save save inversion cost + * + * [1] space: + * 1- if m = invProj: View Space + * 2- if m = invViewProj: World Space + * 3- if m = invMVP: Object Space + * + * You probably want to map the coordinates into object space + * so use invMVP as m + * + * Computing viewProj: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * glm_mat4_inv(viewProj, invMVP); + * + * @param[in] pos point/position in viewport coordinates + * @param[in] invMat matrix (see brief) + * @param[in] vp viewport as [x, y, width, height] + * + * @returns unprojected coordinates + */ +CGLM_INLINE +vec3s +glms_unprojecti_zo(vec3s pos, mat4s invMat, vec4s vp) { + vec3s dest; + glm_unprojecti_zo(pos.raw, invMat.raw, vp.raw, dest.raw); + return dest; +} + +/*! + * @brief map object coordinates to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] pos object coordinates + * @param[in] m MVP matrix + * @param[in] vp viewport as [x, y, width, height] + * + * @returns projected coordinates + */ +CGLM_INLINE +vec3s +glms_project_zo(vec3s pos, mat4s m, vec4s vp) { + vec3s dest; + glm_project_zo(pos.raw, m.raw, vp.raw, dest.raw); + return dest; +} + +/*! + * @brief map object's z coordinate to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * @param[in] v object coordinates + * @param[in] m MVP matrix + * + * @returns projected z coordinate + */ +CGLM_INLINE +float +glms_project_z_zo(vec3s v, mat4s m) { + return glm_project_z_zo(v.raw, m.raw); +} + +#endif /* cglm_project_zo_h */ diff --git a/external/cglm/struct/clipspace/view_lh_no.h b/external/cglm/struct/clipspace/view_lh_no.h new file mode 100644 index 0000000..e4ca5ba --- /dev/null +++ b/external/cglm/struct/clipspace/view_lh_no.h @@ -0,0 +1,89 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_lookat_lh_no(vec3s eye, vec3s center, vec3s up) + CGLM_INLINE mat4s glms_look_lh_no(vec3s eye, vec3s dir, vec3s up) + CGLM_INLINE mat4s glms_look_anyup_lh_no(vec3s eye, vec3s dir) + */ + +#ifndef cglms_view_lh_no_h +#define cglms_view_lh_no_h + +#include "../../common.h" +#include "../../types-struct.h" +#include "../../plane.h" +#include "../../cam.h" +#include "../../clipspace/view_lh_no.h" + +/*! + * @brief set up view matrix + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] center center vector + * @param[in] up up vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_lookat_lh_no(vec3s eye, vec3s center, vec3s up) { + mat4s dest; + glm_lookat_lh_no(eye.raw, center.raw, up.raw, dest.raw); + return dest; +} + +/*! + * @brief set up view matrix + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * convenient wrapper for lookat: if you only have direction not target self + * then this might be useful. Because you need to get target from direction. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[in] up up vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_look_lh_no(vec3s eye, vec3s dir, vec3s up) { + mat4s dest; + glm_look_lh_no(eye.raw, dir.raw, up.raw, dest.raw); + return dest; +} + +/*! + * @brief set up view matrix + * with a left-hand coordinate system and a + * clip-space of [-1, 1]. + * + * convenient wrapper for look: if you only have direction and if you don't + * care what UP vector is then this might be useful to create view matrix + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_look_anyup_lh_no(vec3s eye, vec3s dir) { + mat4s dest; + glm_look_anyup_lh_no(eye.raw, dir.raw, dest.raw); + return dest; +} + +#endif /* cglms_view_lh_no_h */ diff --git a/external/cglm/struct/clipspace/view_lh_zo.h b/external/cglm/struct/clipspace/view_lh_zo.h new file mode 100644 index 0000000..ac1ada9 --- /dev/null +++ b/external/cglm/struct/clipspace/view_lh_zo.h @@ -0,0 +1,89 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_lookat_lh_zo(vec3s eye, vec3s center, vec3s up) + CGLM_INLINE mat4s glms_look_lh_zo(vec3s eye, vec3s dir, vec3s up) + CGLM_INLINE mat4s glms_look_anyup_lh_zo(vec3s eye, vec3s dir) + */ + +#ifndef cglms_view_lh_zo_h +#define cglms_view_lh_zo_h + +#include "../../common.h" +#include "../../types-struct.h" +#include "../../plane.h" +#include "../../cam.h" +#include "../../clipspace/view_lh_zo.h" + +/*! + * @brief set up view matrix + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] center center vector + * @param[in] up up vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_lookat_lh_zo(vec3s eye, vec3s center, vec3s up) { + mat4s dest; + glm_lookat_lh_zo(eye.raw, center.raw, up.raw, dest.raw); + return dest; +} + +/*! + * @brief set up view matrix + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * convenient wrapper for lookat: if you only have direction not target self + * then this might be useful. Because you need to get target from direction. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[in] up up vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_look_lh_zo(vec3s eye, vec3s dir, vec3s up) { + mat4s dest; + glm_look_lh_zo(eye.raw, dir.raw, up.raw, dest.raw); + return dest; +} + +/*! + * @brief set up view matrix + * with a left-hand coordinate system and a + * clip-space of [0, 1]. + * + * convenient wrapper for look: if you only have direction and if you don't + * care what UP vector is then this might be useful to create view matrix + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_look_anyup_lh_zo(vec3s eye, vec3s dir) { + mat4s dest; + glm_look_anyup_lh_zo(eye.raw, dir.raw, dest.raw); + return dest; +} + +#endif /* cglms_view_lh_zo_h */ diff --git a/external/cglm/struct/clipspace/view_rh_no.h b/external/cglm/struct/clipspace/view_rh_no.h new file mode 100644 index 0000000..99b03c3 --- /dev/null +++ b/external/cglm/struct/clipspace/view_rh_no.h @@ -0,0 +1,89 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_lookat_rh_no(vec3s eye, vec3s center, vec3s up) + CGLM_INLINE mat4s glms_look_rh_no(vec3s eye, vec3s dir, vec3s up) + CGLM_INLINE mat4s glms_look_anyup_rh_no(vec3s eye, vec3s dir) + */ + +#ifndef cglms_view_rh_no_h +#define cglms_view_rh_no_h + +#include "../../common.h" +#include "../../types-struct.h" +#include "../../plane.h" +#include "../../cam.h" +#include "../../clipspace/view_rh_no.h" + +/*! + * @brief set up view matrix + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] center center vector + * @param[in] up up vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_lookat_rh_no(vec3s eye, vec3s center, vec3s up) { + mat4s dest; + glm_lookat_rh_no(eye.raw, center.raw, up.raw, dest.raw); + return dest; +} + +/*! + * @brief set up view matrix + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * convenient wrapper for lookat: if you only have direction not target self + * then this might be useful. Because you need to get target from direction. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[in] up up vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_look_rh_no(vec3s eye, vec3s dir, vec3s up) { + mat4s dest; + glm_look_rh_no(eye.raw, dir.raw, up.raw, dest.raw); + return dest; +} + +/*! + * @brief set up view matrix + * with a right-hand coordinate system and a + * clip-space of [-1, 1]. + * + * convenient wrapper for look: if you only have direction and if you don't + * care what UP vector is then this might be useful to create view matrix + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_look_anyup_rh_no(vec3s eye, vec3s dir) { + mat4s dest; + glm_look_anyup_rh_no(eye.raw, dir.raw, dest.raw); + return dest; +} + +#endif /* cglms_view_rh_no_h */ diff --git a/external/cglm/struct/clipspace/view_rh_zo.h b/external/cglm/struct/clipspace/view_rh_zo.h new file mode 100644 index 0000000..14ffe32 --- /dev/null +++ b/external/cglm/struct/clipspace/view_rh_zo.h @@ -0,0 +1,89 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE mat4s glms_lookat_rh_zo(vec3s eye, vec3s center, vec3s up) + CGLM_INLINE mat4s glms_look_rh_zo(vec3s eye, vec3s dir, vec3s up) + CGLM_INLINE mat4s glms_look_anyup_rh_zo(vec3s eye, vec3s dir) + */ + +#ifndef cglms_view_rh_zo_h +#define cglms_view_rh_zo_h + +#include "../../common.h" +#include "../../types-struct.h" +#include "../../plane.h" +#include "../../cam.h" +#include "../../clipspace/view_rh_zo.h" + +/*! + * @brief set up view matrix + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] center center vector + * @param[in] up up vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_lookat_rh_zo(vec3s eye, vec3s center, vec3s up) { + mat4s dest; + glm_lookat_rh_zo(eye.raw, center.raw, up.raw, dest.raw); + return dest; +} + +/*! + * @brief set up view matrix + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * convenient wrapper for lookat: if you only have direction not target self + * then this might be useful. Because you need to get target from direction. + * + * NOTE: The UP vector must not be parallel to the line of sight from + * the eye point to the reference point + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @param[in] up up vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_look_rh_zo(vec3s eye, vec3s dir, vec3s up) { + mat4s dest; + glm_look_rh_zo(eye.raw, dir.raw, up.raw, dest.raw); + return dest; +} + +/*! + * @brief set up view matrix + * with a right-hand coordinate system and a + * clip-space of [0, 1]. + * + * convenient wrapper for look: if you only have direction and if you don't + * care what UP vector is then this might be useful to create view matrix + * + * @param[in] eye eye vector + * @param[in] dir direction vector + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_look_anyup_rh_zo(vec3s eye, vec3s dir) { + mat4s dest; + glm_look_anyup_rh_zo(eye.raw, dir.raw, dest.raw); + return dest; +} + +#endif /* cglms_view_rh_zo_h */ diff --git a/external/cglm/struct/color.h b/external/cglm/struct/color.h new file mode 100644 index 0000000..3ce78da --- /dev/null +++ b/external/cglm/struct/color.h @@ -0,0 +1,27 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglms_colors_h +#define cglms_colors_h + +#include "../common.h" +#include "../types-struct.h" +#include "../color.h" +#include "vec3.h" + +/*! + * @brief averages the color channels into one value + * + * @param[in] rgb RGB color + */ +CGLM_INLINE +float +glms_luminance(vec3s rgb) { + return glm_luminance(rgb.raw); +} + +#endif /* cglms_colors_h */ diff --git a/external/cglm/struct/curve.h b/external/cglm/struct/curve.h new file mode 100644 index 0000000..53ea359 --- /dev/null +++ b/external/cglm/struct/curve.h @@ -0,0 +1,40 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglms_curves_h +#define cglms_curves_h + +#include "../common.h" +#include "../types-struct.h" +#include "../curve.h" +#include "vec4.h" +#include "mat4.h" + +/*! + * @brief helper function to calculate S*M*C multiplication for curves + * + * This function does not encourage you to use SMC, + * instead it is a helper if you use SMC. + * + * if you want to specify S as vector then use more generic glm_mat4_rmc() func. + * + * Example usage: + * B(s) = glm_smc(s, GLM_BEZIER_MAT, (vec4){p0, c0, c1, p1}) + * + * @param[in] s parameter between 0 and 1 (this will be [s3, s2, s, 1]) + * @param[in] m basis matrix + * @param[in] c position/control vector + * + * @return B(s) + */ +CGLM_INLINE +float +glms_smc(float s, mat4s m, vec4s c) { + return glm_smc(s, m.raw, c.raw); +} + +#endif /* cglms_curves_h */ diff --git a/external/cglm/struct/euler.h b/external/cglm/struct/euler.h new file mode 100644 index 0000000..19697f7 --- /dev/null +++ b/external/cglm/struct/euler.h @@ -0,0 +1,249 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + NOTE: + angles must be passed as [X-Angle, Y-Angle, Z-angle] order + For instance you don't pass angles as [Z-Angle, X-Angle, Y-angle] to + glm_euler_zxy function, All RELATED functions accept angles same order + which is [X, Y, Z]. + */ + +/* + Types: + enum glm_euler_seq + + Functions: + CGLM_INLINE vec3s glms_euler_angles(mat4s m) + CGLM_INLINE mat4s glms_euler_xyz(vec3s angles) + CGLM_INLINE mat4s glms_euler_xzy(vec3s angles) + CGLM_INLINE mat4s glms_euler_yxz(vec3s angles) + CGLM_INLINE mat4s glms_euler_yzx(vec3s angles) + CGLM_INLINE mat4s glms_euler_zxy(vec3s angles) + CGLM_INLINE mat4s glms_euler_zyx(vec3s angles) + CGLM_INLINE mat4s glms_euler_by_order(vec3s angles, glm_euler_seq ord) + CGLM_INLINE versors glms_euler_xyz_quat(vec3s angles) + CGLM_INLINE versors glms_euler_xzy_quat(vec3s angles) + CGLM_INLINE versors glms_euler_yxz_quat(vec3s angles) + CGLM_INLINE versors glms_euler_yzx_quat(vec3s angles) + CGLM_INLINE versors glms_euler_zxy_quat(vec3s angles) + CGLM_INLINE versors glms_euler_zyx_quat(vec3s angles) + */ + +#ifndef cglms_euler_h +#define cglms_euler_h + +#include "../common.h" +#include "../types-struct.h" +#include "../euler.h" + +/*! + * @brief extract euler angles (in radians) using xyz order + * + * @param[in] m affine transform + * @returns angles vector [x, y, z] + */ +CGLM_INLINE +vec3s +glms_euler_angles(mat4s m) { + vec3s dest; + glm_euler_angles(m.raw, dest.raw); + return dest; +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @returns rotation matrix + */ +CGLM_INLINE +mat4s +glms_euler_xyz(vec3s angles) { + mat4s dest; + glm_euler_xyz(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @returns rotation matrix + */ +CGLM_INLINE +mat4s +glms_euler_xzy(vec3s angles) { + mat4s dest; + glm_euler_xzy(angles.raw, dest.raw); + return dest; +} + + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @returns rotation matrix + */ +CGLM_INLINE +mat4s +glms_euler_yxz(vec3s angles) { + mat4s dest; + glm_euler_yxz(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @returns rotation matrix + */ +CGLM_INLINE +mat4s +glms_euler_yzx(vec3s angles) { + mat4s dest; + glm_euler_yzx(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @returns rotation matrix + */ +CGLM_INLINE +mat4s +glms_euler_zxy(vec3s angles) { + mat4s dest; + glm_euler_zxy(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @returns rotation matrix + */ +CGLM_INLINE +mat4s +glms_euler_zyx(vec3s angles) { + mat4s dest; + glm_euler_zyx(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Xangle, Yangle, Zangle] + * @param[in] ord euler order + * @returns rotation matrix + */ +CGLM_INLINE +mat4s +glms_euler_by_order(vec3s angles, glm_euler_seq ord) { + mat4s dest; + glm_euler_by_order(angles.raw, ord, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x y z order (roll pitch yaw) + * + * @param[in] angles angles x y z (radians) + * @returns quaternion + */ +CGLM_INLINE +versors +glms_euler_xyz_quat(vec3s angles) { + versors dest; + glm_euler_xyz_quat(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x z y order (roll yaw pitch) + * + * @param[in] angles angles x y z (radians) + * @returns quaternion + */ +CGLM_INLINE +versors +glms_euler_xzy_quat(vec3s angles) { + versors dest; + glm_euler_xzy_quat(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y x z order (pitch roll yaw) + * + * @param[in] angles angles x y z (radians) + * @returns quaternion + */ +CGLM_INLINE +versors +glms_euler_yxz_quat(vec3s angles) { + versors dest; + glm_euler_yxz_quat(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y z x order (pitch yaw roll) + * + * @param[in] angles angles x y z (radians) + * @returns quaternion + */ +CGLM_INLINE +versors +glms_euler_yzx_quat(vec3s angles) { + versors dest; + glm_euler_yzx_quat(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z x y order (yaw roll pitch) + * + * @param[in] angles angles x y z (radians) + * @returns quaternion + */ +CGLM_INLINE +versors +glms_euler_zxy_quat(vec3s angles) { + versors dest; + glm_euler_zxy_quat(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z y x order (yaw pitch roll) + * + * @param[in] angles angles x y z (radians) + * @returns quaternion + */ +CGLM_INLINE +versors +glms_euler_zyx_quat(vec3s angles) { + versors dest; + glm_euler_zyx_quat(angles.raw, dest.raw); + return dest; +} + + +#endif /* cglms_euler_h */ diff --git a/external/cglm/struct/frustum.h b/external/cglm/struct/frustum.h new file mode 100644 index 0000000..81b5b7b --- /dev/null +++ b/external/cglm/struct/frustum.h @@ -0,0 +1,155 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglms_frustums_h +#define cglms_frustums_h + +#include "../common.h" +#include "../types-struct.h" +#include "../frustum.h" +#include "plane.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" + +/* you can override clip space coords + but you have to provide all with same name + e.g.: define GLM_CSCOORD_LBN {0.0f, 0.0f, 1.0f, 1.0f} */ +#ifndef GLM_CUSTOM_CLIPSPACE + +/* near */ +#define GLMS_CSCOORD_LBN {-1.0f, -1.0f, -1.0f, 1.0f} +#define GLMS_CSCOORD_LTN {-1.0f, 1.0f, -1.0f, 1.0f} +#define GLMS_CSCOORD_RTN { 1.0f, 1.0f, -1.0f, 1.0f} +#define GLMS_CSCOORD_RBN { 1.0f, -1.0f, -1.0f, 1.0f} + +/* far */ +#define GLMS_CSCOORD_LBF {-1.0f, -1.0f, 1.0f, 1.0f} +#define GLMS_CSCOORD_LTF {-1.0f, 1.0f, 1.0f, 1.0f} +#define GLMS_CSCOORD_RTF { 1.0f, 1.0f, 1.0f, 1.0f} +#define GLMS_CSCOORD_RBF { 1.0f, -1.0f, 1.0f, 1.0f} + +#endif + +/*! + * @brief extracts view frustum planes + * + * planes' space: + * 1- if m = proj: View Space + * 2- if m = viewProj: World Space + * 3- if m = MVP: Object Space + * + * You probably want to extract planes in world space so use viewProj as m + * Computing viewProj: + * glm_mat4_mul(proj, view, viewProj); + * + * Exracted planes order: [left, right, bottom, top, near, far] + * + * @param[in] m matrix (see brief) + * @param[out] dest extracted view frustum planes (see brief) + */ +CGLM_INLINE +void +glms_frustum_planes(mat4s m, vec4s dest[6]) { + vec4 rawDest[6]; + glm_frustum_planes(m.raw, rawDest); + glms_vec4_(pack)(dest, rawDest, 6); +} + +/*! + * @brief extracts view frustum corners using clip-space coordinates + * + * corners' space: + * 1- if m = invViewProj: World Space + * 2- if m = invMVP: Object Space + * + * You probably want to extract corners in world space so use invViewProj + * Computing invViewProj: + * glm_mat4_mul(proj, view, viewProj); + * ... + * glm_mat4_inv(viewProj, invViewProj); + * + * if you have a near coord at i index, you can get it's far coord by i + 4 + * + * Find center coordinates: + * for (j = 0; j < 4; j++) { + * glm_vec3_center(corners[i], corners[i + 4], centerCorners[i]); + * } + * + * @param[in] invMat matrix (see brief) + * @param[out] dest exracted view frustum corners (see brief) + */ +CGLM_INLINE +void +glms_frustum_corners(mat4s invMat, vec4s dest[8]) { + vec4 rawDest[8]; + glm_frustum_corners(invMat.raw, rawDest); + glms_vec4_(pack)(dest, rawDest, 8); +} + +/*! + * @brief finds center of view frustum + * + * @param[in] corners view frustum corners + * @returns view frustum center + */ +CGLM_INLINE +vec4s +glms_frustum_center(vec4s corners[8]) { + vec4 rawCorners[8]; + vec4s r; + + glms_vec4_(unpack)(rawCorners, corners, 8); + glm_frustum_center(rawCorners, r.raw); + return r; +} + +/*! + * @brief finds bounding box of frustum relative to given matrix e.g. view mat + * + * @param[in] corners view frustum corners + * @param[in] m matrix to convert existing conners + * @param[out] box bounding box as array [min, max] + */ +CGLM_INLINE +void +glms_frustum_box(vec4s corners[8], mat4s m, vec3s box[2]) { + vec4 rawCorners[8]; + vec3 rawBox[2]; + + glms_vec4_(unpack)(rawCorners, corners, 8); + glm_frustum_box(rawCorners, m.raw, rawBox); + glms_vec3_(pack)(box, rawBox, 2); +} + +/*! + * @brief finds planes corners which is between near and far planes (parallel) + * + * this will be helpful if you want to split a frustum e.g. CSM/PSSM. This will + * find planes' corners but you will need to one more plane. + * Actually you have it, it is near, far or created previously with this func ;) + * + * @param[in] corners view frustum corners + * @param[in] splitDist split distance + * @param[in] farDist far distance (zFar) + * @param[out] planeCorners plane corners [LB, LT, RT, RB] + */ +CGLM_INLINE +void +glms_frustum_corners_at(vec4s corners[8], + float splitDist, + float farDist, + vec4s planeCorners[4]) { + vec4 rawCorners[8]; + vec4 rawPlaneCorners[4]; + + glms_vec4_(unpack)(rawCorners, corners, 8); + glm_frustum_corners_at(rawCorners, splitDist, farDist, rawPlaneCorners); + glms_vec4_(pack)(planeCorners, rawPlaneCorners, 8); +} + +#endif /* cglms_frustums_h */ diff --git a/external/cglm/struct/handed/euler_to_quat_lh.h b/external/cglm/struct/handed/euler_to_quat_lh.h new file mode 100644 index 0000000..3964e51 --- /dev/null +++ b/external/cglm/struct/handed/euler_to_quat_lh.h @@ -0,0 +1,115 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glms_euler_xyz_quat_lh(vec3 angles, versor dest); + CGLM_INLINE void glms_euler_xzy_quat_lh(vec3 angles, versor dest); + CGLM_INLINE void glms_euler_yxz_quat_lh(vec3 angles, versor dest); + CGLM_INLINE void glms_euler_yzx_quat_lh(vec3 angles, versor dest); + CGLM_INLINE void glms_euler_zxy_quat_lh(vec3 angles, versor dest); + CGLM_INLINE void glms_euler_zyx_quat_lh(vec3 angles, versor dest); + */ + +#ifndef cglms_euler_to_quat_lh_h +#define cglms_euler_to_quat_lh_h + +#include "../common.h" + + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x y z order in left hand (roll pitch yaw) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +versors +glms_euler_xyz_quat_lh(vec3s angles) { + versors dest; + glm_euler_xyz_quat_lh(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x z y order in left hand (roll yaw pitch) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +versors +glms_euler_xzy_quat_lh(vec3s angles) { + versors dest; + glm_euler_xzy_quat_lh(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y x z order in left hand (pitch roll yaw) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +versors +glms_euler_yxz_quat_lh(vec3s angles) { + versors dest; + glm_euler_yxz_quat_lh(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y z x order in left hand (pitch yaw roll) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +versors +glms_euler_yzx_quat_lh(vec3s angles) { + versors dest; + glm_euler_yzx_quat_lh(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z x y order in left hand (yaw roll pitch) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +versors +glms_euler_zxy_quat_lh(vec3s angles) { + versors dest; + glm_euler_zxy_quat_lh(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z y x order in left hand (yaw pitch roll) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +versors +glms_euler_zyx_quat_lh(vec3s angles) { + versors dest; + glm_euler_zyx_quat_lh(angles.raw, dest.raw); + return dest; +} + + +#endif /* cglms_euler_to_quat_lh_h */ diff --git a/external/cglm/struct/handed/euler_to_quat_rh.h b/external/cglm/struct/handed/euler_to_quat_rh.h new file mode 100644 index 0000000..6c7f400 --- /dev/null +++ b/external/cglm/struct/handed/euler_to_quat_rh.h @@ -0,0 +1,115 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glms_euler_xyz_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glms_euler_xzy_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glms_euler_yxz_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glms_euler_yzx_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glms_euler_zxy_quat_rh(vec3 angles, versor dest); + CGLM_INLINE void glms_euler_zyx_quat_rh(vec3 angles, versor dest); + */ + +#ifndef cglms_euler_to_quat_rh_h +#define cglms_euler_to_quat_rh_h + +#include "../common.h" + + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x y z order in right hand (roll pitch yaw) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +versors +glms_euler_xyz_quat_rh(vec3s angles) { + versors dest; + glm_euler_xyz_quat_rh(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in x z y order in right hand (roll yaw pitch) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +versors +glms_euler_xzy_quat_rh(vec3s angles) { + versors dest; + glm_euler_xzy_quat_rh(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y x z order in right hand (pitch roll yaw) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +versors +glms_euler_yxz_quat_rh(vec3s angles) { + versors dest; + glm_euler_yxz_quat_rh(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in y z x order in right hand (pitch yaw roll) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +versors +glms_euler_yzx_quat_rh(vec3s angles) { + versors dest; + glm_euler_yzx_quat_rh(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z x y order in right hand (yaw roll pitch) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +versors +glms_euler_zxy_quat_rh(vec3s angles) { + versors dest; + glm_euler_zxy_quat_rh(angles.raw, dest.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion using rotation angles and does + * rotations in z y x order in right hand (yaw pitch roll) + * + * @param[in] angles angles x y z (radians) + * @param[out] dest quaternion + */ +CGLM_INLINE +versors +glms_euler_zyx_quat_rh(vec3s angles) { + versors dest; + glm_euler_zyx_quat_rh(angles.raw, dest.raw); + return dest; +} + + +#endif /* cglms_euler_to_quat_rh_h */ diff --git a/external/cglm/struct/io.h b/external/cglm/struct/io.h new file mode 100644 index 0000000..900c2a8 --- /dev/null +++ b/external/cglm/struct/io.h @@ -0,0 +1,107 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glms_mat4_print(mat4s matrix, FILE *ostream); + CGLM_INLINE void glms_mat3_print(mat3s matrix, FILE *ostream); + CGLM_INLINE void glms_vec4_print(vec4s vec, FILE *ostream); + CGLM_INLINE void glms_ivec4_print(ivec3s vec, FILE *ostream); + CGLM_INLINE void glms_vec3_print(vec3s vec, FILE *ostream); + CGLM_INLINE void glms_ivec3_print(ivec3s vec, FILE *ostream); + CGLM_INLINE void glms_vec2_print(vec2s vec, FILE *ostream); + CGLM_INLINE void glms_ivec2_print(ivec3s vec, FILE *ostream); + CGLM_INLINE void glms_versor_print(versor vec, FILE *ostream); + CGLM_INLINE void glms_aabb_print(vec3s bbox[2], const char *tag, FILE *ostream); + */ + +#ifndef cglms_ios_h +#define cglms_ios_h + +#include "../common.h" +#include "../io.h" +#include "mat4.h" + +#include +#include + +CGLM_INLINE +void +glms_mat4_print(mat4s matrix, + FILE * __restrict ostream) { + + glm_mat4_print(matrix.raw, ostream); +} + +CGLM_INLINE +void +glms_mat3_print(mat3s matrix, + FILE * __restrict ostream) { + glm_mat3_print(matrix.raw, ostream); +} + +CGLM_INLINE +void +glms_vec4_print(vec4s vec, + FILE * __restrict ostream) { + glm_vec4_print(vec.raw, ostream); +} + +CGLM_INLINE +void +glms_ivec4_print(ivec4s vec, + FILE * __restrict ostream) { + glm_ivec4_print(vec.raw, ostream); +} + +CGLM_INLINE +void +glms_vec3_print(vec3s vec, + FILE * __restrict ostream) { + glm_vec3_print(vec.raw, ostream); +} + +CGLM_INLINE +void +glms_ivec3_print(ivec3s vec, + FILE * __restrict ostream) { + glm_ivec3_print(vec.raw, ostream); +} + +CGLM_INLINE +void +glms_vec2_print(vec2s vec, + FILE * __restrict ostream) { + glm_vec2_print(vec.raw, ostream); +} + +CGLM_INLINE +void +glms_ivec2_print(ivec2s vec, + FILE * __restrict ostream) { + glm_ivec2_print(vec.raw, ostream); +} + +CGLM_INLINE +void +glms_versor_print(versors vec, + FILE * __restrict ostream) { + glm_versor_print(vec.raw, ostream); +} + +CGLM_INLINE +void +glms_aabb_print(vec3s bbox[2], + const char * __restrict tag, + FILE * __restrict ostream) { + vec3 rawBbox[2]; + + glms_vec3_(unpack)(rawBbox, bbox, 2); + glm_aabb_print(rawBbox, tag, ostream); +} + +#endif /* cglms_ios_h */ diff --git a/external/cglm/struct/ivec2.h b/external/cglm/struct/ivec2.h new file mode 100644 index 0000000..d53c9f6 --- /dev/null +++ b/external/cglm/struct/ivec2.h @@ -0,0 +1,708 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_IVEC2_ONE_INIT + GLMS_IVEC2_ZERO_INIT + GLMS_IVEC2_ONE + GLMS_IVEC2_ZERO + + Functions: + CGLM_INLINE ivec2s glms_ivec2(int * __restrict v) + CGLM_INLINE void glms_ivec2_pack(ivec2s dst[], ivec2s src[], size_t len) + CGLM_INLINE void glms_ivec2_unpack(ivec2 dst[], ivec2 src[], size_t len) + CGLM_INLINE ivec2s glms_ivec2_zero(ivec2s v) + CGLM_INLINE ivec2s glms_ivec2_one(ivec2s v) + CGLM_INLINE int glms_ivec2_dot(ivec2s a, ivec2s b) + CGLM_INLINE int glms_ivec2_cross(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_add(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_adds(ivec2s v, int s) + CGLM_INLINE ivec2s glms_ivec2_sub(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_subs(ivec2s v, int s) + CGLM_INLINE ivec2s glms_ivec2_mul(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_scale(ivec2s v, int s) + CGLM_INLINE ivec2s glms_ivec2_div(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_divs(ivec2s v, int s) + CGLM_INLINE ivec2s glms_ivec2_mod(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_addadd(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_addadds(ivec2s a, int s) + CGLM_INLINE ivec2s glms_ivec2_subadd(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_subadds(ivec2s a, int s) + CGLM_INLINE ivec2s glms_ivec2_muladd(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_muladds(ivec2s a, int s) + CGLM_INLINE ivec2s glms_ivec2_maxadd(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_minadd(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_subsub(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_subsubs(ivec2s a, int s) + CGLM_INLINE ivec2s glms_ivec2_addsub(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_addsubs(ivec2s a, int s) + CGLM_INLINE ivec2s glms_ivec2_mulsub(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_mulsubs(ivec2s a, int s) + CGLM_INLINE ivec2s glms_ivec2_maxsub(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_minsub(ivec2s a, ivec2s b) + CGLM_INLINE int glms_ivec2_distance2(ivec2s a, ivec2s b) + CGLM_INLINE float glms_ivec2_distance(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_fill(int val) + CGLM_INLINE bool glms_ivec2_eq(ivec2s v, int val); + CGLM_INLINE bool glms_ivec2_eqv(ivec2s a, ivec2s b); + CGLM_INLINE ivec2s glms_ivec2_maxv(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_minv(ivec2s a, ivec2s b) + CGLM_INLINE ivec2s glms_ivec2_clamp(ivec2s v, int minVal, int maxVal) + CGLM_INLINE ivec2s glms_ivec2_abs(ivec2s v) + */ + +#ifndef cglms_ivec2_h +#define cglms_ivec2_h + +#include "../common.h" +#include "../types-struct.h" +#include "../ivec2.h" + +#define glms_ivec2_(NAME) CGLM_STRUCTAPI(ivec2, NAME) + +#define GLMS_IVEC2_ONE_INIT {GLM_IVEC2_ONE_INIT} +#define GLMS_IVEC2_ZERO_INIT {GLM_IVEC2_ZERO_INIT} + +#define GLMS_IVEC2_ONE ((ivec2s)GLMS_IVEC2_ONE_INIT) +#define GLMS_IVEC2_ZERO ((ivec2s)GLMS_IVEC2_ZERO_INIT) + +/*! + * @brief init ivec2 using ivec3 or ivec4 + * + * @param[in] v vector + * @returns destination + */ +CGLM_INLINE +ivec2s +glms_ivec2(int * __restrict v) { + ivec2s r; + glm_ivec2(v, r.raw); + return r; +} + +/*! + * @brief pack an array of ivec2 into an array of ivec2s + * + * @param[out] dst array of ivec2s + * @param[in] src array of ivec2 + * @param[in] len number of elements + */ +CGLM_INLINE +void +glms_ivec2_(pack)(ivec2s dst[], ivec2 src[], size_t len) { + size_t i; + + for (i = 0; i < len; i++) { + glm_ivec2_copy(src[i], dst[i].raw); + } +} + +/*! + * @brief unpack an array of ivec2s into an array of ivec2 + * + * @param[out] dst array of ivec2 + * @param[in] src array of ivec2s + * @param[in] len number of elements + */ +CGLM_INLINE +void +glms_ivec2_(unpack)(ivec2 dst[], ivec2s src[], size_t len) { + size_t i; + + for (i = 0; i < len; i++) { + glm_ivec2_copy(src[i].raw, dst[i]); + } +} + +/*! + * @brief set all members of [v] to zero + * + * @returns vector + */ +CGLM_INLINE +ivec2s +glms_ivec2_(zero)(void) { + ivec2s r; + glm_ivec2_zero(r.raw); + return r; +} + +/*! + * @brief set all members of [v] to one + * + * @returns vector + */ +CGLM_INLINE +ivec2s +glms_ivec2_(one)(void) { + ivec2s r; + glm_ivec2_one(r.raw); + return r; +} + +/*! + * @brief ivec2 dot product + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return dot product + */ +CGLM_INLINE +int +glms_ivec2_(dot)(ivec2s a, ivec2s b) { + return glm_ivec2_dot(a.raw, b.raw); +} + +/*! + * @brief ivec2 cross product + * + * REF: http://allenchou.net/2013/07/cross-product-of-2d-vectors/ + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return Z component of cross product + */ +CGLM_INLINE +int +glms_ivec2_(cross)(ivec2s a, ivec2s b) { + return glm_ivec2_cross(a.raw, b.raw); +} + +/*! + * @brief add vector [a] to vector [b] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec2s +glms_ivec2_(add)(ivec2s a, ivec2s b) { + ivec2s r; + glm_ivec2_add(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief add scalar s to vector [v] and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination + */ +CGLM_INLINE +ivec2s +glms_ivec2_(adds)(ivec2s v, int s) { + ivec2s r; + glm_ivec2_adds(v.raw, s, r.raw); + return r; +} + +/*! + * @brief subtract vector [b] from vector [a] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec2s +glms_ivec2_(sub)(ivec2s a, ivec2s b) { + ivec2s r; + glm_ivec2_sub(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief subtract scalar s from vector [v] and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination + */ +CGLM_INLINE +ivec2s +glms_ivec2_(subs)(ivec2s v, int s) { + ivec2s r; + glm_ivec2_subs(v.raw, s, r.raw); + return r; +} + +/*! + * @brief multiply vector [a] with vector [b] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec2s +glms_ivec2_(mul)(ivec2s a, ivec2s b) { + ivec2s r; + glm_ivec2_mul(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief multiply vector [a] with scalar s and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination + */ +CGLM_INLINE +ivec2s +glms_ivec2_(scale)(ivec2s v, int s) { + ivec2s r; + glm_ivec2_scale(v.raw, s, r.raw); + return r; +} + +/*! + * @brief div vector with another component-wise division: d = a / b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns result = (a[0]/b[0], a[1]/b[1]) + */ +CGLM_INLINE +ivec2s +glms_ivec2_(div)(ivec2s a, ivec2s b) { + ivec2s r; + glm_ivec2_div(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief div vector with scalar: d = v / s + * + * @param[in] v vector + * @param[in] s scalar + * @returns result = (a[0]/s, a[1]/s) + */ +CGLM_INLINE +ivec2s +glms_ivec2_(divs)(ivec2s v, int s) { + ivec2s r; + glm_ivec2_divs(v.raw, s, r.raw); + return r; +} + +/*! + * @brief mod vector with another component-wise modulo: d = a % b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns result = (a[0]%b[0], a[1]%b[1]) + */ +CGLM_INLINE +ivec2s +glms_ivec2_(mod)(ivec2s a, ivec2s b) { + ivec2s r; + glm_ivec2_mod(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief add vector [a] with vector [b] and add result to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += (a + b) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(addadd)(ivec2s a, ivec2s b, ivec2s dest) { + glm_ivec2_addadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add scalar [s] onto vector [a] and add result to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest += (a + s) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(addadds)(ivec2s a, int s, ivec2s dest) { + glm_ivec2_addadds(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief subtract vector [a] from vector [b] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += (a - b) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(subadd)(ivec2s a, ivec2s b, ivec2s dest) { + glm_ivec2_subadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief subtract scalar [s] from vector [a] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first + * @param[in] s scalar + * @param[in] dest dest += (a - s) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(subadds)(ivec2s a, int s, ivec2s dest) { + glm_ivec2_subadds(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief multiply vector [a] with vector [b] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += (a * b) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(muladd)(ivec2s a, ivec2s b, ivec2s dest) { + glm_ivec2_muladd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief multiply vector [a] with scalar [s] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest += (a * s) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(muladds)(ivec2s a, int s, ivec2s dest) { + glm_ivec2_muladds(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief add maximum of vector [a] and vector [b] to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += max(a, b) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(maxadd)(ivec2s a, ivec2s b, ivec2s dest) { + glm_ivec2_maxadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add minimum of vector [a] and vector [b] to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += min(a, b) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(minadd)(ivec2s a, ivec2s b, ivec2s dest) { + glm_ivec2_minadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief subtract vector [a] from vector [b] and subtract result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest -= (a - b) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(subsub)(ivec2s a, ivec2s b, ivec2s dest) { + glm_ivec2_subsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief subtract scalar [s] from vector [a] and subtract result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest -= (a - s) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(subsubs)(ivec2s a, int s, ivec2s dest) { + glm_ivec2_subsubs(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief add vector [a] to vector [b] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] b scalar + * @param[in] dest dest -= (a + b) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(addsub)(ivec2s a, ivec2s b, ivec2s dest) { + glm_ivec2_addsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add scalar [s] to vector [a] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest -= (a + b) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(addsubs)(ivec2s a, int s, ivec2s dest) { + glm_ivec2_addsubs(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief multiply vector [a] and vector [b] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] b scalar + * @param[in] dest dest -= (a * b) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(mulsub)(ivec2s a, ivec2s b, ivec2s dest) { + glm_ivec2_mulsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief multiply vector [a] with scalar [s] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest -= (a * s) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(mulsubs)(ivec2s a, int s, ivec2s dest) { + glm_ivec2_mulsubs(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief subtract maximum of vector [a] and vector [b] from vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest -= max(a, b) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(maxsub)(ivec2s a, ivec2s b, ivec2s dest) { + glm_ivec2_maxsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief subtract minimum of vector [a] and vector [b] from vector [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest -= min(a, b) + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(minsub)(ivec2s a, ivec2s b, ivec2s dest) { + glm_ivec2_minsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief squared distance between two vectors + * + * @param[in] a first vector + * @param[in] b second vector + * @return returns squared distance (distance * distance) + */ +CGLM_INLINE +int +glms_ivec2_(distance2)(ivec2s a, ivec2s b) { + return glm_ivec2_distance2(a.raw, b.raw); +} + +/*! + * @brief distance between two vectors + * + * @param[in] a first vector + * @param[in] b second vector + * @return returns distance + */ +CGLM_INLINE +float +glms_ivec2_(distance)(ivec2s a, ivec2s b) { + return glm_ivec2_distance(a.raw, b.raw); +} + +/*! + * @brief fill a vector with specified value + * + * @param[in] val value + * @returns dest + */ +CGLM_INLINE +ivec2s +glms_ivec2_(fill)(int val) { + ivec2s r; + glm_ivec2_fill(r.raw, val); + return r; +} + +/*! + * @brief check if vector is equal to value + * + * @param[in] v vector + * @param[in] val value + */ +CGLM_INLINE +bool +glms_ivec2_(eq)(ivec2s v, int val) { + return glm_ivec2_eq(v.raw, val); +} + +/*! + * @brief check if vector is equal to another + * + * @param[in] a vector + * @param[in] b vector + */ +CGLM_INLINE +bool +glms_ivec2_(eqv)(ivec2s a, ivec2s b) { + return glm_ivec2_eqv(a.raw, b.raw); +} + +/*! + * @brief set each member of dest to greater of vector a and b + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec2s +glms_ivec2_(maxv)(ivec2s a, ivec2s b) { + ivec2s r; + glm_ivec2_maxv(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief set each member of dest to lesser of vector a and b + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec2s +glms_ivec2_(minv)(ivec2s a, ivec2s b) { + ivec2s r; + glm_ivec2_minv(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief clamp each member of [v] between minVal and maxVal (inclusive) + * + * @param[in] v vector + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + * @returns clamped vector + */ +CGLM_INLINE +ivec2s +glms_ivec2_(clamp)(ivec2s v, int minVal, int maxVal) { + glm_ivec2_clamp(v.raw, minVal, maxVal); + return v; +} + +/*! + * @brief absolute value of v + * + * @param[in] v vector + * @returns destination + */ +CGLM_INLINE +ivec2s +glms_ivec2_(abs)(ivec2s v) { + ivec2s r; + glm_ivec2_abs(v.raw, r.raw); + return r; +} + +#endif /* cglms_ivec2_h */ diff --git a/external/cglm/struct/ivec3.h b/external/cglm/struct/ivec3.h new file mode 100644 index 0000000..c2c5f3b --- /dev/null +++ b/external/cglm/struct/ivec3.h @@ -0,0 +1,725 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_IVEC3_ONE_INIT + GLMS_IVEC3_ZERO_INIT + GLMS_IVEC3_ONE + GLMS_IVEC3_ZERO + + Functions: + CGLM_INLINE ivec3s glms_ivec3(ivec4s v4) + CGLM_INLINE void glms_ivec3_pack(ivec3s dst[], ivec3 src[], size_t len) + CGLM_INLINE void glms_ivec3_unpack(ivec3 dst[], ivec3s src[], size_t len) + CGLM_INLINE ivec3s glms_ivec3_zero(void) + CGLM_INLINE ivec3s glms_ivec3_one(void) + CGLM_INLINE int glms_ivec3_dot(ivec3s a, ivec3s b) + CGLM_INLINE int glms_ivec3_norm2(ivec3s v) + CGLM_INLINE int glms_ivec3_norm(ivec3s v) + CGLM_INLINE ivec3s glms_ivec3_add(ivec3s a, ivec3s b) + CGLM_INLINE ivec3s glms_ivec3_adds(ivec3s v, int s) + CGLM_INLINE ivec3s glms_ivec3_sub(ivec3s a, ivec3s b) + CGLM_INLINE ivec3s glms_ivec3_subs(ivec3s v, int s) + CGLM_INLINE ivec3s glms_ivec3_mul(ivec3s a, ivec3s b) + CGLM_INLINE ivec3s glms_ivec3_scale(ivec3s v, int s) + CGLM_INLINE ivec3s glms_ivec3_div(ivec3s a, ivec3s b) + CGLM_INLINE ivec3s glms_ivec3_divs(ivec3s v, int s) + CGLM_INLINE ivec3s glms_ivec3_mod(ivec3s a, ivec3s b) + CGLM_INLINE ivec3s glms_ivec3_addadd(ivec3s a, ivec3s b, ivec3s dest) + CGLM_INLINE ivec3s glms_ivec3_addadds(ivec3s a, int s, ivec3s dest) + CGLM_INLINE ivec3s glms_ivec3_subadd(ivec3s a, ivec3s b, ivec3s dest) + CGLM_INLINE ivec3s glms_ivec3_subadds(ivec3s a, int s, ivec3s dest) + CGLM_INLINE ivec3s glms_ivec3_muladd(ivec3s a, ivec3s b, ivec3s dest) + CGLM_INLINE ivec3s glms_ivec3_muladds(ivec3s a, int s, ivec3s dest) + CGLM_INLINE ivec3s glms_ivec3_minadd(ivec3s a, ivec3s b, ivec3s dest) + CGLM_INLINE ivec3s glms_ivec3_subsub(ivec3s a, ivec3s b, ivec3s dest) + CGLM_INLINE ivec3s glms_ivec3_subsubs(ivec3s a, int s, ivec3s dest) + CGLM_INLINE ivec3s glms_ivec3_addsub(ivec3s a, ivec3s b, ivec3s dest) + CGLM_INLINE ivec3s glms_ivec3_addsubs(ivec3s a, int s, ivec3s dest) + CGLM_INLINE ivec3s glms_ivec3_mulsub(ivec3s a, ivec3s b, ivec3s dest) + CGLM_INLINE ivec3s glms_ivec3_mulsubs(ivec3s a, int s, ivec3s dest) + CGLM_INLINE ivec3s glms_ivec3_maxsub(ivec3s a, ivec3s b, ivec3s dest) + CGLM_INLINE ivec3s glms_ivec3_minsub(ivec3s a, ivec3s b, ivec3s dest) + CGLM_INLINE int glms_ivec3_distance2(ivec3s a, ivec3s b) + CGLM_INLINE float glms_ivec3_distance(ivec3s a, ivec3s b) + CGLM_INLINE ivec3s glms_ivec3_fill(int val) + CGLM_INLINE bool glms_ivec3_eq(ivec3s v, int val) + CGLM_INLINE bool glms_ivec3_eqv(ivec3s a, ivec3s b) + CGLM_INLINE ivec3s glms_ivec3_maxv(ivec3s a, ivec3s b) + CGLM_INLINE ivec3s glms_ivec3_minv(ivec3s a, ivec3s b) + CGLM_INLINE ivec3s glms_ivec3_clamp(ivec3s v, int minVal, int maxVal) + CGLM_INLINE ivec3s glms_ivec3_abs(ivec3s v) + */ + +#ifndef cglms_ivec3_h +#define cglms_ivec3_h + +#include "../common.h" +#include "../types-struct.h" +#include "../ivec3.h" + +#define glms_ivec3_(NAME) CGLM_STRUCTAPI(ivec3, NAME) + +#define GLMS_IVEC3_ONE_INIT {GLM_IVEC3_ONE_INIT} +#define GLMS_IVEC3_ZERO_INIT {GLM_IVEC3_ZERO_INIT} + +#define GLMS_IVEC3_ONE ((ivec3s)GLMS_IVEC3_ONE_INIT) +#define GLMS_IVEC3_ZERO ((ivec3s)GLMS_IVEC3_ZERO_INIT) + +/*! + * @brief init ivec3 using ivec4 + * + * @param[in] v4 vector4 + * @returns destination + */ +CGLM_INLINE +ivec3s +glms_ivec3(ivec4s v4) { + ivec3s r; + glm_ivec3(v4.raw, r.raw); + return r; +} + +/*! + * @brief pack an array of ivec3 into an array of ivec3s + * + * @param[out] dst array of ivec3s + * @param[in] src array of ivec3 + * @param[in] len number of elements + */ +CGLM_INLINE +void +glms_ivec3_(pack)(ivec3s dst[], ivec3 src[], size_t len) { + size_t i; + + for (i = 0; i < len; i++) { + glm_ivec3_copy(src[i], dst[i].raw); + } +} + +/*! + * @brief unpack an array of ivec3s into an array of ivec3 + * + * @param[out] dst array of ivec3 + * @param[in] src array of ivec3s + * @param[in] len number of elements + */ +CGLM_INLINE +void +glms_ivec3_(unpack)(ivec3 dst[], ivec3s src[], size_t len) { + size_t i; + + for (i = 0; i < len; i++) { + glm_ivec3_copy(src[i].raw, dst[i]); + } +} + +/*! + * @brief set all members of [v] to zero + * + * @returns vector + */ +CGLM_INLINE +ivec3s +glms_ivec3_(zero)(void) { + ivec3s r; + glm_ivec3_zero(r.raw); + return r; +} + +/*! + * @brief set all members of [v] to one + * + * @returns vector + */ +CGLM_INLINE +ivec3s +glms_ivec3_(one)(void) { + ivec3s r; + glm_ivec3_one(r.raw); + return r; +} + +/*! + * @brief ivec3 dot product + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return dot product + */ +CGLM_INLINE +int +glms_ivec3_(dot)(ivec3s a, ivec3s b) { + return glm_ivec3_dot(a.raw, b.raw); +} + +/*! + * @brief norm * norm (magnitude) of vec + * + * we can use this func instead of calling norm * norm, because it would call + * sqrtf function twice but with this func we can avoid func call, maybe this is + * not good name for this func + * + * @param[in] v vector + * + * @return norm * norm + */ +CGLM_INLINE +int +glms_ivec3_(norm2)(ivec3s v) { + return glm_ivec3_norm2(v.raw); +} + +/*! + * @brief euclidean norm (magnitude), also called L2 norm + * this will give magnitude of vector in euclidean space + * + * @param[in] v vector + * + * @return norm + */ +CGLM_INLINE +int +glms_ivec3_(norm)(ivec3s v) { + return glm_ivec3_norm(v.raw); +} + +/*! + * @brief add vector [a] to vector [b] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec3s +glms_ivec3_(add)(ivec3s a, ivec3s b) { + ivec3s r; + glm_ivec3_add(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief add scalar s to vector [v] and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination + */ +CGLM_INLINE +ivec3s +glms_ivec3_(adds)(ivec3s v, int s) { + ivec3s r; + glm_ivec3_adds(v.raw, s, r.raw); + return r; +} + +/*! + * @brief subtract vector [b] from vector [a] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec3s +glms_ivec3_(sub)(ivec3s a, ivec3s b) { + ivec3s r; + glm_ivec3_sub(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief subtract scalar s from vector [v] and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination + */ +CGLM_INLINE +ivec3s +glms_ivec3_(subs)(ivec3s v, int s) { + ivec3s r; + glm_ivec3_subs(v.raw, s, r.raw); + return r; +} + +/*! + * @brief multiply vector [a] with vector [b] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec3s +glms_ivec3_(mul)(ivec3s a, ivec3s b) { + ivec3s r; + glm_ivec3_mul(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief multiply vector [a] with scalar s and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination + */ +CGLM_INLINE +ivec3s +glms_ivec3_(scale)(ivec3s v, int s) { + ivec3s r; + glm_ivec3_scale(v.raw, s, r.raw); + return r; +} + +/*! + * @brief div vector with another component-wise division: d = a / b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns result = (a[0]/b[0], a[1]/b[1], a[2]/b[2]) + */ +CGLM_INLINE +ivec3s +glms_ivec3_(div)(ivec3s a, ivec3s b) { + ivec3s r; + glm_ivec3_div(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief div vector with scalar: d = v / s + * + * @param[in] v vector + * @param[in] s scalar + * @returns result = (a[0]/s, a[1]/s, a[2]/s) + */ +CGLM_INLINE +ivec3s +glms_ivec3_(divs)(ivec3s v, int s) { + ivec3s r; + glm_ivec3_divs(v.raw, s, r.raw); + return r; +} + +/*! + * @brief Element-wise modulo operation on ivec3 vectors: dest = a % b + * + * Performs element-wise modulo on each component of vectors `a` and `b`. + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns result = (a[0]%b[0], a[1]%b[1], a[2]%b[2]) + */ +CGLM_INLINE +ivec3s +glms_ivec3_(mod)(ivec3s a, ivec3s b) { + ivec3s r; + glm_ivec3_mod(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief add vector [a] with vector [b] and add result to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += (a + b) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(addadd)(ivec3s a, ivec3s b, ivec3s dest) { + glm_ivec3_addadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add scalar [s] onto vector [a] and add result to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest += (a + s) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(addadds)(ivec3s a, int s, ivec3s dest) { + glm_ivec3_addadds(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief subtract vector [a] from vector [b] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += (a - b) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(subadd)(ivec3s a, ivec3s b, ivec3s dest) { + glm_ivec3_subadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief subtract scalar [s] from vector [a] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first + * @param[in] s scalar + * @param[in] dest dest += (a - s) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(subadds)(ivec3s a, int s, ivec3s dest) { + glm_ivec3_subadds(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief multiply vector [a] with vector [b] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += (a * b) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(muladd)(ivec3s a, ivec3s b, ivec3s dest) { + glm_ivec3_muladd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief multiply vector [a] with scalar [s] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest += (a * s) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(muladds)(ivec3s a, int s, ivec3s dest) { + glm_ivec3_muladds(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief add maximum of vector [a] and vector [b] to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += max(a, b) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(maxadd)(ivec3s a, ivec3s b, ivec3s dest) { + glm_ivec3_maxadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add minimum of vector [a] and vector [b] to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += min(a, b) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(minadd)(ivec3s a, ivec3s b, ivec3s dest) { + glm_ivec3_minadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief subtract vector [a] from vector [b] and subtract result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest -= (a - b) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(subsub)(ivec3s a, ivec3s b, ivec3s dest) { + glm_ivec3_subsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief subtract scalar [s] from vector [a] and subtract result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest -= (a - s) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(subsubs)(ivec3s a, int s, ivec3s dest) { + glm_ivec3_subsubs(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief add vector [a] to vector [b] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] b scalar + * @param[in] dest dest -= (a + b) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(addsub)(ivec3s a, ivec3s b, ivec3s dest) { + glm_ivec3_addsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add scalar [s] to vector [a] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest -= (a + b) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(addsubs)(ivec3s a, int s, ivec3s dest) { + glm_ivec3_addsubs(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief multiply vector [a] and vector [b] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] b scalar + * @param[in] dest dest -= (a * b) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(mulsub)(ivec3s a, ivec3s b, ivec3s dest) { + glm_ivec3_mulsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief multiply vector [a] with scalar [s] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest -= (a * s) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(mulsubs)(ivec3s a, int s, ivec3s dest) { + glm_ivec3_mulsubs(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief subtract maximum of vector [a] and vector [b] from vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest -= max(a, b) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(maxsub)(ivec3s a, ivec3s b, ivec3s dest) { + glm_ivec3_maxsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief subtract minimum of vector [a] and vector [b] from vector [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest -= min(a, b) + * @returns dest + */ +CGLM_INLINE +ivec3s +glms_ivec3_(minsub)(ivec3s a, ivec3s b, ivec3s dest) { + glm_ivec3_minsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief squared distance between two vectors + * + * @param[in] a first vector + * @param[in] b second vector + * @return returns squared distance (distance * distance) + */ +CGLM_INLINE +int +glms_ivec3_(distance2)(ivec3s a, ivec3s b) { + return glm_ivec3_distance2(a.raw, b.raw); +} + +/*! + * @brief distance between two vectors + * + * @param[in] a first vector + * @param[in] b second vector + * @return returns distance + */ +CGLM_INLINE +float +glms_ivec3_(distance)(ivec3s a, ivec3s b) { + return glm_ivec3_distance(a.raw, b.raw); +} + +/*! + * @brief fill a vector with specified value + * + * @param[in] val value + * @returns destination + */ +CGLM_INLINE +ivec3s +glms_ivec3_(fill)(int val) { + ivec3s r; + glm_ivec3_fill(r.raw, val); + return r; +} + +/*! + * @brief check if vector is equal to value + * + * @param[in] v vector + * @param[in] val value + */ +CGLM_INLINE +bool +glms_ivec3_(eq)(ivec3s v, int val) { + return glm_ivec3_eq(v.raw, val); +} + +/*! + * @brief check if vector is equal to another + * + * @param[in] a vector + * @param[in] b vector + */ +CGLM_INLINE +bool +glms_ivec3_(eqv)(ivec3s a, ivec3s b) { + return glm_ivec3_eqv(a.raw, b.raw); +} + +/*! + * @brief set each member of dest to greater of vector a and b + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec3s +glms_ivec3_(maxv)(ivec3s a, ivec3s b) { + ivec3s r; + glm_ivec3_maxv(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief set each member of dest to lesser of vector a and b + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec3s +glms_ivec3_(minv)(ivec3s a, ivec3s b) { + ivec3s r; + glm_ivec3_minv(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief clamp each member of [v] between minVal and maxVal (inclusive) + * + * @param[in] v vector + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + * @returns clamped vector + */ +CGLM_INLINE +ivec3s +glms_ivec3_(clamp)(ivec3s v, int minVal, int maxVal) { + glm_ivec3_clamp(v.raw, minVal, maxVal); + return v; +} + +/*! + * @brief absolute value of v + * + * @param[in] v vector + * @returns destination + */ +CGLM_INLINE +ivec3s +glms_ivec3_(abs)(ivec3s v) { + ivec3s r; + glm_ivec3_abs(v.raw, r.raw); + return r; +} + +#endif /* cglms_ivec3_h */ diff --git a/external/cglm/struct/ivec4.h b/external/cglm/struct/ivec4.h new file mode 100644 index 0000000..103e887 --- /dev/null +++ b/external/cglm/struct/ivec4.h @@ -0,0 +1,588 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_IVEC4_ONE_INIT + GLMS_IVEC4_ZERO_INIT + GLMS_IVEC4_ONE + GLMS_IVEC4_ZERO + + Functions: + CGLM_INLINE ivec4s glms_ivec4(ivec3s v3, int last) + CGLM_INLINE void glms_ivec4_pack(ivec4s dst[], ivec4 src[], size_t len) + CGLM_INLINE void glms_ivec4_unpack(ivec4 dst[], ivec4s src[], size_t len) + CGLM_INLINE ivec4s glms_ivec4_zero(void) + CGLM_INLINE ivec4s glms_ivec4_one(void) + CGLM_INLINE ivec4s glms_ivec4_add(ivec4s a, ivec4s b) + CGLM_INLINE ivec4s glms_ivec4_adds(ivec4s v, int s) + CGLM_INLINE ivec4s glms_ivec4_sub(ivec4s a, ivec4s b) + CGLM_INLINE ivec4s glms_ivec4_subs(ivec4s v, int s) + CGLM_INLINE ivec4s glms_ivec4_mul(ivec4s a, ivec4s b) + CGLM_INLINE ivec4s glms_ivec4_scale(ivec4s v, int s) + CGLM_INLINE ivec4s glms_ivec4_addadd(ivec4s a, ivec4s b, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_addadds(ivec4s a, int s, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_subadd(ivec4s a, ivec4s b, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_subadds(ivec4s a, int s, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_muladd(ivec4s a, ivec4s b, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_muladds(ivec4s a, int s, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_maxadd(ivec4s a, ivec4s b, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_minadd(ivec4s a, ivec4s b, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_subsub(ivec4s a, ivec4s b, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_subsubs(ivec4s a, int s, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_addsub(ivec4s a, ivec4s b, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_addsubs(ivec4s a, int s, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_mulsub(ivec4s a, ivec4s b, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_mulsubs(ivec4s a, int s, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_maxsub(ivec4s a, ivec4s b, ivec4s dest) + CGLM_INLINE ivec4s glms_ivec4_minsub(ivec4s a, ivec4s b, ivec4s dest) + CGLM_INLINE int glms_ivec4_distance2(ivec4s a, ivec4s b) + CGLM_INLINE float glms_ivec4_distance(ivec4s a, ivec4s b) + CGLM_INLINE ivec4s glms_ivec4_maxv(ivec4s a, ivec4s b) + CGLM_INLINE ivec4s glms_ivec4_minv(ivec4s a, ivec4s b) + CGLM_INLINE ivec4s glms_ivec4_clamp(ivec4s v, int minVal, int maxVal) + CGLM_INLINE ivec4s glms_ivec4_abs(ivec4s v) + */ + +#ifndef cglms_ivec4_h +#define cglms_ivec4_h + +#include "../common.h" +#include "../types-struct.h" +#include "../ivec4.h" + +#define glms_ivec4_(NAME) CGLM_STRUCTAPI(ivec4, NAME) + +#define GLMS_IVEC4_ONE_INIT {GLM_IVEC4_ONE_INIT} +#define GLMS_IVEC4_ZERO_INIT {GLM_IVEC4_ZERO_INIT} + +#define GLMS_IVEC4_ONE ((ivec4s)GLMS_IVEC4_ONE_INIT) +#define GLMS_IVEC4_ZERO ((ivec4s)GLMS_IVEC4_ZERO_INIT) + +/*! + * @brief init ivec4 using ivec3 + * + * @param[in] v3 vector3 + * @param[in] last last item + * @returns destination + */ +CGLM_INLINE +ivec4s +glms_ivec4(ivec3s v3, int last) { + ivec4s r; + glm_ivec4(v3.raw, last, r.raw); + return r; +} + +/*! + * @brief pack an array of ivec4 into an array of ivec4s + * + * @param[out] dst array of ivec4s + * @param[in] src array of ivec4 + * @param[in] len number of elements + */ +CGLM_INLINE +void +glms_ivec4_(pack)(ivec4s dst[], ivec4 src[], size_t len) { + size_t i; + + for (i = 0; i < len; i++) { + glm_ivec4_copy(src[i], dst[i].raw); + } +} + +/*! + * @brief unpack an array of ivec4s into an array of ivec4 + * + * @param[out] dst array of ivec4 + * @param[in] src array of ivec4s + * @param[in] len number of elements + */ +CGLM_INLINE +void +glms_ivec4_(unpack)(ivec4 dst[], ivec4s src[], size_t len) { + size_t i; + + for (i = 0; i < len; i++) { + glm_ivec4_copy(src[i].raw, dst[i]); + } +} + +/*! + * @brief set all members of [v] to zero + * + * @returns vector + */ +CGLM_INLINE +ivec4s +glms_ivec4_(zero)(void) { + ivec4s r; + glm_ivec4_zero(r.raw); + return r; +} + +/*! + * @brief set all members of [v] to one + * + * @returns vector + */ +CGLM_INLINE +ivec4s +glms_ivec4_(one)(void) { + ivec4s r; + glm_ivec4_one(r.raw); + return r; +} + +/*! + * @brief add vector [a] to vector [b] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec4s +glms_ivec4_(add)(ivec4s a, ivec4s b) { + ivec4s r; + glm_ivec4_add(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief add scalar s to vector [v] and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination + */ +CGLM_INLINE +ivec4s +glms_ivec4_(adds)(ivec4s v, int s) { + ivec4s r; + glm_ivec4_adds(v.raw, s, r.raw); + return r; +} + +/*! + * @brief subtract vector [b] from vector [a] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec4s +glms_ivec4_(sub)(ivec4s a, ivec4s b) { + ivec4s r; + glm_ivec4_sub(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief subtract scalar s from vector [v] and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination + */ +CGLM_INLINE +ivec4s +glms_ivec4_(subs)(ivec4s v, int s) { + ivec4s r; + glm_ivec4_subs(v.raw, s, r.raw); + return r; +} + +/*! + * @brief multiply vector [a] with vector [b] and store result in [dest] + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec4s +glms_ivec4_(mul)(ivec4s a, ivec4s b) { + ivec4s r; + glm_ivec4_mul(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief multiply vector [a] with scalar s and store result in [dest] + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination + */ +CGLM_INLINE +ivec4s +glms_ivec4_(scale)(ivec4s v, int s) { + ivec4s r; + glm_ivec4_scale(v.raw, s, r.raw); + return r; +} + +/*! + * @brief add vector [a] with vector [b] and add result to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += (a + b) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(addadd)(ivec4s a, ivec4s b, ivec4s dest) { + glm_ivec4_addadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add scalar [s] onto vector [a] and add result to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest += (a + s) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(addadds)(ivec4s a, int s, ivec4s dest) { + glm_ivec4_addadds(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief subtract vector [a] from vector [b] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += (a - b) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(subadd)(ivec4s a, ivec4s b, ivec4s dest) { + glm_ivec4_subadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief subtract scalar [s] from vector [a] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first + * @param[in] s scalar + * @param[in] dest dest += (a - s) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(subadds)(ivec4s a, int s, ivec4s dest) { + glm_ivec4_subadds(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief multiply vector [a] with vector [b] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += (a * b) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(muladd)(ivec4s a, ivec4s b, ivec4s dest) { + glm_ivec4_muladd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief multiply vector [a] with scalar [s] and add result to [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest += (a * s) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(muladds)(ivec4s a, int s, ivec4s dest) { + glm_ivec4_muladds(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief add maximum of vector [a] and vector [b] to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += max(a, b) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(maxadd)(ivec4s a, ivec4s b, ivec4s dest) { + glm_ivec4_maxadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add minimum of vector [a] and vector [b] to vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest += min(a, b) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(minadd)(ivec4s a, ivec4s b, ivec4s dest) { + glm_ivec4_minadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief subtract vector [a] from vector [b] and subtract result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest -= (a - b) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(subsub)(ivec4s a, ivec4s b, ivec4s dest) { + glm_ivec4_subsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief subtract scalar [s] from vector [a] and subtract result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest -= (a - s) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(subsubs)(ivec4s a, int s, ivec4s dest) { + glm_ivec4_subsubs(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief add vector [a] to vector [b] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] b scalar + * @param[in] dest dest -= (a + b) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(addsub)(ivec4s a, ivec4s b, ivec4s dest) { + glm_ivec4_addsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add scalar [s] to vector [a] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest -= (a + b) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(addsubs)(ivec4s a, int s, ivec4s dest) { + glm_ivec4_addsubs(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief multiply vector [a] and vector [b] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] b scalar + * @param[in] dest dest -= (a * b) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(mulsub)(ivec4s a, ivec4s b, ivec4s dest) { + glm_ivec4_mulsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief multiply vector [a] with scalar [s] and subtract the result from [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[in] dest dest -= (a * s) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(mulsubs)(ivec4s a, int s, ivec4s dest) { + glm_ivec4_mulsubs(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief subtract maximum of vector [a] and vector [b] from vector [dest] + * + * applies += operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest -= max(a, b) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(maxsub)(ivec4s a, ivec4s b, ivec4s dest) { + glm_ivec4_maxsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief subtract minimum of vector [a] and vector [b] from vector [dest] + * + * applies -= operator so dest must be initialized + * + * @param[in] a first vector + * @param[in] b second vector + * @param[in] dest dest -= min(a, b) + * @returns dest + */ +CGLM_INLINE +ivec4s +glms_ivec4_(minsub)(ivec4s a, ivec4s b, ivec4s dest) { + glm_ivec4_minsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief squared distance between two vectors + * + * @param[in] a first vector + * @param[in] b second vector + * @return returns squared distance (distance * distance) + */ +CGLM_INLINE +int +glms_ivec4_(distance2)(ivec4s a, ivec4s b) { + return glm_ivec4_distance2(a.raw, b.raw); +} + +/*! + * @brief distance between two vectors + * + * @param[in] a first vector + * @param[in] b second vector + * @return returns distance + */ +CGLM_INLINE +float +glms_ivec4_(distance)(ivec4s a, ivec4s b) { + return glm_ivec4_distance(a.raw, b.raw); +} + +/*! + * @brief set each member of dest to greater of vector a and b + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec4s +glms_ivec4_(maxv)(ivec4s a, ivec4s b) { + ivec4s r; + glm_ivec4_maxv(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief set each member of dest to lesser of vector a and b + * + * @param[in] a first vector + * @param[in] b second vector + * @returns destination + */ +CGLM_INLINE +ivec4s +glms_ivec4_(minv)(ivec4s a, ivec4s b) { + ivec4s r; + glm_ivec4_minv(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief clamp each member of [v] between minVal and maxVal (inclusive) + * + * @param[in] v vector + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + * @returns clamped vector + */ +CGLM_INLINE +ivec4s +glms_ivec4_(clamp)(ivec4s v, int minVal, int maxVal) { + glm_ivec4_clamp(v.raw, minVal, maxVal); + return v; +} + +/*! + * @brief absolute value of v + * + * @param[in] v vector + * @returns destination + */ +CGLM_INLINE +ivec4s +glms_ivec4_(abs)(ivec4s v) { + ivec4s r; + glm_ivec4_abs(v.raw, r.raw); + return r; +} + +#endif /* cglms_ivec4_h */ diff --git a/external/cglm/struct/mat2.h b/external/cglm/struct/mat2.h new file mode 100644 index 0000000..915c1be --- /dev/null +++ b/external/cglm/struct/mat2.h @@ -0,0 +1,274 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_MAT2_IDENTITY_INIT + GLM_MAT2_ZERO_INIT + GLM_MAT2_IDENTITY + GLM_MAT2_ZERO + + Functions: + CGLM_INLINE mat2s glms_mat2_make(const float * __restrict src); + CGLM_INLINE mat2s glms_mat2_identity(void) + CGLM_INLINE void glms_mat2_identity_array(mat2 * restrict mats, size_t count) + CGLM_INLINE mat2s glms_mat2_zero(void) + CGLM_INLINE mat2s glms_mat2_mul(mat2 m1, mat2 m2) + CGLM_INLINE vec2s glms_mat2_mulv(mat2 m, vec2 v) + CGLM_INLINE mat2s glms_mat2_transpose(mat2 m) + CGLM_INLINE mat2s glms_mat2_scale(mat2 m, float s) + CGLM_INLINE mat2s glms_mat2_inv(mat2 m) + CGLM_INLINE mat2s glms_mat2_swap_col(mat2 mat, int col1, int col2) + CGLM_INLINE mat2s glms_mat2_swap_row(mat2 mat, int row1, int row2) + CGLM_INLINE float glms_mat2_det(mat2 m) + CGLM_INLINE float glms_mat2_trace(mat2 m) + CGLM_INLINE float glms_mat2_rmc(vec2 r, mat2 m, vec2 c) + */ + +#ifndef cglms_mat2_h +#define cglms_mat2_h + +#include "../common.h" +#include "../types-struct.h" +#include "../mat2.h" + +/* api definition */ +#define glms_mat2_(NAME) CGLM_STRUCTAPI(mat2, NAME) + +#define GLMS_MAT2_IDENTITY_INIT {GLM_MAT2_IDENTITY_INIT} +#define GLMS_MAT2_ZERO_INIT {GLM_MAT2_ZERO_INIT} + +/* for C only */ +#define GLMS_MAT2_IDENTITY ((mat2s)GLMS_MAT2_IDENTITY_INIT) +#define GLMS_MAT2_ZERO ((mat2s)GLMS_MAT2_ZERO_INIT) + +/*! + * @brief Returns mat2s (r) from pointer (src). + * + * @param[in] src pointer to an array of floats + * @return[out] r constructed mat2s from raw pointer + */ +CGLM_INLINE +mat2s +glms_mat2_(make)(const float * __restrict src) { + mat2s r; + glm_mat2_make(src, r.raw); + return r; +} + +/*! + * @brief Return a identity mat2s (r). + * + * The same thing may be achieved with either of bellow methods, + * but it is more easy to do that with this func especially for members + * e.g. glm_mat2_identity(aStruct->aMatrix); + * + * @code + * glm_mat2_copy(GLM_MAT2_IDENTITY, mat); // C only + * + * // or + * mat2 mat = GLM_MAT2_IDENTITY_INIT; + * @endcode + * + * @return[out] r constructed mat2s from raw pointer + */ +CGLM_INLINE +mat2s +glms_mat2_(identity)(void) { + mat2s r; + glm_mat2_identity(r.raw); + return r; +} + +/*! + * @brief Given an array of mat2s’s (mats) make each matrix an identity matrix. + * + * @param[in, out] mats Array of mat2s’s (must be aligned (16/32) if alignment is not disabled) + * @param[in] count Array size of mats or number of matrices + */ +CGLM_INLINE +void +glms_mat2_(identity_array)(mat2s * __restrict mats, size_t count) { + CGLM_ALIGN_MAT mat2s t = GLMS_MAT2_IDENTITY_INIT; + size_t i; + + for (i = 0; i < count; i++) { + glm_mat2_copy(t.raw, mats[i].raw); + } +} + +/*! + * @brief Return zero'd out mat2 (r). + * + * @return[out] r constructed mat2s from raw pointer + */ +CGLM_INLINE +mat2s +glms_mat2_(zero)(void) { + mat2s r; + glm_mat2_zero(r.raw); + return r; +} + +/*! + * @brief Multiply mat2 (m1) by mat2 (m2) and return in mat2s (r) + * + * m1 and m2 matrices can be the same matrix, it is possible to write this: + * + * @code + * mat2 m = GLM_MAT2_IDENTITY_INIT; + * mat2s r = glms_mat2_mul(m, m); + * @endcode + * + * @param[in] m1 mat2s (left) + * @param[in] m2 mat2s (right) + * @return[out] r constructed mat2s from raw pointers + */ +CGLM_INLINE +mat2s +glms_mat2_(mul)(mat2s m1, mat2s m2) { + mat2s r; + glm_mat2_mul(m1.raw, m2.raw, r.raw); + return r; +} + +/* + * @brief Multiply mat2s (m) by vec2s (v) and return in vec2s (r). + * + * @param[in] m mat2s (left) + * @param[in] v vec2s (right, column vector) + * @return[out] r constructed vec2s from raw pointers + */ +CGLM_INLINE +vec2s +glms_mat2_(mulv)(mat2s m, vec2s v) { + vec2s r; + glm_mat2_mulv(m.raw, v.raw, r.raw); + return r; +} + +/*! + * @brief Transpose mat2s (m) and store result in the same matrix. + * + * @param[in] m mat2s (src) + * @return[out] m constructed mat2s from raw pointers + */ +CGLM_INLINE +mat2s +glms_mat2_(transpose)(mat2s m) { + glm_mat2_transpose(m.raw); + return m; +} + +/*! + * @brief Multiply mat2s (m) by scalar constant (s) + * + * @param[in] m mat2s (src) + * @param[in] s scalar value + * @return[out] m constructed mat2s from raw pointers + */ +CGLM_INLINE +mat2s +glms_mat2_(scale)(mat2s m, float s) { + glm_mat2_scale(m.raw, s); + return m; +} + +/*! + * @brief Inverse mat2s (m) and return in mat2s (r). + * + * @param[in] m mat2s (left, src) + * @return[out] r constructed mat2s from raw pointers + */ +CGLM_INLINE +mat2s +glms_mat2_(inv)(mat2s m) { + mat2s r; + glm_mat2_inv(m.raw, r.raw); + return r; +} + +/*! + * @brief Swap two columns in mat2s (mat) and store in same matrix. + * + * @param[in] mat mat2s + * @param[in] col1 column 1 array index + * @param[in] col2 column 2 array index + * @return[out] mat constructed mat2s from raw pointers columns swapped + */ +CGLM_INLINE +mat2s +glms_mat2_(swap_col)(mat2s mat, int col1, int col2) { + glm_mat2_swap_col(mat.raw, col1, col2); + return mat; +} + +/*! + * @brief Swap two rows in mat2s (mat) and store in same matrix. + * + * @param[in] mat mat2s + * @param[in] row1 row 1 array index + * @param[in] row2 row 2 array index + * @return[out] mat constructed mat2s from raw pointers rows swapped + */ +CGLM_INLINE +mat2s +glms_mat2_(swap_row)(mat2s mat, int row1, int row2) { + glm_mat2_swap_row(mat.raw, row1, row2); + return mat; +} + +/*! + * @brief Returns mat2 determinant. + * + * @param[in] m mat2 (src) + * + * @return[out] mat2s raw pointers determinant (float) + */ +CGLM_INLINE +float +glms_mat2_(det)(mat2s m) { + return glm_mat2_det(m.raw); +} + +/*! + * @brief Returns trace of matrix. Which is: + * + * The sum of the elements on the main diagonal from + * upper left corner to the bottom right corner. + * + * @param[in] m mat2 (m) + * + * @return[out] mat2s raw pointers trace (float) + */ +CGLM_INLINE +float +glms_mat2_(trace)(mat2s m) { + return glm_mat2_trace(m.raw); +} + +/*! + * @brief Helper for R (row vector) * M (matrix) * C (column vector) + * + * rmc stands for Row * Matrix * Column + * + * the result is scalar because M * C = ResC (1x2, column vector), + * then if you take the dot_product(R (2x1), ResC (1x2)) = scalar value. + * + * @param[in] r vec2s (2x1, row vector) + * @param[in] m mat2s (2x2, matrix) + * @param[in] c vec2s (1x2, column vector) + * + * @return[out] Scalar value (float, 1x1) + */ +CGLM_INLINE +float +glms_mat2_(rmc)(vec2s r, mat2s m, vec2s c) { + return glm_mat2_rmc(r.raw, m.raw, c.raw); +} + +#endif /* cglms_mat2_h */ diff --git a/external/cglm/struct/mat2x3.h b/external/cglm/struct/mat2x3.h new file mode 100644 index 0000000..5b061ba --- /dev/null +++ b/external/cglm/struct/mat2x3.h @@ -0,0 +1,125 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_MAT2X3_ZERO_INIT + GLMS_MAT2X3_ZERO + + Functions: + CGLM_INLINE mat2x3s glms_mat2x3_zero(void); + CGLM_INLINE mat2x3s glms_mat2x3_make(const float * __restrict src); + CGLM_INLINE mat2s glms_mat2x3_mul(mat2x3s m1, mat3x2s m2); + CGLM_INLINE vec3s glms_mat2x3_mulv(mat2x3s m, vec2s v); + CGLM_INLINE mat3x2s glms_mat2x3_transpose(mat2x3s m); + CGLM_INLINE mat2x3s glms_mat2x3_scale(mat2x3s m, float s); + */ + +#ifndef cglms_mat2x3_h +#define cglms_mat2x3_h + +#include "../common.h" +#include "../types-struct.h" +#include "../mat2x3.h" + +/* api definition */ +#define glms_mat2x3_(NAME) CGLM_STRUCTAPI(mat2x3, NAME) + +#define GLMS_MAT2X3_ZERO_INIT {GLM_MAT2X3_ZERO_INIT} + +/* for C only */ +#define GLMS_MAT2X3_ZERO ((mat2x3s)GLMS_MAT2X3_ZERO_INIT) + +/*! + * @brief Zero out the mat2x3s (dest). + * + * @return[out] dest constructed mat2x3s from raw pointer + */ +CGLM_INLINE +mat2x3s +glms_mat2x3_(zero)(void) { + mat2x3s dest; + glm_mat2x3_zero(dest.raw); + return dest; +} + +/*! + * @brief Create mat2x3s (dest) from pointer (src). + * + * @param[in] src pointer to an array of floats + * @return[out] dest constructed mat2x3s from raw pointer + */ +CGLM_INLINE +mat2x3s +glms_mat2x3_(make)(const float * __restrict src) { + mat2x3s dest; + glm_mat2x3_make(src, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat2x3s (m1) by mat3x2s (m2) and store in mat3s (dest). + * + * @code + * r = glms_mat2x3_mul(mat2x3s, mat3x2s); + * @endcode + * + * @param[in] m1 mat2x3s (left) + * @param[in] m2 mat3x2s (right) + * @return[out] dest constructed mat3s from raw pointers + */ +CGLM_INLINE +mat3s +glms_mat2x3_(mul)(mat2x3s m1, mat3x2s m2) { + mat3s dest; + glm_mat2x3_mul(m1.raw, m2.raw, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat2x3s (m) by vec2s (v) and store in vec3s (dest). + * + * @param[in] m mat2x3s (left) + * @param[in] v vec2s (right, column vector) + * @return[out] dest constructed vec3s from raw pointers + */ +CGLM_INLINE +vec3s +glms_mat2x3_(mulv)(mat2x3s m, vec2s v) { + vec3s dest; + glm_mat2x3_mulv(m.raw, v.raw, dest.raw); + return dest; +} + +/*! + * @brief Transpose mat2x3s (m) and store in mat3x2s (dest). + * + * @param[in] m mat2x3s (left) + * @return[out] dest constructed mat3x2s from raw pointers + */ +CGLM_INLINE +mat3x2s +glms_mat2x3_(transpose)(mat2x3s m) { + mat3x2s dest; + glm_mat2x3_transpose(m.raw, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat2x3s (m) by scalar constant (s). + * + * @param[in, out] m mat2x3 (src, dest) + * @param[in] s float (scalar) + */ +CGLM_INLINE +mat2x3s +glms_mat2x3_(scale)(mat2x3s m, float s) { + glm_mat2x3_scale(m.raw, s); + return m; +} + +#endif /* cglms_mat2x3_h */ diff --git a/external/cglm/struct/mat2x4.h b/external/cglm/struct/mat2x4.h new file mode 100644 index 0000000..7e3e75a --- /dev/null +++ b/external/cglm/struct/mat2x4.h @@ -0,0 +1,125 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_MAT2X4_ZERO_INIT + GLMS_MAT2X4_ZERO + + Functions: + CGLM_INLINE mat2x4s glms_mat2x4_zero(void); + CGLM_INLINE mat2x4s glms_mat2x4_make(const float * __restrict src); + CGLM_INLINE mat2s glms_mat2x4_mul(mat2x4s m1, mat4x2s m2); + CGLM_INLINE vec4s glms_mat2x4_mulv(mat2x4s m, vec2s v); + CGLM_INLINE mat4x2s glms_mat2x4_transpose(mat2x4s m); + CGLM_INLINE mat2x4s glms_mat2x4_scale(mat2x4s m, float s); + */ + +#ifndef cglms_mat2x4_h +#define cglms_mat2x4_h + +#include "../common.h" +#include "../types-struct.h" +#include "../mat2x4.h" + +/* api definition */ +#define glms_mat2x4_(NAME) CGLM_STRUCTAPI(mat2x4, NAME) + +#define GLMS_MAT2X4_ZERO_INIT {GLM_MAT2X4_ZERO_INIT} + +/* for C only */ +#define GLMS_MAT2X4_ZERO ((mat2x4s)GLMS_MAT2X4_ZERO_INIT) + +/*! + * @brief Zero out the mat2x4s (dest). + * + * @return[out] dest constructed mat2x4s from raw pointer + */ +CGLM_INLINE +mat2x4s +glms_mat2x4_(zero)(void) { + mat2x4s dest; + glm_mat2x4_zero(dest.raw); + return dest; +} + +/*! + * @brief Create mat2x4s (dest) from pointer (src). + * + * @param[in] src pointer to an array of floats + * @return[out] dest constructed mat2x4s from raw pointer + */ +CGLM_INLINE +mat2x4s +glms_mat2x4_(make)(const float * __restrict src) { + mat2x4s dest; + glm_mat2x4_make(src, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat2x4s (m1) by mat4x2s (m2) and store in mat4s (dest). + * + * @code + * r = glms_mat2x4_mul(mat2x4s, mat4x2s); + * @endcode + * + * @param[in] m1 mat2x4s (left) + * @param[in] m2 mat4x2s (right) + * @return[out] dest constructed mat4s from raw pointers + */ +CGLM_INLINE +mat4s +glms_mat2x4_(mul)(mat2x4s m1, mat4x2s m2) { + mat4s dest; + glm_mat2x4_mul(m1.raw, m2.raw, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat2x4s (m) by vec2s (v) and store in vec4s (dest). + * + * @param[in] m mat2x4s (left) + * @param[in] v vec2s (right, column vector) + * @return[out] dest constructed vec4s from raw pointers + */ +CGLM_INLINE +vec4s +glms_mat2x4_(mulv)(mat2x4s m, vec2s v) { + vec4s dest; + glm_mat2x4_mulv(m.raw, v.raw, dest.raw); + return dest; +} + +/*! + * @brief Transpose mat2x4s (m) and store in mat4x2s (dest). + * + * @param[in] m mat2x4s (left) + * @return[out] dest constructed mat4x2s from raw pointers + */ +CGLM_INLINE +mat4x2s +glms_mat2x4_(transpose)(mat2x4s m) { + mat4x2s dest; + glm_mat2x4_transpose(m.raw, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat2x4s (m) by scalar constant (s). + * + * @param[in, out] m mat2x4s (src, dest) + * @param[in] s float (scalar) + */ +CGLM_INLINE +mat2x4s +glms_mat2x4_(scale)(mat2x4s m, float s) { + glm_mat2x4_scale(m.raw, s); + return m; +} + +#endif /* cglms_mat2x4_h */ diff --git a/external/cglm/struct/mat3.h b/external/cglm/struct/mat3.h new file mode 100644 index 0000000..2fae073 --- /dev/null +++ b/external/cglm/struct/mat3.h @@ -0,0 +1,322 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_MAT3_IDENTITY_INIT + GLMS_MAT3_ZERO_INIT + GLMS_MAT3_IDENTITY + GLMS_MAT3_ZERO + + Functions: + CGLM_INLINE mat3s glms_mat3_copy(mat3s mat); + CGLM_INLINE mat3s glms_mat3_identity(void); + CGLM_INLINE void glms_mat3_identity_array(mat3s * __restrict mat, size_t count); + CGLM_INLINE mat3s glms_mat3_zero(void); + CGLM_INLINE mat3s glms_mat3_mul(mat3s m1, mat3s m2); + CGLM_INLINE ma3s glms_mat3_transpose(mat3s m); + CGLM_INLINE vec3s glms_mat3_mulv(mat3s m, vec3s v); + CGLM_INLINE float glms_mat3_trace(mat3s m); + CGLM_INLINE versor glms_mat3_quat(mat3s m); + CGLM_INLINE mat3s glms_mat3_scale(mat3s m, float s); + CGLM_INLINE float glms_mat3_det(mat3s mat); + CGLM_INLINE mat3s glms_mat3_inv(mat3s mat); + CGLM_INLINE mat3s glms_mat3_swap_col(mat3s mat, int col1, int col2); + CGLM_INLINE mat3s glms_mat3_swap_row(mat3s mat, int row1, int row2); + CGLM_INLINE float glms_mat3_rmc(vec3s r, mat3s m, vec3s c); + CGLM_INLINE mat3s glms_mat3_make(const float * __restrict src); + CGLM_INLINE mat3s glms_mat3_textrans(float sx, float sy, float rot, float tx, float ty); + */ + +#ifndef cglms_mat3s_h +#define cglms_mat3s_h + +#include "../common.h" +#include "../types-struct.h" +#include "../mat3.h" +#include "vec3.h" + +/* api definition */ +#define glms_mat3_(NAME) CGLM_STRUCTAPI(mat3, NAME) + +#define GLMS_MAT3_IDENTITY_INIT {GLM_MAT3_IDENTITY_INIT} +#define GLMS_MAT3_ZERO_INIT {GLM_MAT3_ZERO_INIT} + +/* for C only */ +#define GLMS_MAT3_IDENTITY ((mat3s)GLMS_MAT3_IDENTITY_INIT) +#define GLMS_MAT3_ZERO ((mat3s)GLMS_MAT3_ZERO_INIT) + +/*! + * @brief copy all members of [mat] to [dest] + * + * @param[in] mat source + * @returns destination + */ +CGLM_INLINE +mat3s +glms_mat3_(copy)(mat3s mat) { + mat3s r; + glm_mat3_copy(mat.raw, r.raw); + return r; +} + +/*! + * @brief make given matrix identity. It is identical with below, + * but it is more easy to do that with this func especially for members + * e.g. glm_mat3_identity(aStruct->aMatrix); + * + * @code + * glm_mat3_copy(GLM_MAT3_IDENTITY, mat); // C only + * + * // or + * mat3 mat = GLM_MAT3_IDENTITY_INIT; + * @endcode + * + * @returns destination + */ +CGLM_INLINE +mat3s +glms_mat3_(identity)(void) { + mat3s r; + glm_mat3_identity(r.raw); + return r; +} + +/*! + * @brief make given matrix array's each element identity matrix + * + * @param[in, out] mat matrix array (must be aligned (16/32) + * if alignment is not disabled) + * + * @param[in] count count of matrices + */ +CGLM_INLINE +void +glms_mat3_(identity_array)(mat3s * __restrict mat, size_t count) { + CGLM_ALIGN_MAT mat3s t = GLMS_MAT3_IDENTITY_INIT; + size_t i; + + for (i = 0; i < count; i++) { + glm_mat3_copy(t.raw, mat[i].raw); + } +} + +/*! + * @brief make given matrix zero. + * + * @returns matrix + */ +CGLM_INLINE +mat3s +glms_mat3_(zero)(void) { + mat3s r; + glm_mat3_zero(r.raw); + return r; +} + +/*! + * @brief multiply m1 and m2 to dest + * + * m1, m2 and dest matrices can be same matrix, it is possible to write this: + * + * @code + * mat3 m = GLM_MAT3_IDENTITY_INIT; + * r = glms_mat3_mul(m, m); + * @endcode + * + * @param[in] m1 left matrix + * @param[in] m2 right matrix + * @returns destination matrix + */ +CGLM_INLINE +mat3s +glms_mat3_(mul)(mat3s m1, mat3s m2) { + mat3s r; + glm_mat3_mul(m1.raw, m2.raw, r.raw); + return r; +} + +/*! + * @brief transpose mat3 and store result in same matrix + * + * @param[in, out] m source and dest + */ +CGLM_INLINE +mat3s +glms_mat3_(transpose)(mat3s m) { + glm_mat3_transpose(m.raw); + return m; +} + +/*! + * @brief multiply mat3 with vec3 (column vector) and store in dest vector + * + * @param[in] m mat3 (left) + * @param[in] v vec3 (right, column vector) + * @returns vec3 (result, column vector) + */ +CGLM_INLINE +vec3s +glms_mat3_(mulv)(mat3s m, vec3s v) { + vec3s r; + glm_mat3_mulv(m.raw, v.raw, r.raw); + return r; +} + +/*! + * @brief trace of matrix + * + * sum of the elements on the main diagonal from upper left to the lower right + * + * @param[in] m matrix + */ +CGLM_INLINE +float +glms_mat3_(trace)(mat3s m) { + return glm_mat3_trace(m.raw); +} + +/*! + * @brief convert mat3 to quaternion + * + * @param[in] m rotation matrix + * @returns destination quaternion + */ +CGLM_INLINE +versors +glms_mat3_(quat)(mat3s m) { + versors r; + glm_mat3_quat(m.raw, r.raw); + return r; +} + +/*! + * @brief scale (multiply with scalar) matrix + * + * multiply matrix with scalar + * + * @param[in] m matrix + * @param[in] s scalar + * @returns scaled matrix + */ +CGLM_INLINE +mat3s +glms_mat3_(scale)(mat3s m, float s) { + glm_mat3_scale(m.raw, s); + return m; +} + +/*! + * @brief mat3 determinant + * + * @param[in] mat matrix + * + * @return determinant + */ +CGLM_INLINE +float +glms_mat3_(det)(mat3s mat) { + return glm_mat3_det(mat.raw); +} + +/*! + * @brief inverse mat3 and store in dest + * + * @param[in] mat matrix + * @returns inverse matrix + */ +CGLM_INLINE +mat3s +glms_mat3_(inv)(mat3s mat) { + mat3s r; + glm_mat3_inv(mat.raw, r.raw); + return r; +} + +/*! + * @brief swap two matrix columns + * + * @param[in] mat matrix + * @param[in] col1 col1 + * @param[in] col2 col2 + * @returns matrix + */ +CGLM_INLINE +mat3s +glms_mat3_(swap_col)(mat3s mat, int col1, int col2) { + glm_mat3_swap_col(mat.raw, col1, col2); + return mat; +} + +/*! + * @brief swap two matrix rows + * + * @param[in] mat matrix + * @param[in] row1 row1 + * @param[in] row2 row2 + * @returns matrix + */ +CGLM_INLINE +mat3s +glms_mat3_(swap_row)(mat3s mat, int row1, int row2) { + glm_mat3_swap_row(mat.raw, row1, row2); + return mat; +} + +/*! + * @brief helper for R (row vector) * M (matrix) * C (column vector) + * + * rmc stands for Row * Matrix * Column + * + * the result is scalar because R * M = Matrix1x3 (row vector), + * then Matrix1x3 * Vec3 (column vector) = Matrix1x1 (Scalar) + * + * @param[in] r row vector or matrix1x3 + * @param[in] m matrix3x3 + * @param[in] c column vector or matrix3x1 + * + * @return scalar value e.g. Matrix1x1 + */ +CGLM_INLINE +float +glms_mat3_(rmc)(vec3s r, mat3s m, vec3s c) { + return glm_mat3_rmc(r.raw, m.raw, c.raw); +} + +/*! + * @brief Create mat3 matrix from pointer + * + * @param[in] src pointer to an array of floats + * @return constructed matrix from raw pointer + */ +CGLM_INLINE +mat3s +glms_mat3_(make)(const float * __restrict src) { + mat3s r; + glm_mat3_make(src, r.raw); + return r; +} + +/*! + * @brief Create mat3 matrix from texture transform parameters + * + * @param[in] sx scale x + * @param[in] sy scale y + * @param[in] rot rotation in radians CCW/RH + * @param[in] tx translate x + * @param[in] ty translate y + * @return texture transform matrix + */ +CGLM_INLINE +mat3s +glms_mat3_(textrans)(float sx, float sy, float rot, float tx, float ty) { + mat3s r; + glm_mat3_textrans(sx, sy, rot, tx, ty, r.raw); + return r; +} + +#endif /* cglms_mat3s_h */ diff --git a/external/cglm/struct/mat3x2.h b/external/cglm/struct/mat3x2.h new file mode 100644 index 0000000..ab2d388 --- /dev/null +++ b/external/cglm/struct/mat3x2.h @@ -0,0 +1,125 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_MAT3X2_ZERO_INIT + GLMS_MAT3X2_ZERO + + Functions: + CGLM_INLINE mat3x2s glms_mat3x2_zero(void); + CGLM_INLINE mat3x2s glms_mat3x2_make(const float * __restrict src); + CGLM_INLINE mat2s glms_mat3x2_mul(mat3x2s m1, mat2x3s m2); + CGLM_INLINE vec2s glms_mat3x2_mulv(mat3x2s m, vec3s v); + CGLM_INLINE mat2x3s glms_mat3x2_transpose(mat3x2s m); + CGLM_INLINE mat3x2s glms_mat3x2_scale(mat3x2s m, float s); + */ + +#ifndef cglms_mat3x2_h +#define cglms_mat3x2_h + +#include "../common.h" +#include "../types-struct.h" +#include "../mat3x2.h" + +/* api definition */ +#define glms_mat3x2_(NAME) CGLM_STRUCTAPI(mat3x2, NAME) + +#define GLMS_MAT3X2_ZERO_INIT {GLM_MAT3X2_ZERO_INIT} + +/* for C only */ +#define GLMS_MAT3X2_ZERO ((mat3x2s)GLMS_MAT3X2_ZERO_INIT) + +/*! + * @brief Zero out the mat3x2s (dest). + * + * @return[out] dest constructed mat3x2s from raw pointer + */ +CGLM_INLINE +mat3x2s +glms_mat3x2_(zero)(void) { + mat3x2s dest; + glm_mat3x2_zero(dest.raw); + return dest; +} + +/*! + * @brief Create mat3x2s (dest) from pointer (src). + * + * @param[in] src pointer to an array of floats + * @return[out] dest constructed mat3x2s from raw pointer + */ +CGLM_INLINE +mat3x2s +glms_mat3x2_(make)(const float * __restrict src) { + mat3x2s dest; + glm_mat3x2_make(src, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat3x2s (m1) by mat2x3s (m2) and store in mat2s (dest). + * + * @code + * r = glms_mat3x2_mul(mat3x2s, mat2x3s); + * @endcode + * + * @param[in] m1 mat3x2s (left) + * @param[in] m2 mat2x3s (right) + * @return[out] dest constructed mat2s from raw pointers + */ +CGLM_INLINE +mat2s +glms_mat3x2_(mul)(mat3x2s m1, mat2x3s m2) { + mat2s dest; + glm_mat3x2_mul(m1.raw, m2.raw, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat3x2s (m) by vec3s (v) and store in vec2s (dest). + * + * @param[in] m mat3x2s (left) + * @param[in] v vec3s (right, column vector) + * @return[out] dest constructed vec2s from raw pointers + */ +CGLM_INLINE +vec2s +glms_mat3x2_(mulv)(mat3x2s m, vec3s v) { + vec2s dest; + glm_mat3x2_mulv(m.raw, v.raw, dest.raw); + return dest; +} + +/*! + * @brief Transpose mat3x2s (m) and store in mat2x3s (dest). + * + * @param[in] m mat3x2s (left) + * @return[out] dest constructed mat2x3s from raw pointers + */ +CGLM_INLINE +mat2x3s +glms_mat3x2_(transpose)(mat3x2s m) { + mat2x3s dest; + glm_mat3x2_transpose(m.raw, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat3x2s (m) by scalar constant (s). + * + * @param[in, out] m mat3x2s (src, dest) + * @param[in] s float (scalar) + */ +CGLM_INLINE +mat3x2s +glms_mat3x2_(scale)(mat3x2s m, float s) { + glm_mat3x2_scale(m.raw, s); + return m; +} + +#endif /* cglms_mat3x2_h */ diff --git a/external/cglm/struct/mat3x4.h b/external/cglm/struct/mat3x4.h new file mode 100644 index 0000000..436b36c --- /dev/null +++ b/external/cglm/struct/mat3x4.h @@ -0,0 +1,125 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_MAT3X4_ZERO_INIT + GLMS_MAT3X4_ZERO + + Functions: + CGLM_INLINE mat3x4s glms_mat3x4_zero(void); + CGLM_INLINE mat3x4s glms_mat3x4_make(const float * __restrict src); + CGLM_INLINE mat4s glms_mat3x4_mul(mat3x4s m1, mat4x3s m2); + CGLM_INLINE vec4s glms_mat3x4_mulv(mat3x4s m, vec3s v); + CGLM_INLINE mat4x3s glms_mat3x4_transpose(mat3x4s m); + CGLM_INLINE mat3x4s glms_mat3x4_scale(mat3x4s m, float s); + */ + +#ifndef cglms_mat3x4_h +#define cglms_mat3x4_h + +#include "../common.h" +#include "../types-struct.h" +#include "../mat3x4.h" + +/* api definition */ +#define glms_mat3x4_(NAME) CGLM_STRUCTAPI(mat3x4, NAME) + +#define GLMS_MAT3X4_ZERO_INIT {GLM_MAT3X4_ZERO_INIT} + +/* for C only */ +#define GLMS_MAT3X4_ZERO ((mat3x4s)GLMS_MAT3X4_ZERO_INIT) + +/*! + * @brief Zero out the mat3x4s (dest). + * + * @return[out] dest constructed mat3x4s from raw pointer + */ +CGLM_INLINE +mat3x4s +glms_mat3x4_(zero)(void) { + mat3x4s dest; + glm_mat3x4_zero(dest.raw); + return dest; +} + +/*! + * @brief Create mat3x4s (dest) from pointer (src). + * + * @param[in] src pointer to an array of floats + * @return[out] dest constructed mat3x4s from raw pointer + */ +CGLM_INLINE +mat3x4s +glms_mat3x4_(make)(const float * __restrict src) { + mat3x4s dest; + glm_mat3x4_make(src, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat3x4s (m1) by mat4x3s (m2) and store in mat4s (dest). + * + * @code + * r = glms_mat3x4_mul(mat3x4s, mat4x3s); + * @endcode + * + * @param[in] m1 mat3x4s (left) + * @param[in] m2 mat4x3s (right) + * @return[out] dest constructed mat4s from raw pointers + */ +CGLM_INLINE +mat4s +glms_mat3x4_(mul)(mat3x4s m1, mat4x3s m2) { + mat4s dest; + glm_mat3x4_mul(m1.raw, m2.raw, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat3x4s (m) by vec3s (v) and store in vec4s (dest). + * + * @param[in] m mat3x4s (left) + * @param[in] v vec3s (right, column vector) + * @return[out] dest constructed vec4s from raw pointers + */ +CGLM_INLINE +vec4s +glms_mat3x4_(mulv)(mat3x4s m, vec3s v) { + vec4s dest; + glm_mat3x4_mulv(m.raw, v.raw, dest.raw); + return dest; +} + +/*! + * @brief Transpose mat3x4s (m) and store in mat4x3s (dest). + * + * @param[in] m mat3x4s (left) + * @return[out] dest constructed mat4x3s from raw pointers + */ +CGLM_INLINE +mat4x3s +glms_mat3x4_(transpose)(mat3x4s m) { + mat4x3s dest; + glm_mat3x4_transpose(m.raw, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat3x4s (m) by scalar constant (s). + * + * @param[in, out] m mat3x4s (src, dest) + * @param[in] s float (scalar) + */ +CGLM_INLINE +mat3x4s +glms_mat3x4_(scale)(mat3x4s m, float s) { + glm_mat3x4_scale(m.raw, s); + return m; +} + +#endif /* cglms_mat3x4_h */ diff --git a/external/cglm/struct/mat4.h b/external/cglm/struct/mat4.h new file mode 100644 index 0000000..663a5fd --- /dev/null +++ b/external/cglm/struct/mat4.h @@ -0,0 +1,496 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/*! + * Most of functions in this header are optimized manually with SIMD + * if available. You dont need to call/incude SIMD headers manually + */ + +/* + Macros: + GLMS_MAT4_IDENTITY_INIT + GLMS_MAT4_ZERO_INIT + GLMS_MAT4_IDENTITY + GLMS_MAT4_ZERO + + Functions: + CGLM_INLINE mat4s glms_mat4_ucopy(mat4s mat); + CGLM_INLINE mat4s glms_mat4_copy(mat4s mat); + CGLM_INLINE mat4s glms_mat4_identity(void); + CGLM_INLINE void glms_mat4_identity_array(mat4s * __restrict mat, size_t count); + CGLM_INLINE mat4s glms_mat4_zero(void); + CGLM_INLINE mat3s glms_mat4_pick3(mat4s mat); + CGLM_INLINE mat3s glms_mat4_pick3t(mat4s mat); + CGLM_INLINE mat4s glms_mat4_ins3(mat3s mat, mat4s dest); + CGLM_INLINE mat4s glms_mat4_mul(mat4s m1, mat4s m2); + CGLM_INLINE mat4s glms_mat4_mulN(mat4s * __restrict matrices[], uint32_t len); + CGLM_INLINE vec4s glms_mat4_mulv(mat4s m, vec4s v); + CGLM_INLINE float glms_mat4_trace(mat4s m); + CGLM_INLINE float glms_mat4_trace3(mat4s m); + CGLM_INLINE versors glms_mat4_quat(mat4s m); + CGLM_INLINE vec3s glms_mat4_mulv3(mat4s m, vec3s v, float last); + CGLM_INLINE mat4s glms_mat4_transpose(mat4s m); + CGLM_INLINE mat4s glms_mat4_scale_p(mat4s m, float s); + CGLM_INLINE mat4s glms_mat4_scale(mat4s m, float s); + CGLM_INLINE float glms_mat4_det(mat4s mat); + CGLM_INLINE mat4s glms_mat4_inv(mat4s mat); + CGLM_INLINE mat4s glms_mat4_inv_fast(mat4s mat); + CGLM_INLINE mat4s glms_mat4_swap_col(mat4s mat, int col1, int col2); + CGLM_INLINE mat4s glms_mat4_swap_row(mat4s mat, int row1, int row2); + CGLM_INLINE float glms_mat4_rmc(vec4s r, mat4s m, vec4s c); + CGLM_INLINE mat4s glms_mat4_make(const float * __restrict src); + CGLM_INLINE mat4s glms_mat4_textrans(float sx, float sy, float rot, float tx, float ty); + */ + +#ifndef cglms_mat4s_h +#define cglms_mat4s_h + +#include "../common.h" +#include "../types-struct.h" +#include "../mat4.h" +#include "vec4.h" +#include "vec3.h" + +/* api definition */ +#define glms_mat4_(NAME) CGLM_STRUCTAPI(mat4, NAME) + +#define GLMS_MAT4_IDENTITY_INIT {GLM_MAT4_IDENTITY_INIT} +#define GLMS_MAT4_ZERO_INIT {GLM_MAT4_ZERO_INIT} + +/* for C only */ +#define GLMS_MAT4_IDENTITY ((mat4s)GLMS_MAT4_IDENTITY_INIT) +#define GLMS_MAT4_ZERO ((mat4s)GLMS_MAT4_ZERO_INIT) + +/*! + * @brief copy all members of [mat] to [dest] + * + * matrix may not be aligned, u stands for unaligned, this may be useful when + * copying a matrix from external source e.g. asset importer... + * + * @param[in] mat source + * @returns destination + */ +CGLM_INLINE +mat4s +glms_mat4_(ucopy)(mat4s mat) { + mat4s r; + glm_mat4_ucopy(mat.raw, r.raw); + return r; +} + +/*! + * @brief copy all members of [mat] to [dest] + * + * @param[in] mat source + * @returns destination + */ +CGLM_INLINE +mat4s +glms_mat4_(copy)(mat4s mat) { + mat4s r; + glm_mat4_copy(mat.raw, r.raw); + return r; +} + +/*! + * @brief make given matrix identity. It is identical with below, + * but it is more easy to do that with this func especially for members + * e.g. glm_mat4_identity(aStruct->aMatrix); + * + * @code + * glm_mat4_copy(GLM_MAT4_IDENTITY, mat); // C only + * + * // or + * mat4 mat = GLM_MAT4_IDENTITY_INIT; + * @endcode + * + * @returns destination + */ +CGLM_INLINE +mat4s +glms_mat4_(identity)(void) { + mat4s r; + glm_mat4_identity(r.raw); + return r; +} + +/*! + * @brief make given matrix array's each element identity matrix + * + * @param[in, out] mat matrix array (must be aligned (16/32) + * if alignment is not disabled) + * + * @param[in] count count of matrices + */ +CGLM_INLINE +void +glms_mat4_(identity_array)(mat4s * __restrict mat, size_t count) { + CGLM_ALIGN_MAT mat4s t = GLMS_MAT4_IDENTITY_INIT; + size_t i; + + for (i = 0; i < count; i++) { + glm_mat4_copy(t.raw, mat[i].raw); + } +} + +/*! + * @brief make given matrix zero. + * + * @returns matrix + */ +CGLM_INLINE +mat4s +glms_mat4_(zero)(void) { + mat4s r; + glm_mat4_zero(r.raw); + return r; +} + +/*! + * @brief copy upper-left of mat4 to mat3 + * + * @param[in] mat source + * @returns destination + */ +CGLM_INLINE +mat3s +glms_mat4_(pick3)(mat4s mat) { + mat3s r; + glm_mat4_pick3(mat.raw, r.raw); + return r; +} + +/*! + * @brief copy upper-left of mat4 to mat3 (transposed) + * + * the postfix t stands for transpose + * + * @param[in] mat source + * @returns destination + */ +CGLM_INLINE +mat3s +glms_mat4_(pick3t)(mat4s mat) { + mat3s r; + glm_mat4_pick3t(mat.raw, r.raw); + return r; +} + +/*! + * @brief copy mat3 to mat4's upper-left + * + * @param[in] mat source + * @param[in] dest destination + * @returns destination + */ +CGLM_INLINE +mat4s +glms_mat4_(ins3)(mat3s mat, mat4s dest) { + glm_mat4_ins3(mat.raw, dest.raw); + return dest; +} + +/*! + * @brief multiply m1 and m2 to dest + * + * m1, m2 and dest matrices can be same matrix, it is possible to write this: + * + * @code + * mat4 m = GLM_MAT4_IDENTITY_INIT; + * r = glms_mat4_mul(m, m); + * @endcode + * + * @param[in] m1 left matrix + * @param[in] m2 right matrix + * @returns destination matrix + */ +CGLM_INLINE +mat4s +glms_mat4_(mul)(mat4s m1, mat4s m2) { + mat4s r; + glm_mat4_mul(m1.raw, m2.raw, r.raw); + return r; +} + +/*! + * @brief mupliply N mat4 matrices and store result in dest + * + * this function lets you multiply multiple (more than two or more...) matrices + *

multiplication will be done in loop, this may reduce instructions + * size but if len is too small then compiler may unroll whole loop, + * usage: + * @code + * mat4 m1, m2, m3, m4, res; + * + * res = glm_mat4_mulN((mat4 *[]){&m1, &m2, &m3, &m4}, 4); + * @endcode + * + * @warning matrices parameter is pointer array not mat4 array! + * + * @param[in] matrices mat4 * array + * @param[in] len matrices count + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_mat4_(mulN)(mat4s * __restrict matrices[], uint32_t len) { + CGLM_ALIGN_MAT mat4s r = GLMS_MAT4_IDENTITY_INIT; + size_t i; + + for (i = 0; i < len; i++) { + r = glms_mat4_(mul)(r, *matrices[i]); + } + + return r; +} + +/*! + * @brief multiply mat4 with vec4 (column vector) and store in dest vector + * + * @param[in] m mat4 (left) + * @param[in] v vec4 (right, column vector) + * @returns vec4 (result, column vector) + */ +CGLM_INLINE +vec4s +glms_mat4_(mulv)(mat4s m, vec4s v) { + vec4s r; + glm_mat4_mulv(m.raw, v.raw, r.raw); + return r; +} + +/*! + * @brief trace of matrix + * + * sum of the elements on the main diagonal from upper left to the lower right + * + * @param[in] m matrix + */ +CGLM_INLINE +float +glms_mat4_(trace)(mat4s m) { + return glm_mat4_trace(m.raw); +} + +/*! + * @brief trace of matrix (rotation part) + * + * sum of the elements on the main diagonal from upper left to the lower right + * + * @param[in] m matrix + */ +CGLM_INLINE +float +glms_mat4_(trace3)(mat4s m) { + return glm_mat4_trace3(m.raw); +} + +/*! + * @brief convert mat4's rotation part to quaternion + * + * @param[in] m affine matrix + * @returns destination quaternion + */ +CGLM_INLINE +versors +glms_mat4_(quat)(mat4s m) { + versors r; + glm_mat4_quat(m.raw, r.raw); + return r; +} + +/*! + * @brief multiply vector with mat4 + * + * @param[in] m mat4(affine transform) + * @param[in] v vec3 + * @param[in] last 4th item to make it vec4 + * @returns result vector (vec3) + */ +CGLM_INLINE +vec3s +glms_mat4_(mulv3)(mat4s m, vec3s v, float last) { + vec3s r; + glm_mat4_mulv3(m.raw, v.raw, last, r.raw); + return r; +} + +/*! + * @brief transpose mat4 and store result in same matrix + * + * @param[in] m source + * @returns result + */ +CGLM_INLINE +mat4s +glms_mat4_(transpose)(mat4s m) { + glm_mat4_transpose(m.raw); + return m; +} + +/*! + * @brief scale (multiply with scalar) matrix without simd optimization + * + * multiply matrix with scalar + * + * @param[in] m matrix + * @param[in] s scalar + * @returns matrix + */ +CGLM_INLINE +mat4s +glms_mat4_(scale_p)(mat4s m, float s) { + glm_mat4_scale_p(m.raw, s); + return m; +} + +/*! + * @brief scale (multiply with scalar) matrix + * + * multiply matrix with scalar + * + * @param[in] m matrix + * @param[in] s scalar + * @returns matrix + */ +CGLM_INLINE +mat4s +glms_mat4_(scale)(mat4s m, float s) { + glm_mat4_scale(m.raw, s); + return m; +} + +/*! + * @brief mat4 determinant + * + * @param[in] mat matrix + * + * @return determinant + */ +CGLM_INLINE +float +glms_mat4_(det)(mat4s mat) { + return glm_mat4_det(mat.raw); +} + +/*! + * @brief inverse mat4 and store in dest + * + * @param[in] mat matrix + * @returns inverse matrix + */ +CGLM_INLINE +mat4s +glms_mat4_(inv)(mat4s mat) { + mat4s r; + glm_mat4_inv(mat.raw, r.raw); + return r; +} + +/*! + * @brief inverse mat4 and store in dest + * + * this func uses reciprocal approximation without extra corrections + * e.g Newton-Raphson. this should work faster than normal, + * to get more precise use glm_mat4_inv version. + * + * NOTE: You will lose precision, glm_mat4_inv is more accurate + * + * @param[in] mat matrix + * @returns inverse matrix + */ +CGLM_INLINE +mat4s +glms_mat4_(inv_fast)(mat4s mat) { + mat4s r; + glm_mat4_inv_fast(mat.raw, r.raw); + return r; +} + +/*! + * @brief swap two matrix columns + * + * @param[in] mat matrix + * @param[in] col1 col1 + * @param[in] col2 col2 + * @returns matrix + */ +CGLM_INLINE +mat4s +glms_mat4_(swap_col)(mat4s mat, int col1, int col2) { + glm_mat4_swap_col(mat.raw, col1, col2); + return mat; +} + +/*! + * @brief swap two matrix rows + * + * @param[in] mat matrix + * @param[in] row1 row1 + * @param[in] row2 row2 + * @returns matrix + */ +CGLM_INLINE +mat4s +glms_mat4_(swap_row)(mat4s mat, int row1, int row2) { + glm_mat4_swap_row(mat.raw, row1, row2); + return mat; +} + +/*! + * @brief helper for R (row vector) * M (matrix) * C (column vector) + * + * rmc stands for Row * Matrix * Column + * + * the result is scalar because R * M = Matrix1x4 (row vector), + * then Matrix1x4 * Vec4 (column vector) = Matrix1x1 (Scalar) + * + * @param[in] r row vector or matrix1x4 + * @param[in] m matrix4x4 + * @param[in] c column vector or matrix4x1 + * + * @return scalar value e.g. B(s) + */ +CGLM_INLINE +float +glms_mat4_(rmc)(vec4s r, mat4s m, vec4s c) { + return glm_mat4_rmc(r.raw, m.raw, c.raw); +} + +/*! + * @brief Create mat4 matrix from pointer + * + * @param[in] src pointer to an array of floats + * @return constructed matrix from raw pointer + */ +CGLM_INLINE +mat4s +glms_mat4_(make)(const float * __restrict src) { + mat4s r; + glm_mat4_make(src, r.raw); + return r; +} + +/*! + * @brief Create mat4 matrix from texture transform parameters + * + * @param[in] sx scale x + * @param[in] sy scale y + * @param[in] rot rotation in radians CCW/RH + * @param[in] tx translate x + * @param[in] ty translate y + * @return texture transform matrix + */ +CGLM_INLINE +mat4s +glms_mat4_(textrans)(float sx, float sy, float rot, float tx, float ty) { + mat4s r; + glm_mat4_textrans(sx, sy, rot, tx, ty, r.raw); + return r; +} + +#endif /* cglms_mat4s_h */ diff --git a/external/cglm/struct/mat4x2.h b/external/cglm/struct/mat4x2.h new file mode 100644 index 0000000..6c68abe --- /dev/null +++ b/external/cglm/struct/mat4x2.h @@ -0,0 +1,126 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_MAT4X2_ZERO_INIT + GLMS_MAT4X2_ZERO + + Functions: + CGLM_INLINE mat4x2s glms_mat4x2_zero(void); + CGLM_INLINE mat4x2s glms_mat4x2_make(const float * __restrict src); + CGLM_INLINE mat2s glms_mat4x2_mul(mat4x2s m1, mat2x4s m2); + CGLM_INLINE vec2s glms_mat4x2_mulv(mat4x2s m, vec4s v); + CGLM_INLINE mat2x4s glms_mat4x2_transpose(mat4x2s m); + CGLM_INLINE mat4x2s glms_mat4x2_scale(mat4x2s m, float s); + */ + +#ifndef cglms_mat4x2_h +#define cglms_mat4x2_h + +#include "../common.h" +#include "../types-struct.h" +#include "../mat4x2.h" + +/* api definition */ +#define glms_mat4x2_(NAME) CGLM_STRUCTAPI(mat4x2, NAME) + +#define GLMS_MAT4X2_ZERO_INIT {GLM_MAT4X2_ZERO_INIT} + +/* for C only */ +#define GLMS_MAT4X2_ZERO ((mat4x2s)GLMS_MAT4X2_ZERO_INIT) + + +/*! + * @brief Zero out the mat4x2s (dest). + * + * @return[out] dest constructed mat4x2s from raw pointer + */ +CGLM_INLINE +mat4x2s +glms_mat4x2_(zero)(void) { + mat4x2s dest; + glm_mat4x2_zero(dest.raw); + return dest; +} + +/*! + * @brief Create mat4x2s (dest) from pointer (src). + * + * @param[in] src pointer to an array of floats + * @return[out] dest constructed mat4x2s from raw pointer + */ +CGLM_INLINE +mat4x2s +glms_mat4x2_(make)(const float * __restrict src) { + mat4x2s dest; + glm_mat4x2_make(src, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat4x2s (m1) by mat2x4s (m2) and store in mat2s (dest). + * + * @code + * r = glms_mat4x2_mul(mat4x2s, mat2x4s); + * @endcode + * + * @param[in] m1 mat4x2s (left) + * @param[in] m2 mat2x4s (right) + * @return[out] dest constructed mat2s from raw pointers + */ +CGLM_INLINE +mat2s +glms_mat4x2_(mul)(mat4x2s m1, mat2x4s m2) { + mat2s dest; + glm_mat4x2_mul(m1.raw, m2.raw, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat4x2s (m) by vec4s (v) and store in vec2s (dest). + * + * @param[in] m mat4x2s (left) + * @param[in] v vec4s (right, column vector) + * @return[out] dest constructed vec2s from raw pointers + */ +CGLM_INLINE +vec2s +glms_mat4x2_(mulv)(mat4x2s m, vec4s v) { + vec2s dest; + glm_mat4x2_mulv(m.raw, v.raw, dest.raw); + return dest; +} + +/*! + * @brief Transpose mat4x2s (m) and store in mat2x4s (dest). + * + * @param[in] m mat4x2s (left) + * @return[out] dest constructed mat2x4s from raw pointers + */ +CGLM_INLINE +mat2x4s +glms_mat4x2_(transpose)(mat4x2s m) { + mat2x4s dest; + glm_mat4x2_transpose(m.raw, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat4x2s (m) by scalar constant (s). + * + * @param[in, out] m mat4x2s (src, dest) + * @param[in] s float (scalar) + */ +CGLM_INLINE +mat4x2s +glms_mat4x2_(scale)(mat4x2s m, float s) { + glm_mat4x2_scale(m.raw, s); + return m; +} + +#endif /* cglms_mat4x2_h */ diff --git a/external/cglm/struct/mat4x3.h b/external/cglm/struct/mat4x3.h new file mode 100644 index 0000000..b398f98 --- /dev/null +++ b/external/cglm/struct/mat4x3.h @@ -0,0 +1,125 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_MAT4X3_ZERO_INIT + GLMS_MAT4X3_ZERO + + Functions: + CGLM_INLINE mat4x3s glms_mat4x3_zero(void); + CGLM_INLINE mat4x3s glms_mat4x3_make(const float * __restrict src); + CGLM_INLINE mat3s glms_mat4x3_mul(mat4x3s m1, mat3x4s m2); + CGLM_INLINE vec3s glms_mat4x3_mulv(mat4x3s m, vec4s v); + CGLM_INLINE mat3x4s glms_mat4x3_transpose(mat4x3s m); + CGLM_INLINE mat4x3s glms_mat4x3_scale(mat4x3s m, float s); + */ + +#ifndef cglms_mat4x3_h +#define cglms_mat4x3_h + +#include "../common.h" +#include "../types-struct.h" +#include "../mat4x3.h" + +/* api definition */ +#define glms_mat4x3_(NAME) CGLM_STRUCTAPI(mat4x3, NAME) + +#define GLMS_MAT4X3_ZERO_INIT {GLM_MAT4X3_ZERO_INIT} + +/* for C only */ +#define GLMS_MAT4X3_ZERO ((mat4x3s)GLMS_MAT4X3_ZERO_INIT) + +/*! + * @brief Zero out the mat4x3s (dest). + * + * @return[out] dest constructed mat4x3s from raw pointer + */ +CGLM_INLINE +mat4x3s +glms_mat4x3_(zero)(void) { + mat4x3s dest; + glm_mat4x3_zero(dest.raw); + return dest; +} + +/*! + * @brief Create mat4x3s (dest) from pointer (src). + * + * @param[in] src pointer to an array of floats + * @return[out] dest constructed mat4x3s from raw pointer + */ +CGLM_INLINE +mat4x3s +glms_mat4x3_(make)(const float * __restrict src) { + mat4x3s dest; + glm_mat4x3_make(src, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat4x3s (m1) by mat3x4s (m2) and store in mat3s (dest). + * + * @code + * r = glms_mat4x3_mul(mat4x3s, mat3x4s); + * @endcode + * + * @param[in] m1 mat4x3s (left) + * @param[in] m2 mat3x4s (right) + * @return[out] dest constructed mat3s from raw pointers + */ +CGLM_INLINE +mat3s +glms_mat4x3_(mul)(mat4x3s m1, mat3x4s m2) { + mat3s dest; + glm_mat4x3_mul(m1.raw, m2.raw, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat4x3s (m) by vec4s (v) and store in vec3s (dest). + * + * @param[in] m mat4x3s (left) + * @param[in] v vec4s (right, column vector) + * @return[out] dest constructed vec3s from raw pointers + */ +CGLM_INLINE +vec3s +glms_mat4x3_(mulv)(mat4x3s m, vec4s v) { + vec3s dest; + glm_mat4x3_mulv(m.raw, v.raw, dest.raw); + return dest; +} + +/*! + * @brief Transpose mat4x3s (m) and store in mat3x4s (dest). + * + * @param[in] m mat4x3s (left) + * @return[out] dest constructed mat3x4s from raw pointers + */ +CGLM_INLINE +mat3x4s +glms_mat4x3_(transpose)(mat4x3s m) { + mat3x4s dest; + glm_mat4x3_transpose(m.raw, dest.raw); + return dest; +} + +/*! + * @brief Multiply mat4x3s (m) by scalar constant (s). + * + * @param[in, out] m mat4x3s (src, dest) + * @param[in] s float (scalar) + */ +CGLM_INLINE +mat4x3s +glms_mat4x3_(scale)(mat4x3s m, float s) { + glm_mat4x3_scale(m.raw, s); + return m; +} + +#endif /* cglms_mat4x3_h */ diff --git a/external/cglm/struct/noise.h b/external/cglm/struct/noise.h new file mode 100644 index 0000000..3fd7d2e --- /dev/null +++ b/external/cglm/struct/noise.h @@ -0,0 +1,57 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglms_noises_h +#define cglms_noises_h + +#include "../common.h" +#include "../types-struct.h" +#include "../noise.h" +#include "vec4.h" + +/* + Functions: + CGLM_INLINE float glms_perlin_vec4(vec4s point); + */ + +/*! + * @brief Classic perlin noise + * + * @param[in] point 4D vector + * @returns perlin noise value + */ +CGLM_INLINE +float +glms_perlin_vec4(vec4s point) { + return glm_perlin_vec4(point.raw); +} + +/*! + * @brief Classic perlin noise + * + * @param[in] point 3D vector + * @returns perlin noise value + */ +CGLM_INLINE +float +glms_perlin_vec3(vec3s point) { + return glm_perlin_vec3(point.raw); +} + +/*! + * @brief Classic perlin noise + * + * @param[in] point 2D vector + * @returns perlin noise value + */ +CGLM_INLINE +float +glms_perlin_vec2(vec2s point) { + return glm_perlin_vec2(point.raw); +} + +#endif /* cglms_noises_h */ diff --git a/external/cglm/struct/plane.h b/external/cglm/struct/plane.h new file mode 100644 index 0000000..6a84ac7 --- /dev/null +++ b/external/cglm/struct/plane.h @@ -0,0 +1,40 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglms_planes_h +#define cglms_planes_h + +#include "../common.h" +#include "../types-struct.h" +#include "../plane.h" +#include "vec4.h" + +/* + Plane equation: Ax + By + Cz + D = 0; + + It stored in vec4 as [A, B, C, D]. (A, B, C) is normal and D is distance +*/ + +/* + Functions: + CGLM_INLINE vec4s glms_plane_normalize(vec4s plane); + */ + +/*! + * @brief normalizes a plane + * + * @param[in] plane plane to normalize + * @returns normalized plane + */ +CGLM_INLINE +vec4s +glms_plane_normalize(vec4s plane) { + glm_plane_normalize(plane.raw); + return plane; +} + +#endif /* cglms_planes_h */ diff --git a/external/cglm/struct/project.h b/external/cglm/struct/project.h new file mode 100644 index 0000000..8383c77 --- /dev/null +++ b/external/cglm/struct/project.h @@ -0,0 +1,162 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglms_projects_h +#define cglms_projects_h + +#include "../common.h" +#include "../types-struct.h" +#include "../project.h" +#include "vec3.h" +#include "vec4.h" +#include "mat4.h" + +#ifndef CGLM_CLIPSPACE_INCLUDE_ALL +# if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT +# include "clipspace/project_zo.h" +# elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT +# include "clipspace/project_no.h" +# endif +#else +# include "clipspace/project_zo.h" +# include "clipspace/project_no.h" +#endif + +/*! + * @brief maps the specified viewport coordinates into specified space [1] + * the matrix should contain projection matrix. + * + * if you don't have ( and don't want to have ) an inverse matrix then use + * glm_unproject version. You may use existing inverse of matrix in somewhere + * else, this is why glm_unprojecti exists to save save inversion cost + * + * [1] space: + * 1- if m = invProj: View Space + * 2- if m = invViewProj: World Space + * 3- if m = invMVP: Object Space + * + * You probably want to map the coordinates into object space + * so use invMVP as m + * + * Computing viewProj: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * glm_mat4_inv(viewProj, invMVP); + * + * @param[in] pos point/position in viewport coordinates + * @param[in] invMat matrix (see brief) + * @param[in] vp viewport as [x, y, width, height] + * @returns unprojected coordinates + */ +CGLM_INLINE +vec3s +glms_unprojecti(vec3s pos, mat4s invMat, vec4s vp) { + vec3s r; + glm_unprojecti(pos.raw, invMat.raw, vp.raw, r.raw); + return r; +} + +/*! + * @brief maps the specified viewport coordinates into specified space [1] + * the matrix should contain projection matrix. + * + * this is same as glm_unprojecti except this function get inverse matrix for + * you. + * + * [1] space: + * 1- if m = proj: View Space + * 2- if m = viewProj: World Space + * 3- if m = MVP: Object Space + * + * You probably want to map the coordinates into object space + * so use MVP as m + * + * Computing viewProj and MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * or in struct api: + * MVP = mat4_mul(mat4_mul(proj, view), model) + * + * @param[in] pos point/position in viewport coordinates + * @param[in] m matrix (see brief) + * @param[in] vp viewport as [x, y, width, height] + * @returns unprojected coordinates + */ +CGLM_INLINE +vec3s +glms_unproject(vec3s pos, mat4s m, vec4s vp) { + vec3s r; + glm_unproject(pos.raw, m.raw, vp.raw, r.raw); + return r; +} + +/*! + * @brief map object coordinates to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * or in struct api: + * MVP = mat4_mul(mat4_mul(proj, view), model) + * + * @param[in] pos object coordinates + * @param[in] m MVP matrix + * @param[in] vp viewport as [x, y, width, height] + * @returns projected coordinates + */ +CGLM_INLINE +vec3s +glms_project(vec3s pos, mat4s m, vec4s vp) { + vec3s r; + glm_project(pos.raw, m.raw, vp.raw, r.raw); + return r; +} + +/*! + * @brief map object's z coordinate to window coordinates + * + * Computing MVP: + * glm_mat4_mul(proj, view, viewProj); + * glm_mat4_mul(viewProj, model, MVP); + * + * or in struct api: + * MVP = mat4_mul(mat4_mul(proj, view), model) + * + * @param[in] v object coordinates + * @param[in] m MVP matrix + * + * @returns projected z coordinate + */ +CGLM_INLINE +float +glms_project_z(vec3s v, mat4s m) { +#if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT + return glms_project_z_zo(v, m); +#elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT + return glms_project_z_no(v, m); +#endif +} + +/*! + * @brief define a picking region + * + * @param[in] center center [x, y] of a picking region in window coordinates + * @param[in] size size [width, height] of the picking region in window coordinates + * @param[in] vp viewport as [x, y, width, height] + * @returns projected coordinates + */ +CGLM_INLINE +mat4s +glms_pickmatrix(vec2s center, vec2s size, vec4s vp) { + mat4s res; + glm_pickmatrix(center.raw, size.raw, vp.raw, res.raw); + return res; +} + +#endif /* cglms_projects_h */ diff --git a/external/cglm/struct/quat.h b/external/cglm/struct/quat.h new file mode 100644 index 0000000..d6789e4 --- /dev/null +++ b/external/cglm/struct/quat.h @@ -0,0 +1,601 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_QUAT_IDENTITY_INIT + GLMS_QUAT_IDENTITY + + Functions: + CGLM_INLINE versors glms_quat_identity(void) + CGLM_INLINE void glms_quat_identity_array(versor *q, size_t count) + CGLM_INLINE versors glms_quat_init(float x, float y, float z, float w) + CGLM_INLINE versors glms_quatv(float angle, vec3s axis) + CGLM_INLINE versors glms_quat(float angle, float x, float y, float z) + CGLM_INLINE versors glms_quat_from_vecs(vec3s a, vec3s b) + CGLM_INLINE float glms_quat_norm(versors q) + CGLM_INLINE versors glms_quat_normalize(versors q) + CGLM_INLINE float glms_quat_dot(versors p, versors q) + CGLM_INLINE versors glms_quat_conjugate(versors q) + CGLM_INLINE versors glms_quat_inv(versors q) + CGLM_INLINE versors glms_quat_add(versors p, versors q) + CGLM_INLINE versors glms_quat_sub(versors p, versors q) + CGLM_INLINE vec3s glms_quat_imagn(versors q) + CGLM_INLINE float glms_quat_imaglen(versors q) + CGLM_INLINE float glms_quat_angle(versors q) + CGLM_INLINE vec3s glms_quat_axis(versors q) + CGLM_INLINE versors glms_quat_mul(versors p, versors q) + CGLM_INLINE mat4s glms_quat_mat4(versors q) + CGLM_INLINE mat4s glms_quat_mat4t(versors q) + CGLM_INLINE mat3s glms_quat_mat3(versors q) + CGLM_INLINE mat3s glms_quat_mat3t(versors q) + CGLM_INLINE versors glms_quat_lerp(versors from, versors to, float t) + CGLM_INLINE versors glms_quat_lerpc(versors from, versors to, float t) + CGLM_INLINE versors glms_quat_nlerp(versors from, versors to, float t) + CGLM_INLINE versors glms_quat_slerp(versors from, versors to, float t) + CGLM_INLINE versors glms_quat_slerp_longest(versors from, versors to, float t) + CGLM_INLINE mat4s. glms_quat_look(vec3s eye, versors ori) + CGLM_INLINE versors glms_quat_for(vec3s dir, vec3s fwd, vec3s up) + CGLM_INLINE versors glms_quat_forp(vec3s from, vec3s to, vec3s fwd, vec3s up) + CGLM_INLINE vec3s glms_quat_rotatev(versors q, vec3s v) + CGLM_INLINE mat4s glms_quat_rotate(mat4s m, versors q) + CGLM_INLINE mat4s glms_quat_rotate_at(mat4s m, versors q, vec3s pivot) + CGLM_INLINE mat4s glms_quat_rotate_atm(versors q, vec3s pivot) + CGLM_INLINE versors glms_quat_make(float * restrict src) + */ + +#ifndef cglms_quat_h +#define cglms_quat_h + +#include "../common.h" +#include "../types-struct.h" +#include "../plane.h" +#include "../quat.h" + +/* api definition */ +#define glms_quat_(NAME) CGLM_STRUCTAPI(quat, NAME) + +/* + * IMPORTANT: + * ---------------------------------------------------------------------------- + * cglm stores quat as [x, y, z, w] since v0.3.6 + * + * it was [w, x, y, z] before v0.3.6 it has been changed to [x, y, z, w] + * with v0.3.6 version. + * ---------------------------------------------------------------------------- + */ + +#define GLMS_QUAT_IDENTITY_INIT {GLM_QUAT_IDENTITY_INIT} +#define GLMS_QUAT_IDENTITY ((versors)GLMS_QUAT_IDENTITY_INIT) + +/*! + * @brief makes given quat to identity + * + * @returns identity quaternion + */ +CGLM_INLINE +versors +glms_quat_(identity)(void) { + versors dest; + glm_quat_identity(dest.raw); + return dest; +} + +/*! + * @brief make given quaternion array's each element identity quaternion + * + * @param[in, out] q quat array (must be aligned (16) + * if alignment is not disabled) + * + * @param[in] count count of quaternions + */ +CGLM_INLINE +void +glms_quat_(identity_array)(versors * __restrict q, size_t count) { + CGLM_ALIGN(16) versor v = GLM_QUAT_IDENTITY_INIT; + size_t i; + + for (i = 0; i < count; i++) { + glm_vec4_copy(v, q[i].raw); + } +} + +/*! + * @brief inits quaternion with raw values + * + * @param[in] x x + * @param[in] y y + * @param[in] z z + * @param[in] w w (real part) + * @returns quaternion + */ +CGLM_INLINE +versors +glms_quat_(init)(float x, float y, float z, float w) { + versors dest; + glm_quat_init(dest.raw, x, y, z, w); + return dest; +} + +/*! + * @brief creates NEW quaternion with axis vector + * + * @param[in] angle angle (radians) + * @param[in] axis axis + * @returns quaternion + */ +CGLM_INLINE +versors +glms_quatv(float angle, vec3s axis) { + versors dest; + glm_quatv(dest.raw, angle, axis.raw); + return dest; +} + +/*! + * @brief creates NEW quaternion with individual axis components + * + * @param[in] angle angle (radians) + * @param[in] x axis.x + * @param[in] y axis.y + * @param[in] z axis.z + * @returns quaternion + */ +CGLM_INLINE +versors +glms_quat(float angle, float x, float y, float z) { + versors dest; + glm_quat(dest.raw, angle, x, y, z); + return dest; +} + +/*! + * @brief compute quaternion rotating vector A to vector B + * + * @param[in] a vec3 (must have unit length) + * @param[in] b vec3 (must have unit length) + * @returns quaternion (of unit length) + */ +CGLM_INLINE +versors +glms_quat_(from_vecs)(vec3s a, vec3s b) { + versors dest; + glm_quat_from_vecs(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief returns norm (magnitude) of quaternion + * + * @param[in] q quaternion + */ +CGLM_INLINE +float +glms_quat_(norm)(versors q) { + return glm_quat_norm(q.raw); +} + +/*! + * @brief normalize quaternion + * + * @param[in] q quaternion + * @returns quaternion + */ +CGLM_INLINE +versors +glms_quat_(normalize)(versors q) { + versors dest; + glm_quat_normalize_to(q.raw, dest.raw); + return dest; +} + +/*! + * @brief dot product of two quaternion + * + * @param[in] p quaternion 1 + * @param[in] q quaternion 2 + * @returns dot product + */ +CGLM_INLINE +float +glms_quat_(dot)(versors p, versors q) { + return glm_quat_dot(p.raw, q.raw); +} + +/*! + * @brief conjugate of quaternion + * + * @param[in] q quaternion + * @returns conjugate + */ +CGLM_INLINE +versors +glms_quat_(conjugate)(versors q) { + versors dest; + glm_quat_conjugate(q.raw, dest.raw); + return dest; +} + +/*! + * @brief inverse of non-zero quaternion + * + * @param[in] q quaternion + * @returns inverse quaternion + */ +CGLM_INLINE +versors +glms_quat_(inv)(versors q) { + versors dest; + glm_quat_inv(q.raw, dest.raw); + return dest; +} + +/*! + * @brief add (componentwise) two quaternions and store result in dest + * + * @param[in] p quaternion 1 + * @param[in] q quaternion 2 + * @returns result quaternion + */ +CGLM_INLINE +versors +glms_quat_(add)(versors p, versors q) { + versors dest; + glm_quat_add(p.raw, q.raw, dest.raw); + return dest; +} + +/*! + * @brief subtract (componentwise) two quaternions and store result in dest + * + * @param[in] p quaternion 1 + * @param[in] q quaternion 2 + * @returns result quaternion + */ +CGLM_INLINE +versors +glms_quat_(sub)(versors p, versors q) { + versors dest; + glm_quat_sub(p.raw, q.raw, dest.raw); + return dest; +} + +/*! + * @brief returns normalized imaginary part of quaternion + * + * @param[in] q quaternion + */ +CGLM_INLINE +vec3s +glms_quat_(imagn)(versors q) { + vec3s dest; + glm_normalize_to(q.raw, dest.raw); + return dest; +} + +/*! + * @brief returns length of imaginary part of quaternion + * + * @param[in] q quaternion + */ +CGLM_INLINE +float +glms_quat_(imaglen)(versors q) { + return glm_quat_imaglen(q.raw); +} + +/*! + * @brief returns angle of quaternion + * + * @param[in] q quaternion + */ +CGLM_INLINE +float +glms_quat_(angle)(versors q) { + return glm_quat_angle(q.raw); +} + +/*! + * @brief axis of quaternion + * + * @param[in] q quaternion + * @returns axis of quaternion + */ +CGLM_INLINE +vec3s +glms_quat_(axis)(versors q) { + vec3s dest; + glm_quat_axis(q.raw, dest.raw); + return dest; +} + +/*! + * @brief multiplies two quaternion and stores result in dest + * this is also called Hamilton Product + * + * According to WikiPedia: + * The product of two rotation quaternions [clarification needed] will be + * equivalent to the rotation q followed by the rotation p + * + * @param[in] p quaternion 1 + * @param[in] q quaternion 2 + * @returns result quaternion + */ +CGLM_INLINE +versors +glms_quat_(mul)(versors p, versors q) { + versors dest; + glm_quat_mul(p.raw, q.raw, dest.raw); + return dest; +} + +/*! + * @brief convert quaternion to mat4 + * + * @param[in] q quaternion + * @returns result matrix + */ +CGLM_INLINE +mat4s +glms_quat_(mat4)(versors q) { + mat4s dest; + glm_quat_mat4(q.raw, dest.raw); + return dest; +} + +/*! + * @brief convert quaternion to mat4 (transposed) + * + * @param[in] q quaternion + * @returns result matrix as transposed + */ +CGLM_INLINE +mat4s +glms_quat_(mat4t)(versors q) { + mat4s dest; + glm_quat_mat4t(q.raw, dest.raw); + return dest; +} + +/*! + * @brief convert quaternion to mat3 + * + * @param[in] q quaternion + * @returns result matrix + */ +CGLM_INLINE +mat3s +glms_quat_(mat3)(versors q) { + mat3s dest; + glm_quat_mat3(q.raw, dest.raw); + return dest; +} + +/*! + * @brief convert quaternion to mat3 (transposed) + * + * @param[in] q quaternion + * @returns result matrix + */ +CGLM_INLINE +mat3s +glms_quat_(mat3t)(versors q) { + mat3s dest; + glm_quat_mat3t(q.raw, dest.raw); + return dest; +} + +/*! + * @brief interpolates between two quaternions + * using linear interpolation (LERP) + * + * @param[in] from from + * @param[in] to to + * @param[in] t interpolant (amount) + * @returns result quaternion + */ +CGLM_INLINE +versors +glms_quat_(lerp)(versors from, versors to, float t) { + versors dest; + glm_quat_lerp(from.raw, to.raw, t, dest.raw); + return dest; +} + +/*! + * @brief interpolates between two quaternions + * using linear interpolation (LERP) + * + * @param[in] from from + * @param[in] to to + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @returns result quaternion + */ +CGLM_INLINE +versors +glms_quat_(lerpc)(versors from, versors to, float t) { + versors dest; + glm_quat_lerpc(from.raw, to.raw, t, dest.raw); + return dest; +} + +/*! + * @brief interpolates between two quaternions + * taking the shortest rotation path using + * normalized linear interpolation (NLERP) + * + * @param[in] from from + * @param[in] to to + * @param[in] t interpolant (amount) + * @returns result quaternion + */ +CGLM_INLINE +versors +glms_quat_(nlerp)(versors from, versors to, float t) { + versors dest; + glm_quat_nlerp(from.raw, to.raw, t, dest.raw); + return dest; +} + +/*! + * @brief interpolates between two quaternions + * using spherical linear interpolation (SLERP) + * + * @param[in] from from + * @param[in] to to + * @param[in] t amount + * @returns result quaternion + */ +CGLM_INLINE +versors +glms_quat_(slerp)(versors from, versors to, float t) { + versors dest; + glm_quat_slerp(from.raw, to.raw, t, dest.raw); + return dest; +} + +/*! + * @brief interpolates between two quaternions + * using spherical linear interpolation (SLERP) and always takes the longest path + * + * @param[in] from from + * @param[in] to to + * @param[in] t amount + * @returns result quaternion + */ +CGLM_INLINE +versors +glms_quat_(slerp_longest)(versors from, versors to, float t) { + versors dest; + glm_quat_slerp_longest(from.raw, to.raw, t, dest.raw); + return dest; +} + +/*! + * @brief creates view matrix using quaternion as camera orientation + * + * @param[in] eye eye + * @param[in] ori orientation in world space as quaternion + * @returns view matrix + */ +CGLM_INLINE +mat4s +glms_quat_(look)(vec3s eye, versors ori) { + mat4s dest; + glm_quat_look(eye.raw, ori.raw, dest.raw); + return dest; +} + +/*! + * @brief creates look rotation quaternion + * + * @param[in] dir direction to look + * @param[in] up up vector + * @returns destination quaternion + */ +CGLM_INLINE +versors +glms_quat_(for)(vec3s dir, vec3s up) { + versors dest; + glm_quat_for(dir.raw, up.raw, dest.raw); + return dest; +} + +/*! + * @brief creates look rotation quaternion using source and + * destination positions p suffix stands for position + * + * @param[in] from source point + * @param[in] to destination point + * @param[in] up up vector + * @returns destination quaternion + */ +CGLM_INLINE +versors +glms_quat_(forp)(vec3s from, vec3s to, vec3s up) { + versors dest; + glm_quat_forp(from.raw, to.raw, up.raw, dest.raw); + return dest; +} + +/*! + * @brief rotate vector using using quaternion + * + * @param[in] q quaternion + * @param[in] v vector to rotate + * @returns rotated vector + */ +CGLM_INLINE +vec3s +glms_quat_(rotatev)(versors q, vec3s v) { + vec3s dest; + glm_quat_rotatev(q.raw, v.raw, dest.raw); + return dest; +} + +/*! + * @brief rotate existing transform matrix using quaternion + * + * @param[in] m existing transform matrix + * @param[in] q quaternion + * @returns rotated matrix/transform + */ +CGLM_INLINE +mat4s +glms_quat_(rotate)(mat4s m, versors q) { + glm_quat_rotate(m.raw, q.raw, m.raw); + return m; +} + +/*! + * @brief rotate existing transform matrix using quaternion at pivot point + * + * @param[in, out] m existing transform matrix + * @param[in] q quaternion + * @returns pivot + */ +CGLM_INLINE +mat4s +glms_quat_(rotate_at)(mat4s m, versors q, vec3s pivot) { + glm_quat_rotate_at(m.raw, q.raw, pivot.raw); + return m; +} + +/*! + * @brief rotate NEW transform matrix using quaternion at pivot point + * + * this creates rotation matrix, it assumes you don't have a matrix + * + * this should work faster than glm_quat_rotate_at because it reduces + * one glm_translate. + * + * @param[in] q quaternion + * @returns pivot + */ +CGLM_INLINE +mat4s +glms_quat_(rotate_atm)(versors q, vec3s pivot) { + mat4s dest; + glm_quat_rotate_atm(dest.raw, q.raw, pivot.raw); + return dest; +} + +/*! + * @brief Create CGLM quaternion from pointer + * + * @param[in] src pointer to an array of floats + * @returns constructed quaternion from raw pointer + */ +CGLM_INLINE +versors +glms_quat_(make)(const float * __restrict src) { + versors dest; + glm_quat_make(src, dest.raw); + return dest; +} + +#endif /* cglms_quat_h */ diff --git a/external/cglm/struct/ray.h b/external/cglm/struct/ray.h new file mode 100644 index 0000000..10609b9 --- /dev/null +++ b/external/cglm/struct/ray.h @@ -0,0 +1,86 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglms_ray_h +#define cglms_ray_h + +#include "../common.h" +#include "../types-struct.h" +#include "../ray.h" + +/* api definition */ +#define glms_ray_(NAME) CGLM_STRUCTAPI(ray, NAME) + +/*! + * @brief Möller–Trumbore ray-triangle intersection algorithm + * + * @param[in] origin origin of ray + * @param[in] direction direction of ray + * @param[in] v0 first vertex of triangle + * @param[in] v1 second vertex of triangle + * @param[in] v2 third vertex of triangle + * @param[in, out] d distance to intersection + * @return whether there is intersection + */ +CGLM_INLINE +bool +glms_ray_(triangle)(vec3s origin, + vec3s direction, + vec3s v0, + vec3s v1, + vec3s v2, + float *d) { + return glm_ray_triangle(origin.raw, direction.raw, v0.raw, v1.raw, v2.raw, d); +} + +/*! + * @brief ray sphere intersection + * + * returns false if there is no intersection if true: + * + * - t1 > 0, t2 > 0: ray intersects the sphere at t1 and t2 both ahead of the origin + * - t1 < 0, t2 > 0: ray starts inside the sphere, exits at t2 + * - t1 < 0, t2 < 0: no intersection ahead of the ray ( returns false ) + * - the caller can check if the intersection points (t1 and t2) fall within a + * specific range (for example, tmin < t1, t2 < tmax) to determine if the + * intersections are within a desired segment of the ray + * + * @param[in] origin ray origin + * @param[out] dir normalized ray direction + * @param[in] s sphere [center.x, center.y, center.z, radii] + * @param[in] t1 near point1 (closer to origin) + * @param[in] t2 far point2 (farther from origin) + * + * @returns whether there is intersection + */ +CGLM_INLINE +bool +glms_ray_(sphere)(vec3s origin, + vec3s dir, + vec4s s, + float * __restrict t1, + float * __restrict t2) { + return glm_ray_sphere(origin.raw, dir.raw, s.raw, t1, t2); +} + +/*! + * @brief point using t by 𝐏(𝑡)=𝐀+𝑡𝐛 + * + * @param[in] orig origin of ray + * @param[in] dir direction of ray + * @param[in] t parameter + * @returns point point at t + */ +CGLM_INLINE +vec3s +glms_ray_(at)(vec3s orig, vec3s dir, float t) { + vec3s r; + glm_ray_at(orig.raw, dir.raw, t, r.raw); + return r; +} + +#endif /* cglms_ray_h */ diff --git a/external/cglm/struct/sphere.h b/external/cglm/struct/sphere.h new file mode 100644 index 0000000..9859c72 --- /dev/null +++ b/external/cglm/struct/sphere.h @@ -0,0 +1,93 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglms_spheres_h +#define cglms_spheres_h + +#include "../common.h" +#include "../types-struct.h" +#include "../sphere.h" +#include "mat4.h" + +/* + Sphere Representation in cglm: [center.x, center.y, center.z, radii] + + You could use this representation or you can convert it to vec4 before call + any function + */ + +/*! + * @brief helper for getting sphere radius + * + * @param[in] s sphere + * + * @return returns radii + */ +CGLM_INLINE +float +glms_sphere_radii(vec4s s) { + return glm_sphere_radii(s.raw); +} + +/*! + * @brief apply transform to sphere, it is just wrapper for glm_mat4_mulv3 + * + * @param[in] s sphere + * @param[in] m transform matrix + * @returns transformed sphere + */ +CGLM_INLINE +vec4s +glms_sphere_transform(vec4s s, mat4s m) { + vec4s r; + glm_sphere_transform(s.raw, m.raw, r.raw); + return r; +} + +/*! + * @brief merges two spheres and creates a new one + * + * two sphere must be in same space, for instance if one in world space then + * the other must be in world space too, not in local space. + * + * @param[in] s1 sphere 1 + * @param[in] s2 sphere 2 + * returns merged/extended sphere + */ +CGLM_INLINE +vec4s +glms_sphere_merge(vec4s s1, vec4s s2) { + vec4s r; + glm_sphere_merge(s1.raw, s2.raw, r.raw); + return r; +} + +/*! + * @brief check if two sphere intersects + * + * @param[in] s1 sphere + * @param[in] s2 other sphere + */ +CGLM_INLINE +bool +glms_sphere_sphere(vec4s s1, vec4s s2) { + return glm_sphere_sphere(s1.raw, s2.raw); +} + +/*! + * @brief check if sphere intersects with point + * + * @param[in] s sphere + * @param[in] point point + */ +CGLM_INLINE +bool +glms_sphere_point(vec4s s, vec3s point) { + return glm_sphere_point(s.raw, point.raw); +} + +#endif /* cglms_spheres_h */ diff --git a/external/cglm/struct/vec2-ext.h b/external/cglm/struct/vec2-ext.h new file mode 100644 index 0000000..246132f --- /dev/null +++ b/external/cglm/struct/vec2-ext.h @@ -0,0 +1,337 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/*! + * @brief SIMD like functions + */ + +/* + Functions: + CGLM_INLINE vec2s glms_vec2_fill(float val) + CGLM_INLINE bool glms_vec2_eq(vec2s v, float val) + CGLM_INLINE bool glms_vec2_eq_eps(vec2s v, float val) + CGLM_INLINE bool glms_vec2_eq_all(vec2s v) + CGLM_INLINE bool glms_vec2_eqv(vec2s a, vec2s b) + CGLM_INLINE bool glms_vec2_eqv_eps(vec2s a, vec2s b) + CGLM_INLINE float glms_vec2_max(vec2s v) + CGLM_INLINE float glms_vec2_min(vec2s v) + CGLM_INLINE bool glms_vec2_isnan(vec2s v) + CGLM_INLINE bool glms_vec2_isinf(vec2s v) + CGLM_INLINE bool glms_vec2_isvalid(vec2s v) + CGLM_INLINE vec2s glms_vec2_sign(vec2s v) + CGLM_INLINE vec2s glms_vec2_abs(vec2s v) + CGLM_INLINE vec2s glms_vec2_fract(vec2s v) + CGLM_INLINE vec2s glms_vec2_floor(vec2s v) + CGLM_INLINE vec2s glms_vec2_mods(vec2s v, float s) + CGLM_INLINE vec2s glms_vec2_steps(float edge, vec2s v) + CGLM_INLINE vec2s glms_vec2_stepr(vec2s edge, float v) + CGLM_INLINE vec2s glms_vec2_sqrt(vec2s v) + */ + +#ifndef cglms_vec2s_ext_h +#define cglms_vec2s_ext_h + +#include "../common.h" +#include "../types-struct.h" +#include "../util.h" +#include "../vec2-ext.h" + +/* api definition */ +#define glms_vec2_(NAME) CGLM_STRUCTAPI(vec2, NAME) + +/*! + * @brief fill a vector with specified value + * + * @param[in] val value + * @returns dest + */ +CGLM_INLINE +vec2s +glms_vec2_(fill)(float val) { + vec2s r; + glm_vec2_fill(r.raw, val); + return r; +} + +/*! + * @brief check if vector is equal to value (without epsilon) + * + * @param[in] v vector + * @param[in] val value + */ +CGLM_INLINE +bool +glms_vec2_(eq)(vec2s v, float val) { + return glm_vec2_eq(v.raw, val); +} + +/*! + * @brief check if vector is equal to value (with epsilon) + * + * @param[in] v vector + * @param[in] val value + */ +CGLM_INLINE +bool +glms_vec2_(eq_eps)(vec2s v, float val) { + return glm_vec2_eq_eps(v.raw, val); +} + +/*! + * @brief check if vector members are equal (without epsilon) + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec2_(eq_all)(vec2s v) { + return glm_vec2_eq_all(v.raw); +} + +/*! + * @brief check if vector is equal to another (without epsilon) + * + * @param[in] a vector + * @param[in] b vector + */ +CGLM_INLINE +bool +glms_vec2_(eqv)(vec2s a, vec2s b) { + return glm_vec2_eqv(a.raw, b.raw); +} + +/*! + * @brief check if vector is equal to another (with epsilon) + * + * @param[in] a vector + * @param[in] b vector + */ +CGLM_INLINE +bool +glms_vec2_(eqv_eps)(vec2s a, vec2s b) { + return glm_vec2_eqv_eps(a.raw, b.raw); +} + +/*! + * @brief max value of vector + * + * @param[in] v vector + */ +CGLM_INLINE +float +glms_vec2_(max)(vec2s v) { + return glm_vec2_max(v.raw); +} + +/*! + * @brief min value of vector + * + * @param[in] v vector + */ +CGLM_INLINE +float +glms_vec2_min(vec2s v) { + return glm_vec2_min(v.raw); +} + +/*! + * @brief check if one of items is NaN (not a number) + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec2_(isnan)(vec2s v) { + return glm_vec2_isnan(v.raw); +} + +/*! + * @brief check if one of items is INFINITY + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec2_(isinf)(vec2s v) { + return glm_vec2_isinf(v.raw); +} + +/*! + * @brief check if all items are valid number + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec2_isvalid(vec2s v) { + return glm_vec2_isvalid(v.raw); +} + +/*! + * @brief get sign of 32 bit float as +1, -1, 0 + * + * Important: It returns 0 for zero/NaN input + * + * @param v vector + * @returns sign vector + */ +CGLM_INLINE +vec2s +glms_vec2_(sign)(vec2s v) { + vec2s r; + glm_vec2_sign(v.raw, r.raw); + return r; +} + +/*! + * @brief fractional part of each vector item + * + * @param v vector + * @returns abs vector + */ +CGLM_INLINE +vec2s +glms_vec2_(abs)(vec2s v) { + vec2s r; + glm_vec2_abs(v.raw, r.raw); + return r; +} + +/*! + * @brief fractional part of each vector item + * + * @param[in] v vector + * @returns destination vector + */ +CGLM_INLINE +vec2s +glms_vec2_(fract)(vec2s v) { + vec2s r; + glm_vec2_fract(v.raw, r.raw); + return r; +} + +/*! + * @brief floor of each vector item + * + * @param[in] v vector + * @returns destination vector + */ +CGLM_INLINE +vec2s +glms_vec2_(floor)(vec2s v) { + vec2s r; + glm_vec2_floor(v.raw, r.raw); + return r; +} + +/*! + * @brief mod of each vector item by scalar + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec2s +glms_vec2_(mods)(vec2s v, float s) { + vec2s r; + glm_vec2_mods(v.raw, s, r.raw); + return r; +} + +/*! + * @brief threshold each vector item with scalar + * condition is: (x[i] < edge) ? 0.0 : 1.0 + * + * @param[in] edge threshold + * @param[in] x vector to test against threshold + * @returns destination + */ +CGLM_INLINE +vec2s +glms_vec2_(steps)(float edge, vec2s x) { + vec2s r; + glm_vec2_steps(edge, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold a value with *vector* as the threshold + * condition is: (x < edge[i]) ? 0.0 : 1.0 + * + * @param[in] edge threshold vector + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec2s +glms_vec2_(stepr)(vec2s edge, float x) { + vec2s r; + glm_vec2_stepr(edge.raw, x, r.raw); + return r; +} + +/*! + * @brief square root of each vector item + * + * @param[in] v vector + * @returns destination vector + */ +CGLM_INLINE +vec2s +glms_vec2_(sqrt)(vec2s v) { + vec2s r; + glm_vec2_sqrt(v.raw, r.raw); + return r; +} + +/*! + * @brief treat vectors as complex numbers and multiply them as such. + * + * @param[in] a left number + * @param[in] b right number + * @param[out] dest destination number + */ +CGLM_INLINE +vec2s +glms_vec2_(complex_mul)(vec2s a, vec2s b, vec2s dest) { + glm_vec2_complex_mul(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief treat vectors as complex numbers and divide them as such. + * + * @param[in] a left number (numerator) + * @param[in] b right number (denominator) + * @param[out] dest destination number + */ +CGLM_INLINE +vec2s +glms_vec2_(complex_div)(vec2s a, vec2s b, vec2s dest) { + glm_vec2_complex_div(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief treat the vector as a complex number and conjugate it as such. + * + * @param[in] a the number + * @param[out] dest destination number + */ +CGLM_INLINE +vec2s +glms_vec2_(complex_conjugate)(vec2s a, vec2s dest) { + glm_vec2_complex_conjugate(a.raw, dest.raw); + return dest; +} + +#endif /* cglms_vec2s_ext_h */ diff --git a/external/cglm/struct/vec2.h b/external/cglm/struct/vec2.h new file mode 100644 index 0000000..40ed659 --- /dev/null +++ b/external/cglm/struct/vec2.h @@ -0,0 +1,747 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_VEC2_ONE_INIT + GLMS_VEC2_ZERO_INIT + GLMS_VEC2_ONE + GLMS_VEC2_ZERO + + Functions: + CGLM_INLINE vec2s glms_vec2(vec3s v3) + CGLM_INLINE void glms_vec2_pack(vec2s dst[], vec2 src[], size_t len) + CGLM_INLINE void glms_vec2_unpack(vec2 dst[], vec2s src[], size_t len) + CGLM_INLINE vec2s glms_vec2_zero(void) + CGLM_INLINE vec2s glms_vec2_one(void) + CGLM_INLINE float glms_vec2_dot(vec2s a, vec2s b) + CGLM_INLINE float glms_vec2_cross(vec2s a, vec2s b) + CGLM_INLINE float glms_vec2_norm2(vec2s v) + CGLM_INLINE float glms_vec2_norm(vec2s v) + CGLM_INLINE vec2s glms_vec2_add(vec2s a, vec2s b) + CGLM_INLINE vec2s glms_vec2_adds(vec2s a, float s) + CGLM_INLINE vec2s glms_vec2_sub(vec2s a, vec2s b) + CGLM_INLINE vec2s glms_vec2_subs(vec2s a, float s) + CGLM_INLINE vec2s glms_vec2_mul(vec2s a, vec2s b) + CGLM_INLINE vec2s glms_vec2_scale(vec2s v, float s) + CGLM_INLINE vec2s glms_vec2_scale_as(vec2s v, float s) + CGLM_INLINE vec2s glms_vec2_div(vec2s a, vec2s b) + CGLM_INLINE vec2s glms_vec2_divs(vec2s a, float s) + CGLM_INLINE vec2s glms_vec2_addadd(vec2s a, vec2s b, vec2s dest) + CGLM_INLINE vec2s glms_vec2_subadd(vec2s a, vec2s b, vec2s dest) + CGLM_INLINE vec2s glms_vec2_muladd(vec2s a, vec2s b, vec2s dest) + CGLM_INLINE vec2s glms_vec2_muladds(vec2s a, float s, vec2s dest) + CGLM_INLINE vec2s glms_vec2_maxadd(vec2s a, vec2s b, vec2s dest) + CGLM_INLINE vec2s glms_vec2_minadd(vec2s a, vec2s b, vec2s dest) + CGLM_INLINE vec2s glms_vec2_subsub(vec2s a, vec2s b, vec2s dest) + CGLM_INLINE vec2s glms_vec2_addsub(vec2s a, vec2s b, vec2s dest) + CGLM_INLINE vec2s glms_vec2_mulsub(vec2s a, vec2s b, vec2s dest) + CGLM_INLINE vec2s glms_vec2_mulsubs(vec2s a, float s, vec2s dest) + CGLM_INLINE vec2s glms_vec2_maxsub(vec2s a, vec2s b, vec2s dest) + CGLM_INLINE vec2s glms_vec2_minsub(vec2s a, vec2s b, vec2s dest) + CGLM_INLINE vec2s glms_vec2_negate(vec2s v) + CGLM_INLINE vec2s glms_vec2_normalize(vec2s v) + CGLM_INLINE vec2s glms_vec2_rotate(vec2s v, float angle, vec2s axis) + CGLM_INLINE vec2s glms_vec2_center(vec2s a, vec2s b) + CGLM_INLINE float glms_vec2_distance(vec2s a, vec2s b) + CGLM_INLINE float glms_vec2_distance2(vec2s a, vec2s b) + CGLM_INLINE vec2s glms_vec2_maxv(vec2s a, vec2s b) + CGLM_INLINE vec2s glms_vec2_minv(vec2s a, vec2s b) + CGLM_INLINE vec2s glms_vec2_clamp(vec2s v, float minVal, float maxVal) + CGLM_INLINE vec2s glms_vec2_lerp(vec2s from, vec2s to, float t) + CGLM_INLINE vec2s glms_vec2_step(vec2s edge, vec2s x) + CGLM_INLINE vec2s glms_vec2_make(float * restrict src) + CGLM_INLINE vec2s glms_vec2_reflect(vec2s v, vec2s n) + CGLM_INLINE bool glms_vec2_refract(vec2s v, vec2s n, float eta, vec2s *dest) + */ + +#ifndef cglms_vec2s_h +#define cglms_vec2s_h + +#include "../common.h" +#include "../types-struct.h" +#include "../util.h" +#include "../vec2.h" +#include "vec2-ext.h" + +#define GLMS_VEC2_ONE_INIT {GLM_VEC2_ONE_INIT} +#define GLMS_VEC2_ZERO_INIT {GLM_VEC2_ZERO_INIT} + +#define GLMS_VEC2_ONE ((vec2s)GLMS_VEC2_ONE_INIT) +#define GLMS_VEC2_ZERO ((vec2s)GLMS_VEC2_ZERO_INIT) + +/*! + * @brief init vec2 using vec2 + * + * @param[in] v3 vector3 + * @returns destination + */ +CGLM_INLINE +vec2s +glms_vec2(vec3s v3) { + vec2s r; + glm_vec2(v3.raw, r.raw); + return r; +} + +/*! + * @brief pack an array of vec2 into an array of vec2s + * + * @param[out] dst array of vec2 + * @param[in] src array of vec2s + * @param[in] len number of elements + */ +CGLM_INLINE +void +glms_vec2_(pack)(vec2s dst[], vec2 src[], size_t len) { + size_t i; + + for (i = 0; i < len; i++) { + glm_vec2_copy(src[i], dst[i].raw); + } +} + +/*! + * @brief unpack an array of vec2s into an array of vec2 + * + * @param[out] dst array of vec2s + * @param[in] src array of vec2 + * @param[in] len number of elements + */ +CGLM_INLINE +void +glms_vec2_(unpack)(vec2 dst[], vec2s src[], size_t len) { + size_t i; + + for (i = 0; i < len; i++) { + glm_vec2_copy(src[i].raw, dst[i]); + } +} + +/*! + * @brief make vector zero + * + * @returns zero vector + */ +CGLM_INLINE +vec2s +glms_vec2_(zero)(void) { + vec2s r; + glm_vec2_zero(r.raw); + return r; +} + +/*! + * @brief make vector one + * + * @returns one vector + */ +CGLM_INLINE +vec2s +glms_vec2_(one)(void) { + vec2s r; + glm_vec2_one(r.raw); + return r; +} + +/*! + * @brief vec2 dot product + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return dot product + */ +CGLM_INLINE +float +glms_vec2_(dot)(vec2s a, vec2s b) { + return glm_vec2_dot(a.raw, b.raw); +} + +/*! + * @brief vec2 cross product + * + * REF: http://allenchou.net/2013/07/cross-product-of-2d-vectors/ + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return Z component of cross product + */ +CGLM_INLINE +float +glms_vec2_(cross)(vec2s a, vec2s b) { + return glm_vec2_cross(a.raw, b.raw); +} + +/*! + * @brief norm * norm (magnitude) of vec + * + * we can use this func instead of calling norm * norm, because it would call + * sqrtf function twice but with this func we can avoid func call, maybe this is + * not good name for this func + * + * @param[in] v vector + * + * @return norm * norm + */ +CGLM_INLINE +float +glms_vec2_(norm2)(vec2s v) { + return glm_vec2_norm2(v.raw); +} + +/*! + * @brief norm (magnitude) of vec2 + * + * @param[in] v vector + * + * @return norm + */ +CGLM_INLINE +float +glms_vec2_(norm)(vec2s v) { + return glm_vec2_norm(v.raw); +} + +/*! + * @brief add a vector to b vector store result in dest + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns destination vector + */ +CGLM_INLINE +vec2s +glms_vec2_(add)(vec2s a, vec2s b) { + vec2s r; + glm_vec2_add(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief add scalar to v vector store result in dest (d = v + s) + * + * @param[in] a vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec2s +glms_vec2_(adds)(vec2s a, float s) { + vec2s r; + glm_vec2_adds(a.raw, s, r.raw); + return r; +} + +/*! + * @brief subtract b vector from a vector store result in dest + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns destination vector + */ +CGLM_INLINE +vec2s +glms_vec2_(sub)(vec2s a, vec2s b) { + vec2s r; + glm_vec2_sub(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief subtract scalar from v vector store result in dest (d = v - s) + * + * @param[in] a vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec2s +glms_vec2_(subs)(vec2s a, float s) { + vec2s r; + glm_vec2_subs(a.raw, s, r.raw); + return r; +} + +/*! + * @brief multiply two vectors (component-wise multiplication) + * + * @param a vector1 + * @param b vector2 + * @returns result = (a[0] * b[0], a[1] * b[1]) + */ +CGLM_INLINE +vec2s +glms_vec2_(mul)(vec2s a, vec2s b) { + vec2s r; + glm_vec2_mul(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief multiply/scale vec2 vector with scalar: result = v * s + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec2s +glms_vec2_(scale)(vec2s v, float s) { + vec2s r; + glm_vec2_scale(v.raw, s, r.raw); + return r; +} + +/*! + * @brief make vec2 vector scale as specified: result = unit(v) * s + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec2s +glms_vec2_(scale_as)(vec2s v, float s) { + vec2s r; + glm_vec2_scale_as(v.raw, s, r.raw); + return r; +} + +/*! + * @brief div vector with another component-wise division: d = a / b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns result = (a[0]/b[0], a[1]/b[1]) + */ +CGLM_INLINE +vec2s +glms_vec2_(div)(vec2s a, vec2s b) { + vec2s r; + glm_vec2_div(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief div vector with scalar: d = v / s + * + * @param[in] a vector + * @param[in] s scalar + * @returns result = (a[0]/s, a[1]/s) + */ +CGLM_INLINE +vec2s +glms_vec2_(divs)(vec2s a, float s) { + vec2s r; + glm_vec2_divs(a.raw, s, r.raw); + return r; +} + +/*! + * @brief add two vectors and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a + b) + */ +CGLM_INLINE +vec2s +glms_vec2_(addadd)(vec2s a, vec2s b, vec2s dest) { + glm_vec2_addadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief sub two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a + b) + */ +CGLM_INLINE +vec2s +glms_vec2_(subadd)(vec2s a, vec2s b, vec2s dest) { + glm_vec2_subadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a * b) + */ +CGLM_INLINE +vec2s +glms_vec2_(muladd)(vec2s a, vec2s b, vec2s dest) { + glm_vec2_muladd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul vector with scalar and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @returns dest += (a * b) + */ +CGLM_INLINE +vec2s +glms_vec2_(muladds)(vec2s a, float s, vec2s dest) { + glm_vec2_muladds(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief add max of two vectors to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += max(a, b) + */ +CGLM_INLINE +vec2s +glms_vec2_(maxadd)(vec2s a, vec2s b, vec2s dest) { + glm_vec2_maxadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add min of two vectors to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += min(a, b) + */ +CGLM_INLINE +vec2s +glms_vec2_(minadd)(vec2s a, vec2s b, vec2s dest) { + glm_vec2_minadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief sub two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= (a - b) + */ +CGLM_INLINE +vec2s +glms_vec2_(subsub)(vec2s a, vec2s b, vec2s dest) { + glm_vec2_subsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= (a + b) + */ +CGLM_INLINE +vec2s +glms_vec2_(addsub)(vec2s a, vec2s b, vec2s dest) { + glm_vec2_addsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= (a * b) + */ +CGLM_INLINE +vec2s +glms_vec2_(mulsub)(vec2s a, vec2s b, vec2s dest) { + glm_vec2_mulsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul vector with scalar and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @returns dest -= (a * b) + */ +CGLM_INLINE +vec2s +glms_vec2_(mulsubs)(vec2s a, float s, vec2s dest) { + glm_vec2_mulsubs(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief sub max of two vectors to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= max(a, b) + */ +CGLM_INLINE +vec2s +glms_vec2_(maxsub)(vec2s a, vec2s b, vec2s dest) { + glm_vec2_maxsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief sub min of two vectors to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= min(a, b) + */ +CGLM_INLINE +vec2s +glms_vec2_(minsub)(vec2s a, vec2s b, vec2s dest) { + glm_vec2_minsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief negate vector components + * + * @param[in] v vector + * @returns negated vector + */ +CGLM_INLINE +vec2s +glms_vec2_(negate)(vec2s v) { + glm_vec2_negate(v.raw); + return v; +} + +/*! + * @brief normalize vec2 and store result in same vec + * + * @param[in] v vector + * @returns normalized vector + */ +CGLM_INLINE +vec2s +glms_vec2_(normalize)(vec2s v) { + glm_vec2_normalize(v.raw); + return v; +} + +/*! + * @brief rotate vec2 by angle using Rodrigues' rotation formula + * + * @param[in] v vector + * @param[in] angle angle by radians + * @returns rotated vector + */ +CGLM_INLINE +vec2s +glms_vec2_(rotate)(vec2s v, float angle) { + vec2s r; + glm_vec2_rotate(v.raw, angle, r.raw); + return r; +} + +/** + * @brief find center point of two vector + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns center point + */ +CGLM_INLINE +vec2s +glms_vec2_(center)(vec2s a, vec2s b) { + vec2s r; + glm_vec2_center(a.raw, b.raw, r.raw); + return r; +} + +/** + * @brief distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return distance + */ +CGLM_INLINE +float +glms_vec2_(distance)(vec2s a, vec2s b) { + return glm_vec2_distance(a.raw, b.raw); +} + +/** + * @brief squared distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return squared distance (distance * distance) + */ +CGLM_INLINE +float +glms_vec2_(distance2)(vec2s a, vec2s b) { + return glm_vec2_distance2(a.raw, b.raw); +} + +/*! + * @brief max values of vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns destination + */ +CGLM_INLINE +vec2s +glms_vec2_(maxv)(vec2s a, vec2s b) { + vec2s r; + glm_vec2_maxv(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief min values of vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns destination + */ +CGLM_INLINE +vec2s +glms_vec2_(minv)(vec2s a, vec2s b) { + vec2s r; + glm_vec2_minv(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief clamp vector's individual members between min and max values + * + * @param[in] v vector + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + * @returns clamped vector + */ +CGLM_INLINE +vec2s +glms_vec2_(clamp)(vec2s v, float minVal, float maxVal) { + glm_vec2_clamp(v.raw, minVal, maxVal); + return v; +} + +/*! + * @brief linear interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @returns destination + */ +CGLM_INLINE +vec2s +glms_vec2_(lerp)(vec2s from, vec2s to, float t) { + vec2s r; + glm_vec2_lerp(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief threshold function + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec2s +glms_vec2_(step)(vec2s edge, vec2s x) { + vec2s r; + glm_vec2_step(edge.raw, x.raw, r.raw); + return r; +} + +/*! + * @brief Create two dimensional vector from pointer + * + * @param[in] src pointer to an array of floats + * @returns constructed 2D vector from raw pointer + */ +CGLM_INLINE +vec2s +glms_vec2_(make)(const float * __restrict src) { + vec2s dest; + glm_vec2_make(src, dest.raw); + return dest; +} + +/*! + * @brief reflection vector using an incident ray and a surface normal + * + * @param[in] I incident vector + * @param[in] N normalized normal vector + * @returns reflection result + */ +CGLM_INLINE +vec2s +glms_vec2_(reflect)(vec2s v, vec2s n) { + vec2s dest; + glm_vec2_reflect(v.raw, n.raw, dest.raw); + return dest; +} + +/*! + * @brief computes refraction vector for an incident vector and a surface normal. + * + * calculates the refraction vector based on Snell's law. If total internal reflection + * occurs (angle too great given eta), dest is set to zero and returns false. + * Otherwise, computes refraction vector, stores it in dest, and returns true. + * + * @param[in] v normalized incident vector + * @param[in] n normalized normal vector + * @param[in] eta ratio of indices of refraction (incident/transmitted) + * @param[out] dest refraction vector if refraction occurs; zero vector otherwise + * + * @returns true if refraction occurs; false if total internal reflection occurs. + */ +CGLM_INLINE +bool +glms_vec2_(refract)(vec2s v, vec2s n, float eta, vec2s * __restrict dest) { + return glm_vec2_refract(v.raw, n.raw, eta, dest->raw); +} + +#endif /* cglms_vec2s_h */ diff --git a/external/cglm/struct/vec3-ext.h b/external/cglm/struct/vec3-ext.h new file mode 100644 index 0000000..6cd8ca0 --- /dev/null +++ b/external/cglm/struct/vec3-ext.h @@ -0,0 +1,325 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/*! + * @brief SIMD like functions + */ + +/* + Functions: + CGLM_INLINE vec3s glms_vec3_broadcast(float val); + CGLM_INLINE vec3s glms_vec3_fill(float val); + CGLM_INLINE bool glms_vec3_eq(vec3s v, float val); + CGLM_INLINE bool glms_vec3_eq_eps(vec3s v, float val); + CGLM_INLINE bool glms_vec3_eq_all(vec3s v); + CGLM_INLINE bool glms_vec3_eqv(vec3s a, vec3s b); + CGLM_INLINE bool glms_vec3_eqv_eps(vec3s a, vec3s b); + CGLM_INLINE float glms_vec3_max(vec3s v); + CGLM_INLINE float glms_vec3_min(vec3s v); + CGLM_INLINE bool glms_vec3_isnan(vec3s v); + CGLM_INLINE bool glms_vec3_isinf(vec3s v); + CGLM_INLINE bool glms_vec3_isvalid(vec3s v); + CGLM_INLINE vec3s glms_vec3_sign(vec3s v); + CGLM_INLINE vec3s glms_vec3_abs(vec3s v); + CGLM_INLINE vec3s glms_vec3_fract(vec3s v); + CGLM_INLINE vec3s glms_vec3_floor(vec3s v); + CGLM_INLINE vec3s glms_vec3_mods(vec3s v, float s); + CGLM_INLINE vec3s glms_vec3_steps(float edge, vec3s v); + CGLM_INLINE vec3s glms_vec3_stepr(vec3s edge, float v); + CGLM_INLINE float glms_vec3_hadd(vec3s v); + CGLM_INLINE vec3s glms_vec3_sqrt(vec3s v); + */ + +#ifndef cglms_vec3s_ext_h +#define cglms_vec3s_ext_h + +#include "../common.h" +#include "../types-struct.h" +#include "../util.h" +#include "../vec3-ext.h" + +/* api definition */ +#define glms_vec3_(NAME) CGLM_STRUCTAPI(vec3, NAME) + +/*! + * @brief fill a vector with specified value + * + * @param[in] val value + * @returns dest + */ +CGLM_INLINE +vec3s +glms_vec3_(broadcast)(float val) { + vec3s r; + glm_vec3_broadcast(val, r.raw); + return r; +} + +/*! + * @brief fill a vector with specified value + * + * @param[in] val value + * @returns dest + */ +CGLM_INLINE +vec3s +glms_vec3_(fill)(float val) { + vec3s r; + glm_vec3_fill(r.raw, val); + return r; +} + +/*! + * @brief check if vector is equal to value (without epsilon) + * + * @param[in] v vector + * @param[in] val value + */ +CGLM_INLINE +bool +glms_vec3_(eq)(vec3s v, float val) { + return glm_vec3_eq(v.raw, val); +} + +/*! + * @brief check if vector is equal to value (with epsilon) + * + * @param[in] v vector + * @param[in] val value + */ +CGLM_INLINE +bool +glms_vec3_(eq_eps)(vec3s v, float val) { + return glm_vec3_eq_eps(v.raw, val); +} + +/*! + * @brief check if vector members are equal (without epsilon) + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec3_(eq_all)(vec3s v) { + return glm_vec3_eq_all(v.raw); +} + +/*! + * @brief check if vector is equal to another (without epsilon) + * + * @param[in] a vector + * @param[in] b vector + */ +CGLM_INLINE +bool +glms_vec3_(eqv)(vec3s a, vec3s b) { + return glm_vec3_eqv(a.raw, b.raw); +} + +/*! + * @brief check if vector is equal to another (with epsilon) + * + * @param[in] a vector + * @param[in] b vector + */ +CGLM_INLINE +bool +glms_vec3_(eqv_eps)(vec3s a, vec3s b) { + return glm_vec3_eqv_eps(a.raw, b.raw); +} + +/*! + * @brief max value of vector + * + * @param[in] v vector + */ +CGLM_INLINE +float +glms_vec3_(max)(vec3s v) { + return glm_vec3_max(v.raw); +} + +/*! + * @brief min value of vector + * + * @param[in] v vector + */ +CGLM_INLINE +float +glms_vec3_(min)(vec3s v) { + return glm_vec3_min(v.raw); +} + +/*! + * @brief check if one of items is NaN (not a number) + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec3_(isnan)(vec3s v) { + return glm_vec3_isnan(v.raw); +} + +/*! + * @brief check if one of items is INFINITY + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec3_(isinf)(vec3s v) { + return glm_vec3_isinf(v.raw); +} + +/*! + * @brief check if all items are valid number + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec3_(isvalid)(vec3s v) { + return glm_vec3_isvalid(v.raw); +} + +/*! + * @brief get sign of 32 bit float as +1, -1, 0 + * + * Important: It returns 0 for zero/NaN input + * + * @param v vector + * @returns sign vector + */ +CGLM_INLINE +vec3s +glms_vec3_(sign)(vec3s v) { + vec3s r; + glm_vec3_sign(v.raw, r.raw); + return r; +} + +/*! + * @brief absolute value of each vector item + * + * @param[in] v vector + * @return destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_(abs)(vec3s v) { + vec3s r; + glm_vec3_abs(v.raw, r.raw); + return r; +} + +/*! + * @brief fractional part of each vector item + * + * @param[in] v vector + * @return dest destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_(fract)(vec3s v) { + vec3s r; + glm_vec3_fract(v.raw, r.raw); + return r; +} + +/*! + * @brief floor of each vector item + * + * @param[in] v vector + * @return dest destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_(floor)(vec3s v) { + vec3s r; + glm_vec3_floor(v.raw, r.raw); + return r; +} + +/*! + * @brief mod of each vector item by scalar + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_(mods)(vec3s v, float s) { + vec3s r; + glm_vec3_mods(v.raw, s, r.raw); + return r; +} + +/*! + * @brief threshold each vector item with scalar + * condition is: (x[i] < edge) ? 0.0 : 1.0 + * + * @param[in] edge threshold + * @param[in] x vector to test against threshold + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(steps)(float edge, vec3s x) { + vec3s r; + glm_vec3_steps(edge, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold a value with *vector* as the threshold + * condition is: (x < edge[i]) ? 0.0 : 1.0 + * + * @param[in] edge threshold vector + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(stepr)(vec3s edge, float x) { + vec3s r; + glm_vec3_stepr(edge.raw, x, r.raw); + return r; +} + +/*! + * @brief vector reduction by summation + * @warning could overflow + * + * @param[in] v vector + * @return sum of all vector's elements + */ +CGLM_INLINE +float +glms_vec3_(hadd)(vec3s v) { + return glm_vec3_hadd(v.raw); +} + +/*! + * @brief square root of each vector item + * + * @param[in] v vector + * @returns destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_(sqrt)(vec3s v) { + vec3s r; + glm_vec3_sqrt(v.raw, r.raw); + return r; +} + +#endif /* cglms_vec3s_ext_h */ diff --git a/external/cglm/struct/vec3.h b/external/cglm/struct/vec3.h new file mode 100644 index 0000000..a1d901e --- /dev/null +++ b/external/cglm/struct/vec3.h @@ -0,0 +1,1132 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_VEC3_ONE_INIT + GLMS_VEC3_ZERO_INIT + GLMS_VEC3_ONE + GLMS_VEC3_ZERO + GLMS_YUP + GLMS_ZUP + GLMS_XUP + + Functions: + CGLM_INLINE vec3s glms_vec3(vec4s v4); + CGLM_INLINE void glms_vec3_pack(vec3s dst[], vec3 src[], size_t len); + CGLM_INLINE void glms_vec3_unpack(vec3 dst[], vec3s src[], size_t len); + CGLM_INLINE vec3s glms_vec3_zero(void); + CGLM_INLINE vec3s glms_vec3_one(void); + CGLM_INLINE float glms_vec3_dot(vec3s a, vec3s b); + CGLM_INLINE float glms_vec3_norm2(vec3s v); + CGLM_INLINE float glms_vec3_norm(vec3s v); + CGLM_INLINE float glms_vec3_norm_one(vec3s v); + CGLM_INLINE float glms_vec3_norm_inf(vec3s v); + CGLM_INLINE vec3s glms_vec3_add(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_adds(vec3s a, float s); + CGLM_INLINE vec3s glms_vec3_sub(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_subs(vec3s a, float s); + CGLM_INLINE vec3s glms_vec3_mul(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_scale(vec3s v, float s); + CGLM_INLINE vec3s glms_vec3_scale_as(vec3s v, float s); + CGLM_INLINE vec3s glms_vec3_div(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_divs(vec3s a, float s); + CGLM_INLINE vec3s glms_vec3_addadd(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_subadd(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_muladd(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_muladds(vec3s a, float s, vec3s dest); + CGLM_INLINE vec3s glms_vec3_maxadd(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_minadd(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_subsub(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_addsub(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_mulsub(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_mulsubs(vec3s a, float s, vec3s dest); + CGLM_INLINE vec3s glms_vec3_maxsub(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_minsub(vec3s a, vec3s b, vec3s dest); + CGLM_INLINE vec3s glms_vec3_flipsign(vec3s v); + CGLM_INLINE vec3s glms_vec3_negate(vec3s v); + CGLM_INLINE vec3s glms_vec3_normalize(vec3s v); + CGLM_INLINE vec3s glms_vec3_cross(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_crossn(vec3s a, vec3s b); + CGLM_INLINE float glms_vec3_angle(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_rotate(vec3s v, float angle, vec3s axis); + CGLM_INLINE vec3s glms_vec3_rotate_m4(mat4s m, vec3s v); + CGLM_INLINE vec3s glms_vec3_rotate_m3(mat3s m, vec3s v); + CGLM_INLINE vec3s glms_vec3_proj(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_center(vec3s a, vec3s b); + CGLM_INLINE float glms_vec3_distance(vec3s a, vec3s b); + CGLM_INLINE float glms_vec3_distance2(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_maxv(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_minv(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_vec3_ortho(vec3s v); + CGLM_INLINE vec3s glms_vec3_clamp(vec3s v, float minVal, float maxVal); + CGLM_INLINE vec3s glms_vec3_lerp(vec3s from, vec3s to, float t); + CGLM_INLINE vec3s glms_vec3_lerpc(vec3s from, vec3s to, float t); + CGLM_INLINE vec3s glms_vec3_mix(vec3s from, vec3s to, float t); + CGLM_INLINE vec3s glms_vec3_mixc(vec3s from, vec3s to, float t); + CGLM_INLINE vec3s glms_vec3_step(vec3s edge, vec3s x); + CGLM_INLINE vec3s glms_vec3_smoothstep_uni(float edge0, float edge1, vec3s x); + CGLM_INLINE vec3s glms_vec3_smoothstep(vec3s edge0, vec3s edge1, vec3s x); + CGLM_INLINE vec3s glms_vec3_smoothinterp(vec3s from, vec3s to, float t); + CGLM_INLINE vec3s glms_vec3_smoothinterpc(vec3s from, vec3s to, float t); + CGLM_INLINE vec3s glms_vec3_swizzle(vec3s v, int mask); + CGLM_INLINE vec3s glms_vec3_make(float * restrict src); + CGLM_INLINE vec3s glms_vec3_faceforward(vec3s n, vec3s v, vec3s nref); + CGLM_INLINE vec3s glms_vec3_reflect(vec3s v, vec3s n); + CGLM_INLINE bool glms_vec3_refract(vec3s v, vec3s n, float eta, vec3s *dest) + + Convenient: + CGLM_INLINE vec3s glms_cross(vec3s a, vec3s b); + CGLM_INLINE float glms_dot(vec3s a, vec3s b); + CGLM_INLINE vec3s glms_normalize(vec3s v); + + Deprecated: + glms_vec3_step_uni --> use glms_vec3_steps + */ + +#ifndef cglms_vec3s_h +#define cglms_vec3s_h + +#include "../common.h" +#include "../types-struct.h" +#include "../util.h" +#include "../vec3.h" +#include "vec3-ext.h" + +/* DEPRECATED! */ +#define glms_vec3_step_uni(edge, x) glms_vec3_steps(edge, x) + +#define GLMS_VEC3_ONE_INIT {GLM_VEC3_ONE_INIT} +#define GLMS_VEC3_ZERO_INIT {GLM_VEC3_ZERO_INIT} + +#define GLMS_VEC3_ONE ((vec3s)GLMS_VEC3_ONE_INIT) +#define GLMS_VEC3_ZERO ((vec3s)GLMS_VEC3_ZERO_INIT) + +#define GLMS_YUP ((vec3s){{0.0f, 1.0f, 0.0f}}) +#define GLMS_ZUP ((vec3s){{0.0f, 0.0f, 1.0f}}) +#define GLMS_XUP ((vec3s){{1.0f, 0.0f, 0.0f}}) + +/*! + * @brief init vec3 using vec4 + * + * @param[in] v4 vector4 + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3(vec4s v4) { + vec3s r; + glm_vec3(v4.raw, r.raw); + return r; +} + +/*! + * @brief pack an array of vec3 into an array of vec3s + * + * @param[out] dst array of vec3 + * @param[in] src array of vec3s + * @param[in] len number of elements + */ +CGLM_INLINE +void +glms_vec3_(pack)(vec3s dst[], vec3 src[], size_t len) { + size_t i; + + for (i = 0; i < len; i++) { + glm_vec3_copy(src[i], dst[i].raw); + } +} + +/*! + * @brief unpack an array of vec3s into an array of vec3 + * + * @param[out] dst array of vec3s + * @param[in] src array of vec3 + * @param[in] len number of elements + */ +CGLM_INLINE +void +glms_vec3_(unpack)(vec3 dst[], vec3s src[], size_t len) { + size_t i; + + for (i = 0; i < len; i++) { + glm_vec3_copy(src[i].raw, dst[i]); + } +} + +/*! + * @brief make vector zero + * + * @returns zero vector + */ +CGLM_INLINE +vec3s +glms_vec3_(zero)(void) { + vec3s r; + glm_vec3_zero(r.raw); + return r; +} + +/*! + * @brief make vector one + * + * @returns one vector + */ +CGLM_INLINE +vec3s +glms_vec3_(one)(void) { + vec3s r; + glm_vec3_one(r.raw); + return r; +} + +/*! + * @brief vec3 dot product + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return dot product + */ +CGLM_INLINE +float +glms_vec3_(dot)(vec3s a, vec3s b) { + return glm_vec3_dot(a.raw, b.raw); +} + +/*! + * @brief norm * norm (magnitude) of vec + * + * we can use this func instead of calling norm * norm, because it would call + * sqrtf function twice but with this func we can avoid func call, maybe this is + * not good name for this func + * + * @param[in] v vector + * + * @return norm * norm + */ +CGLM_INLINE +float +glms_vec3_(norm2)(vec3s v) { + return glm_vec3_norm2(v.raw); +} + +/*! + * @brief norm (magnitude) of vec3 + * + * @param[in] v vector + * + * @return norm + */ +CGLM_INLINE +float +glms_vec3_(norm)(vec3s v) { + return glm_vec3_norm(v.raw); +} + +/*! + * @brief L1 norm of vec3 + * Also known as Manhattan Distance or Taxicab norm. + * L1 Norm is the sum of the magnitudes of the vectors in a space. + * It is calculated as the sum of the absolute values of the vector components. + * In this norm, all the components of the vector are weighted equally. + * + * This computes: + * R = |v[0]| + |v[1]| + |v[2]| + * + * @param[in] v vector + * + * @return L1 norm + */ +CGLM_INLINE +float +glms_vec3_(norm_one)(vec3s v) { + return glm_vec3_norm_one(v.raw); +} + +/*! + * @brief Infinity norm of vec3 + * Also known as Maximum norm. + * Infinity Norm is the largest magnitude among each element of a vector. + * It is calculated as the maximum of the absolute values of the vector components. + * + * This computes: + * inf norm = max(|v[0]|, |v[1]|, |v[2]|) + * + * @param[in] v vector + * + * @return Infinity norm + */ +CGLM_INLINE +float +glms_vec3_(norm_inf)(vec3s v) { + return glm_vec3_norm_inf(v.raw); +} + +/*! + * @brief add a vector to b vector store result in dest + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_(add)(vec3s a, vec3s b) { + vec3s r; + glm_vec3_add(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief add scalar to v vector store result in dest (d = v + s) + * + * @param[in] a vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_(adds)(vec3s a, float s) { + vec3s r; + glm_vec3_adds(a.raw, s, r.raw); + return r; +} + +/*! + * @brief subtract b vector from a vector store result in dest + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_(sub)(vec3s a, vec3s b) { + vec3s r; + glm_vec3_sub(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief subtract scalar from v vector store result in dest (d = v - s) + * + * @param[in] a vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_(subs)(vec3s a, float s) { + vec3s r; + glm_vec3_subs(a.raw, s, r.raw); + return r; +} + +/*! + * @brief multiply two vectors (component-wise multiplication) + * + * @param a vector1 + * @param b vector2 + * @returns v3 = (a[0] * b[0], a[1] * b[1], a[2] * b[2]) + */ +CGLM_INLINE +vec3s +glms_vec3_(mul)(vec3s a, vec3s b) { + vec3s r; + glm_vec3_mul(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief multiply/scale vec3 vector with scalar: result = v * s + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_(scale)(vec3s v, float s) { + vec3s r; + glm_vec3_scale(v.raw, s, r.raw); + return r; +} + +/*! + * @brief make vec3 vector scale as specified: result = unit(v) * s + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec3s +glms_vec3_(scale_as)(vec3s v, float s) { + vec3s r; + glm_vec3_scale_as(v.raw, s, r.raw); + return r; +} + +/*! + * @brief div vector with another component-wise division: d = a / b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns result = (a[0]/b[0], a[1]/b[1], a[2]/b[2]) + */ +CGLM_INLINE +vec3s +glms_vec3_(div)(vec3s a, vec3s b) { + vec3s r; + glm_vec3_div(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief div vector with scalar: d = v / s + * + * @param[in] a vector + * @param[in] s scalar + * @returns result = (a[0]/s, a[1]/s, a[2]/s) + */ +CGLM_INLINE +vec3s +glms_vec3_(divs)(vec3s a, float s) { + vec3s r; + glm_vec3_divs(a.raw, s, r.raw); + return r; +} + +/*! + * @brief add two vectors and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a + b) + */ +CGLM_INLINE +vec3s +glms_vec3_(addadd)(vec3s a, vec3s b, vec3s dest) { + glm_vec3_addadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief sub two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a + b) + */ +CGLM_INLINE +vec3s +glms_vec3_(subadd)(vec3s a, vec3s b, vec3s dest) { + glm_vec3_subadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a * b) + */ +CGLM_INLINE +vec3s +glms_vec3_(muladd)(vec3s a, vec3s b, vec3s dest) { + glm_vec3_muladd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul vector with scalar and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @returns dest += (a * b) + */ +CGLM_INLINE +vec3s +glms_vec3_(muladds)(vec3s a, float s, vec3s dest) { + glm_vec3_muladds(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief add max of two vectors to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += max(a, b) + */ +CGLM_INLINE +vec3s +glms_vec3_(maxadd)(vec3s a, vec3s b, vec3s dest) { + glm_vec3_maxadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add min of two vectors to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += min(a, b) + */ +CGLM_INLINE +vec3s +glms_vec3_(minadd)(vec3s a, vec3s b, vec3s dest) { + glm_vec3_minadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief sub two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= (a - b) + */ +CGLM_INLINE +vec3s +glms_vec3_(subsub)(vec3s a, vec3s b, vec3s dest) { + glm_vec3_subsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= (a + b) + */ +CGLM_INLINE +vec3s +glms_vec3_(addsub)(vec3s a, vec3s b, vec3s dest) { + glm_vec3_addsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= (a * b) + */ +CGLM_INLINE +vec3s +glms_vec3_(mulsub)(vec3s a, vec3s b, vec3s dest) { + glm_vec3_mulsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul vector with scalar and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @returns dest -= (a * b) + */ +CGLM_INLINE +vec3s +glms_vec3_(mulsubs)(vec3s a, float s, vec3s dest) { + glm_vec3_mulsubs(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief sub max of two vectors to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= max(a, b) + */ +CGLM_INLINE +vec3s +glms_vec3_(maxsub)(vec3s a, vec3s b, vec3s dest) { + glm_vec3_maxsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief sub min of two vectors to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= min(a, b) + */ +CGLM_INLINE +vec3s +glms_vec3_(minsub)(vec3s a, vec3s b, vec3s dest) { + glm_vec3_minsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief negate vector components and store result in dest + * + * @param[in] v vector + * @returns result vector + */ +CGLM_INLINE +vec3s +glms_vec3_(flipsign)(vec3s v) { + glm_vec3_flipsign(v.raw); + return v; +} + +/*! + * @brief negate vector components + * + * @param[in] v vector + * @returns negated vector + */ +CGLM_INLINE +vec3s +glms_vec3_(negate)(vec3s v) { + glm_vec3_negate(v.raw); + return v; +} + +/*! + * @brief normalize vec3 and store result in same vec + * + * @param[in] v vector + * @returns normalized vector + */ +CGLM_INLINE +vec3s +glms_vec3_(normalize)(vec3s v) { + glm_vec3_normalize(v.raw); + return v; +} + +/*! + * @brief cross product of two vector (RH) + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(cross)(vec3s a, vec3s b) { + vec3s r; + glm_vec3_cross(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief cross product of two vector (RH) and normalize the result + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(crossn)(vec3s a, vec3s b) { + vec3s r; + glm_vec3_crossn(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief angle between two vector + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return angle as radians + */ +CGLM_INLINE +float +glms_vec3_(angle)(vec3s a, vec3s b) { + return glm_vec3_angle(a.raw, b.raw); +} + +/*! + * @brief rotate vec3 around axis by angle using Rodrigues' rotation formula + * + * @param[in] v vector + * @param[in] axis axis vector (must be unit vector) + * @param[in] angle angle by radians + * @returns rotated vector + */ +CGLM_INLINE +vec3s +glms_vec3_(rotate)(vec3s v, float angle, vec3s axis) { + glm_vec3_rotate(v.raw, angle, axis.raw); + return v; +} + +/*! + * @brief apply rotation matrix to vector + * + * matrix format should be (no perspective): + * a b c x + * e f g y + * i j k z + * 0 0 0 w + * + * @param[in] m affine matrix or rot matrix + * @param[in] v vector + * @returns rotated vector + */ +CGLM_INLINE +vec3s +glms_vec3_(rotate_m4)(mat4s m, vec3s v) { + vec3s r; + glm_vec3_rotate_m4(m.raw, v.raw, r.raw); + return r; +} + +/*! + * @brief apply rotation matrix to vector + * + * @param[in] m affine matrix or rot matrix + * @param[in] v vector + * @returns rotated vector + */ +CGLM_INLINE +vec3s +glms_vec3_(rotate_m3)(mat3s m, vec3s v) { + vec3s r; + glm_vec3_rotate_m3(m.raw, v.raw, r.raw); + return r; +} + +/*! + * @brief project a vector onto b vector + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns projected vector + */ +CGLM_INLINE +vec3s +glms_vec3_(proj)(vec3s a, vec3s b) { + vec3s r; + glm_vec3_proj(a.raw, b.raw, r.raw); + return r; +} + +/** + * @brief find center point of two vector + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns center point + */ +CGLM_INLINE +vec3s +glms_vec3_(center)(vec3s a, vec3s b) { + vec3s r; + glm_vec3_center(a.raw, b.raw, r.raw); + return r; +} + +/** + * @brief distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return distance + */ +CGLM_INLINE +float +glms_vec3_(distance)(vec3s a, vec3s b) { + return glm_vec3_distance(a.raw, b.raw); +} + +/** + * @brief squared distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return squared distance (distance * distance) + */ +CGLM_INLINE +float +glms_vec3_(distance2)(vec3s a, vec3s b) { + return glm_vec3_distance2(a.raw, b.raw); +} + +/*! + * @brief max values of vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(maxv)(vec3s a, vec3s b) { + vec3s r; + glm_vec3_maxv(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief min values of vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(minv)(vec3s a, vec3s b) { + vec3s r; + glm_vec3_minv(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief possible orthogonal/perpendicular vector + * + * @param[in] v vector + * @returns orthogonal/perpendicular vector + */ +CGLM_INLINE +vec3s +glms_vec3_(ortho)(vec3s v) { + vec3s r; + glm_vec3_ortho(v.raw, r.raw); + return r; +} + +/*! + * @brief clamp vector's individual members between min and max values + * + * @param[in] v vector + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + * @returns clamped vector + */ +CGLM_INLINE +vec3s +glms_vec3_(clamp)(vec3s v, float minVal, float maxVal) { + glm_vec3_clamp(v.raw, minVal, maxVal); + return v; +} + +/*! + * @brief linear interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(lerp)(vec3s from, vec3s to, float t) { + vec3s r; + glm_vec3_lerp(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief linear interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(lerpc)(vec3s from, vec3s to, float t) { + vec3s r; + glm_vec3_lerpc(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief linear interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(mix)(vec3s from, vec3s to, float t) { + vec3s r; + glm_vec3_mix(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief linear interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(mixc)(vec3s from, vec3s to, float t) { + vec3s r; + glm_vec3_mixc(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief threshold function + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @returns 0.0 if x < edge, else 1.0 + */ +CGLM_INLINE +vec3s +glms_vec3_(step)(vec3s edge, vec3s x) { + vec3s r; + glm_vec3_step(edge.raw, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold function with a smooth transition (unidimensional) + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(smoothstep_uni)(float edge0, float edge1, vec3s x) { + vec3s r; + glm_vec3_smoothstep_uni(edge0, edge1, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold function with a smooth transition + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(smoothstep)(vec3s edge0, vec3s edge1, vec3s x) { + vec3s r; + glm_vec3_smoothstep(edge0.raw, edge1.raw, x.raw, r.raw); + return r; +} + +/*! + * @brief smooth Hermite interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(smoothinterp)(vec3s from, vec3s to, float t) { + vec3s r; + glm_vec3_smoothinterp(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief smooth Hermite interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_(smoothinterpc)(vec3s from, vec3s to, float t) { + vec3s r; + glm_vec3_smoothinterpc(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief vec3 cross product + * + * this is just convenient wrapper + * + * @param[in] a source 1 + * @param[in] b source 2 + * @returns destination + */ +CGLM_INLINE +vec3s +glms_cross(vec3s a, vec3s b) { + vec3s r; + glm_cross(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief vec3 dot product + * + * this is just convenient wrapper + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return dot product + */ +CGLM_INLINE +float +glms_dot(vec3s a, vec3s b) { + return glm_dot(a.raw, b.raw); +} + +/*! + * @brief normalize vec3 and store result in same vec + * + * this is just convenient wrapper + * + * @param[in] v vector + * @returns normalized vector + */ +CGLM_INLINE +vec3s +glms_normalize(vec3s v) { + glm_normalize(v.raw); + return v; +} + +/*! + * @brief swizzle vector components + * + * you can use existing masks e.g. GLM_XXX, GLM_ZYX + * + * @param[in] v source + * @param[in] mask mask + * @returns swizzled vector + */ +CGLM_INLINE +vec3s +glms_vec3_(swizzle)(vec3s v, int mask) { + vec3s dest; + glm_vec3_swizzle(v.raw, mask, dest.raw); + return dest; +} + +/*! + * @brief Create three dimensional vector from pointer + * + * @param[in] src pointer to an array of floats + * @returns constructed 3D vector from raw pointer + */ +CGLM_INLINE +vec3s +glms_vec3_(make)(const float * __restrict src) { + vec3s dest; + glm_vec3_make(src, dest.raw); + return dest; +} + +/*! + * @brief a vector pointing in the same direction as another + * + * orients a vector to point away from a surface as defined by its normal + * + * @param[in] n vector to orient. + * @param[in] v incident vector + * @param[in] nref reference vector + * @returns oriented vector, pointing away from the surface. + */ +CGLM_INLINE +vec3s +glms_vec3_(faceforward)(vec3s n, vec3s v, vec3s nref) { + vec3s dest; + glm_vec3_faceforward(n.raw, v.raw, nref.raw, dest.raw); + return dest; +} + +/*! + * @brief reflection vector using an incident ray and a surface normal + * + * @param[in] I incident vector + * @param[in] N normalized normal vector + * @returns reflection result + */ +CGLM_INLINE +vec3s +glms_vec3_(reflect)(vec3s v, vec3s n) { + vec3s dest; + glm_vec3_reflect(v.raw, n.raw, dest.raw); + return dest; +} + +/*! + * @brief computes refraction vector for an incident vector and a surface normal. + * + * calculates the refraction vector based on Snell's law. If total internal reflection + * occurs (angle too great given eta), dest is set to zero and returns false. + * Otherwise, computes refraction vector, stores it in dest, and returns true. + * + * @param[in] v normalized incident vector + * @param[in] n normalized normal vector + * @param[in] eta ratio of indices of refraction (incident/transmitted) + * @param[out] dest refraction vector if refraction occurs; zero vector otherwise + * + * @returns true if refraction occurs; false if total internal reflection occurs. + */ +CGLM_INLINE +bool +glms_vec3_(refract)(vec3s v, vec3s n, float eta, vec3s * __restrict dest) { + return glm_vec3_refract(v.raw, n.raw, eta, dest->raw); +} + +#endif /* cglms_vec3s_h */ diff --git a/external/cglm/struct/vec4-ext.h b/external/cglm/struct/vec4-ext.h new file mode 100644 index 0000000..f57348e --- /dev/null +++ b/external/cglm/struct/vec4-ext.h @@ -0,0 +1,325 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/*! + * @brief SIMD like functions + */ + +/* + Functions: + CGLM_INLINE vec4s glms_vec4_broadcast(float val); + CGLM_INLINE vec4s glms_vec4_fill(float val); + CGLM_INLINE bool glms_vec4_eq(vec4s v, float val); + CGLM_INLINE bool glms_vec4_eq_eps(vec4s v, float val); + CGLM_INLINE bool glms_vec4_eq_all(vec4s v); + CGLM_INLINE bool glms_vec4_eqv(vec4s a, vec4s b); + CGLM_INLINE bool glms_vec4_eqv_eps(vec4s a, vec4s b); + CGLM_INLINE float glms_vec4_max(vec4s v); + CGLM_INLINE float glms_vec4_min(vec4s v); + CGLM_INLINE bool glms_vec4_isnan(vec4s v); + CGLM_INLINE bool glms_vec4_isinf(vec4s v); + CGLM_INLINE bool glms_vec4_isvalid(vec4s v); + CGLM_INLINE vec4s glms_vec4_sign(vec4s v); + CGLM_INLINE vec4s glms_vec4_abs(vec4s v); + CGLM_INLINE vec4s glms_vec4_fract(vec4s v); + CGLM_INLINE float glms_vec4_floor(vec4s v); + CGLM_INLINE float glms_vec4_mods(vec4s v, float s); + CGLM_INLINE float glms_vec4_steps(float edge, vec4s v); + CGLM_INLINE void glms_vec4_stepr(vec4s edge, float v); + CGLM_INLINE float glms_vec4_hadd(vec4s v); + CGLM_INLINE vec4s glms_vec4_sqrt(vec4s v); + */ + +#ifndef cglms_vec4s_ext_h +#define cglms_vec4s_ext_h + +#include "../common.h" +#include "../types-struct.h" +#include "../util.h" +#include "../vec4-ext.h" + +/* api definition */ +#define glms_vec4_(NAME) CGLM_STRUCTAPI(vec4, NAME) + +/*! + * @brief fill a vector with specified value + * + * @param val value + * @returns dest + */ +CGLM_INLINE +vec4s +glms_vec4_(broadcast)(float val) { + vec4s r; + glm_vec4_broadcast(val, r.raw); + return r; +} + +/*! + * @brief fill a vector with specified value + * + * @param val value + * @returns dest + */ +CGLM_INLINE +vec4s +glms_vec4_(fill)(float val) { + vec4s r; + glm_vec4_fill(r.raw, val); + return r; +} + +/*! + * @brief check if vector is equal to value (without epsilon) + * + * @param v vector + * @param val value + */ +CGLM_INLINE +bool +glms_vec4_(eq)(vec4s v, float val) { + return glm_vec4_eq(v.raw, val); +} + +/*! + * @brief check if vector is equal to value (with epsilon) + * + * @param v vector + * @param val value + */ +CGLM_INLINE +bool +glms_vec4_(eq_eps)(vec4s v, float val) { + return glm_vec4_eq_eps(v.raw, val); +} + +/*! + * @brief check if vector members are equal (without epsilon) + * + * @param v vector + */ +CGLM_INLINE +bool +glms_vec4_(eq_all)(vec4s v) { + return glm_vec4_eq_all(v.raw); +} + +/*! + * @brief check if vector is equal to another (without epsilon) + * + * @param a vector + * @param b vector + */ +CGLM_INLINE +bool +glms_vec4_(eqv)(vec4s a, vec4s b) { + return glm_vec4_eqv(a.raw, b.raw); +} + +/*! + * @brief check if vector is equal to another (with epsilon) + * + * @param a vector + * @param b vector + */ +CGLM_INLINE +bool +glms_vec4_(eqv_eps)(vec4s a, vec4s b) { + return glm_vec4_eqv_eps(a.raw, b.raw); +} + +/*! + * @brief max value of vector + * + * @param v vector + */ +CGLM_INLINE +float +glms_vec4_(max)(vec4s v) { + return glm_vec4_max(v.raw); +} + +/*! + * @brief min value of vector + * + * @param v vector + */ +CGLM_INLINE +float +glms_vec4_(min)(vec4s v) { + return glm_vec4_min(v.raw); +} + +/*! + * @brief check if one of items is NaN (not a number) + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec4_(isnan)(vec4s v) { + return glm_vec4_isnan(v.raw); +} + +/*! + * @brief check if one of items is INFINITY + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec4_(isinf)(vec4s v) { + return glm_vec4_isinf(v.raw); +} + +/*! + * @brief check if all items are valid number + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glms_vec4_(isvalid)(vec4s v) { + return glm_vec4_isvalid(v.raw); +} + +/*! + * @brief get sign of 32 bit float as +1, -1, 0 + * + * Important: It returns 0 for zero/NaN input + * + * @param v vector + * @returns sign vector + */ +CGLM_INLINE +vec4s +glms_vec4_(sign)(vec4s v) { + vec4s r; + glm_vec4_sign(v.raw, r.raw); + return r; +} + +/*! + * @brief absolute value of each vector item + * + * @param[in] v vector + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_(abs)(vec4s v) { + vec4s r; + glm_vec4_abs(v.raw, r.raw); + return r; +} + +/*! + * @brief fractional part of each vector item + * + * @param[in] v vector + * @returns dest destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_(fract)(vec4s v) { + vec4s r; + glm_vec4_fract(v.raw, r.raw); + return r; +} + +/*! + * @brief floor of each vector item + * + * @param[in] v vector + * @returns dest destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_(floor)(vec4s v) { + vec4s r; + glm_vec4_floor(v.raw, r.raw); + return r; +} + +/*! + * @brief mod of each vector item by scalar + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_(mods)(vec4s v, float s) { + vec4s r; + glm_vec4_mods(v.raw, s, r.raw); + return r; +} + +/*! + * @brief threshold each vector item with scalar + * condition is: (x[i] < edge) ? 0.0 : 1.0 + * + * @param[in] edge threshold + * @param[in] x vector to test against threshold + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(steps)(float edge, vec4s x) { + vec4s r; + glm_vec4_steps(edge, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold a value with *vector* as the threshold + * condition is: (x < edge[i]) ? 0.0 : 1.0 + * + * @param[in] edge threshold vector + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(stepr)(vec4s edge, float x) { + vec4s r; + glm_vec4_stepr(edge.raw, x, r.raw); + return r; +} + +/*! + * @brief vector reduction by summation + * @warning could overflow + * + * @param[in] v vector + * @return sum of all vector's elements + */ +CGLM_INLINE +float +glms_vec4_(hadd)(vec4s v) { + return glm_vec4_hadd(v.raw); +} + +/*! + * @brief square root of each vector item + * + * @param[in] v vector + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_(sqrt)(vec4s v) { + vec4s r; + glm_vec4_sqrt(v.raw, r.raw); + return r; +} + +#endif /* cglms_vec4s_ext_h */ diff --git a/external/cglm/struct/vec4.h b/external/cglm/struct/vec4.h new file mode 100644 index 0000000..a64c1a3 --- /dev/null +++ b/external/cglm/struct/vec4.h @@ -0,0 +1,961 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLMS_VEC4_ONE_INIT + GLMS_VEC4_BLACK_INIT + GLMS_VEC4_ZERO_INIT + GLMS_VEC4_ONE + GLMS_VEC4_BLACK + GLMS_VEC4_ZERO + + Functions: + CGLM_INLINE vec4s glms_vec4(vec3s v3, float last); + CGLM_INLINE vec3s glms_vec4_copy3(vec4s v); + CGLM_INLINE vec4s glms_vec4_copy(vec4s v); + CGLM_INLINE vec4s glms_vec4_ucopy(vec4s v); + CGLM_INLINE void glms_vec4_pack(vec4s dst[], vec4 src[], size_t len); + CGLM_INLINE void glms_vec4_unpack(vec4 dst[], vec4s src[], size_t len); + CGLM_INLINE float glms_vec4_dot(vec4s a, vec4s b); + CGLM_INLINE float glms_vec4_norm2(vec4s v); + CGLM_INLINE float glms_vec4_norm(vec4s v); + CGLM_INLINE float glms_vec4_norm_one(vec4s v); + CGLM_INLINE float glms_vec4_norm_inf(vec4s v); + CGLM_INLINE vec4s glms_vec4_add(vec4s a, vec4s b); + CGLM_INLINE vec4s glms_vec4_adds(vec4s v, float s); + CGLM_INLINE vec4s glms_vec4_sub(vec4s a, vec4s b); + CGLM_INLINE vec4s glms_vec4_subs(vec4s v, float s); + CGLM_INLINE vec4s glms_vec4_mul(vec4s a, vec4s b); + CGLM_INLINE vec4s glms_vec4_scale(vec4s v, float s); + CGLM_INLINE vec4s glms_vec4_scale_as(vec4s v, float s); + CGLM_INLINE vec4s glms_vec4_div(vec4s a, vec4s b); + CGLM_INLINE vec4s glms_vec4_divs(vec4s v, float s); + CGLM_INLINE vec4s glms_vec4_addadd(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_subadd(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_muladd(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_muladds(vec4s a, float s, vec4s dest); + CGLM_INLINE vec4s glms_vec4_maxadd(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_minadd(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_subsub(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_addsub(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_mulsub(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_mulsubs(vec4s a, float s, vec4s dest); + CGLM_INLINE vec4s glms_vec4_maxsub(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_minsub(vec4s a, vec4s b, vec4s dest); + CGLM_INLINE vec4s glms_vec4_negate(vec4s v); + CGLM_INLINE vec4s glms_vec4_normalize(vec4s v); + CGLM_INLINE float glms_vec4_distance(vec4s a, vec4s b); + CGLM_INLINE float glms_vec4_distance2(vec4s a, vec4s b); + CGLM_INLINE vec4s glms_vec4_maxv(vec4s a, vec4s b); + CGLM_INLINE vec4s glms_vec4_minv(vec4s a, vec4s b); + CGLM_INLINE vec4s glms_vec4_clamp(vec4s v, float minVal, float maxVal); + CGLM_INLINE vec4s glms_vec4_lerp(vec4s from, vec4s to, float t); + CGLM_INLINE vec4s glms_vec4_lerpc(vec4s from, vec4s to, float t); + CGLM_INLINE vec4s glms_vec4_mix(vec4s from, vec4s to, float t); + CGLM_INLINE vec4s glms_vec4_mixc(vec4s from, vec4s to, float t); + CGLM_INLINE vec4s glms_vec4_step(vec4s edge, vec4s x); + CGLM_INLINE vec4s glms_vec4_smoothstep_uni(float edge0, float edge1, vec4s x); + CGLM_INLINE vec4s glms_vec4_smoothstep(vec4s edge0, vec4s edge1, vec4s x); + CGLM_INLINE vec4s glms_vec4_smoothinterp(vec4s from, vec4s to, float t); + CGLM_INLINE vec4s glms_vec4_smoothinterpc(vec4s from, vec4s to, float t); + CGLM_INLINE vec4s glms_vec4_cubic(float s); + CGLM_INLINE vec4s glms_vec4_swizzle(vec4s v, int mask); + CGLM_INLINE vec4s glms_vec4_make(float * restrict src); + CGLM_INLINE vec4s glms_vec4_reflect(vec4s v, vec4s n); + CGLM_INLINE bool glms_vec4_refract(vec4s v, vec4s n, float eta, vec4s *dest) + + Deprecated: + glms_vec4_step_uni --> use glms_vec4_steps + */ + +#ifndef cglms_vec4s_h +#define cglms_vec4s_h + +#include "../common.h" +#include "../types-struct.h" +#include "../util.h" +#include "../vec4.h" +#include "vec4-ext.h" + +/* DEPRECATED! */ +#define glms_vec4_step_uni(edge, x) glms_vec4_steps(edge, x) + +#define GLMS_VEC4_ONE_INIT {GLM_VEC4_ONE_INIT} +#define GLMS_VEC4_BLACK_INIT {GLM_VEC4_BLACK_INIT} +#define GLMS_VEC4_ZERO_INIT {GLM_VEC4_ZERO_INIT} + +#define GLMS_VEC4_ONE ((vec4s)GLM_VEC4_ONE_INIT) +#define GLMS_VEC4_BLACK ((vec4s)GLM_VEC4_BLACK_INIT) +#define GLMS_VEC4_ZERO ((vec4s)GLM_VEC4_ZERO_INIT) + +/*! + * @brief init vec4 using vec3 + * + * @param[in] v3 vector3 + * @param[in] last last item + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4(vec3s v3, float last) { + vec4s r; + glm_vec4(v3.raw, last, r.raw); + return r; +} + +/*! + * @brief copy first 3 members of [a] to [dest] + * + * @param[in] v source + * @returns vec3 + */ +CGLM_INLINE +vec3s +glms_vec4_(copy3)(vec4s v) { + vec3s r; + glm_vec4_copy3(v.raw, r.raw); + return r; +} + +/*! + * @brief copy all members of [a] to [dest] + * + * @param[in] v source + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(copy)(vec4s v) { + vec4s r; + glm_vec4_copy(v.raw, r.raw); + return r; +} + +/*! + * @brief copy all members of [a] to [dest] + * + * alignment is not required + * + * @param[in] v source + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(ucopy)(vec4s v) { + vec4s r; + glm_vec4_ucopy(v.raw, r.raw); + return r; +} + +/*! + * @brief pack an array of vec4 into an array of vec4s + * + * @param[out] dst array of vec4 + * @param[in] src array of vec4s + * @param[in] len number of elements + */ +CGLM_INLINE +void +glms_vec4_(pack)(vec4s dst[], vec4 src[], size_t len) { + size_t i; + + for (i = 0; i < len; i++) { + glm_vec4_copy(src[i], dst[i].raw); + } +} + +/*! + * @brief unpack an array of vec4s into an array of vec4 + * + * @param[out] dst array of vec4s + * @param[in] src array of vec4 + * @param[in] len number of elements + */ +CGLM_INLINE +void +glms_vec4_(unpack)(vec4 dst[], vec4s src[], size_t len) { + size_t i; + + for (i = 0; i < len; i++) { + glm_vec4_copy(src[i].raw, dst[i]); + } +} + +/*! + * @brief make vector zero + * + * @returns zero vector + */ +CGLM_INLINE +vec4s +glms_vec4_(zero)(void) { + vec4s r; + glm_vec4_zero(r.raw); + return r; +} + +/*! + * @brief make vector one + * + * @returns one vector + */ +CGLM_INLINE +vec4s +glms_vec4_(one)(void) { + vec4s r; + glm_vec4_one(r.raw); + return r; +} + +/*! + * @brief vec4 dot product + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return dot product + */ +CGLM_INLINE +float +glms_vec4_(dot)(vec4s a, vec4s b) { + return glm_vec4_dot(a.raw, b.raw); +} + +/*! + * @brief norm * norm (magnitude) of vec + * + * we can use this func instead of calling norm * norm, because it would call + * sqrtf function twice but with this func we can avoid func call, maybe this is + * not good name for this func + * + * @param[in] v vec4 + * + * @return norm * norm + */ +CGLM_INLINE +float +glms_vec4_(norm2)(vec4s v) { + return glm_vec4_norm2(v.raw); +} + +/*! + * @brief norm (magnitude) of vec4 + * + * @param[in] v vector + * + * @return norm + */ +CGLM_INLINE +float +glms_vec4_(norm)(vec4s v) { + return glm_vec4_norm(v.raw); +} + +/*! + * @brief L1 norm of vec4 + * Also known as Manhattan Distance or Taxicab norm. + * L1 Norm is the sum of the magnitudes of the vectors in a space. + * It is calculated as the sum of the absolute values of the vector components. + * In this norm, all the components of the vector are weighted equally. + * + * This computes: + * R = |v[0]| + |v[1]| + |v[2]| + |v[3]| + * + * @param[in] v vector + * + * @return L1 norm + */ +CGLM_INLINE +float +glms_vec4_(norm_one)(vec4s v) { + return glm_vec4_norm_one(v.raw); +} + +/*! + * @brief Infinity norm of vec4 + * Also known as Maximum norm. + * Infinity Norm is the largest magnitude among each element of a vector. + * It is calculated as the maximum of the absolute values of the vector components. + * + * This computes: + * inf norm = max(|v[0]|, |v[1]|, |v[2]|, |v[3]|) + * + * @param[in] v vector + * + * @return Infinity norm + */ +CGLM_INLINE +float +glms_vec4_(norm_inf)(vec4s v) { + return glm_vec4_norm_inf(v.raw); +} + +/*! + * @brief add b vector to a vector store result in dest + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_(add)(vec4s a, vec4s b) { + vec4s r; + glm_vec4_add(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief add scalar to v vector store result in dest (d = v + vec(s)) + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_(adds)(vec4s v, float s) { + vec4s r; + glm_vec4_adds(v.raw, s, r.raw); + return r; +} + +/*! + * @brief subtract b vector from a vector store result in dest (d = a - b) + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_(sub)(vec4s a, vec4s b) { + vec4s r; + glm_vec4_sub(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief subtract scalar from v vector store result in dest (d = v - vec(s)) + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_(subs)(vec4s v, float s) { + vec4s r; + glm_vec4_subs(v.raw, s, r.raw); + return r; +} + +/*! + * @brief multiply two vectors (component-wise multiplication) + * + * @param a vector1 + * @param b vector2 + * @returns dest = (a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3]) + */ +CGLM_INLINE +vec4s +glms_vec4_(mul)(vec4s a, vec4s b) { + vec4s r; + glm_vec4_mul(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief multiply/scale vec4 vector with scalar: result = v * s + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_(scale)(vec4s v, float s) { + vec4s r; + glm_vec4_scale(v.raw, s, r.raw); + return r; +} + +/*! + * @brief make vec4 vector scale as specified: result = unit(v) * s + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_(scale_as)(vec4s v, float s) { + vec4s r; + glm_vec4_scale_as(v.raw, s, r.raw); + return r; +} + +/*! + * @brief div vector with another component-wise division: d = a / b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns result = (a[0]/b[0], a[1]/b[1], a[2]/b[2], a[3]/b[3]) + */ +CGLM_INLINE +vec4s +glms_vec4_(div)(vec4s a, vec4s b) { + vec4s r; + glm_vec4_div(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief div vec4 vector with scalar: d = v / s + * + * @param[in] v vector + * @param[in] s scalar + * @returns destination vector + */ +CGLM_INLINE +vec4s +glms_vec4_(divs)(vec4s v, float s) { + vec4s r; + glm_vec4_divs(v.raw, s, r.raw); + return r; +} + +/*! + * @brief add two vectors and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a + b) + */ +CGLM_INLINE +vec4s +glms_vec4_(addadd)(vec4s a, vec4s b, vec4s dest) { + glm_vec4_addadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief sub two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a - b) + */ +CGLM_INLINE +vec4s +glms_vec4_(subadd)(vec4s a, vec4s b, vec4s dest) { + glm_vec4_subadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += (a * b) + */ +CGLM_INLINE +vec4s +glms_vec4_(muladd)(vec4s a, vec4s b, vec4s dest) { + glm_vec4_muladd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul vector with scalar and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @returns dest += (a * b) + */ +CGLM_INLINE +vec4s +glms_vec4_(muladds)(vec4s a, float s, vec4s dest) { + glm_vec4_muladds(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief add max of two vectors to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += max(a, b) + */ +CGLM_INLINE +vec4s +glms_vec4_(maxadd)(vec4s a, vec4s b, vec4s dest) { + glm_vec4_maxadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add min of two vectors to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest += min(a, b) + */ +CGLM_INLINE +vec4s +glms_vec4_(minadd)(vec4s a, vec4s b, vec4s dest) { + glm_vec4_minadd(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief sub two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= (a + b) + */ +CGLM_INLINE +vec4s +glms_vec4_(subsub)(vec4s a, vec4s b, vec4s dest) { + glm_vec4_subsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief add two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= (a + b) + */ +CGLM_INLINE +vec4s +glms_vec4_(addsub)(vec4s a, vec4s b, vec4s dest) { + glm_vec4_addsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= (a * b) + */ +CGLM_INLINE +vec4s +glms_vec4_(mulsub)(vec4s a, vec4s b, vec4s dest) { + glm_vec4_mulsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief mul vector with scalar and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @returns dest -= (a * b) + */ +CGLM_INLINE +vec4s +glms_vec4_(mulsubs)(vec4s a, float s, vec4s dest) { + glm_vec4_mulsubs(a.raw, s, dest.raw); + return dest; +} + +/*! + * @brief sub max of two vectors to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= max(a, b) + */ +CGLM_INLINE +vec4s +glms_vec4_(maxsub)(vec4s a, vec4s b, vec4s dest) { + glm_vec4_maxsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief sub min of two vectors to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @returns dest -= min(a, b) + */ +CGLM_INLINE +vec4s +glms_vec4_(minsub)(vec4s a, vec4s b, vec4s dest) { + glm_vec4_minsub(a.raw, b.raw, dest.raw); + return dest; +} + +/*! + * @brief negate vector components and store result in dest + * + * @param[in] v vector + * @returns result vector + */ +CGLM_INLINE +vec4s +glms_vec4_(negate)(vec4s v) { + glm_vec4_negate(v.raw); + return v; +} + +/*! + * @brief normalize vec4 and store result in same vec + * + * @param[in] v vector + * @returns normalized vector + */ +CGLM_INLINE +vec4s +glms_vec4_(normalize)(vec4s v) { + glm_vec4_normalize(v.raw); + return v; +} + +/** + * @brief distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return returns distance + */ +CGLM_INLINE +float +glms_vec4_(distance)(vec4s a, vec4s b) { + return glm_vec4_distance(a.raw, b.raw); +} + +/** + * @brief squared distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return returns squared distance + */ +CGLM_INLINE +float +glms_vec4_(distance2)(vec4s a, vec4s b) { + return glm_vec4_distance2(a.raw, b.raw); +} + +/*! + * @brief max values of vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(maxv)(vec4s a, vec4s b) { + vec4s r; + glm_vec4_maxv(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief min values of vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(minv)(vec4s a, vec4s b) { + vec4s r; + glm_vec4_minv(a.raw, b.raw, r.raw); + return r; +} + +/*! + * @brief clamp vector's individual members between min and max values + * + * @param[in] v vector + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + * @returns clamped vector + */ +CGLM_INLINE +vec4s +glms_vec4_(clamp)(vec4s v, float minVal, float maxVal) { + glm_vec4_clamp(v.raw, minVal, maxVal); + return v; +} + +/*! + * @brief linear interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(lerp)(vec4s from, vec4s to, float t) { + vec4s r; + glm_vec4_lerp(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief linear interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(lerpc)(vec4s from, vec4s to, float t) { + vec4s r; + glm_vec4_lerpc(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief linear interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(mix)(vec4s from, vec4s to, float t) { + vec4s r; + glm_vec4_mix(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief linear interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(mixc)(vec4s from, vec4s to, float t) { + vec4s r; + glm_vec4_mixc(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief threshold function + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @returns 0.0 if x < edge, else 1.0 + */ +CGLM_INLINE +vec4s +glms_vec4_(step)(vec4s edge, vec4s x) { + vec4s r; + glm_vec4_step(edge.raw, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold function with a smooth transition (unidimensional) + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(smoothstep_uni)(float edge0, float edge1, vec4s x) { + vec4s r; + glm_vec4_smoothstep_uni(edge0, edge1, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold function with a smooth transition + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(smoothstep)(vec4s edge0, vec4s edge1, vec4s x) { + vec4s r; + glm_vec4_smoothstep(edge0.raw, edge1.raw, x.raw, r.raw); + return r; +} + +/*! + * @brief smooth Hermite interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(smoothinterp)(vec4s from, vec4s to, float t) { + vec4s r; + glm_vec4_smoothinterp(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief smooth Hermite interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(smoothinterpc)(vec4s from, vec4s to, float t) { + vec4s r; + glm_vec4_smoothinterpc(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief helper to fill vec4 as [S^3, S^2, S, 1] + * + * @param[in] s parameter + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_(cubic)(float s) { + vec4s r; + glm_vec4_cubic(s, r.raw); + return r; +} + +/*! + * @brief swizzle vector components + * + * you can use existing masks e.g. GLM_XXXX, GLM_WZYX + * + * @param[in] v source + * @param[in] mask mask + * @returns swizzled vector + */ +CGLM_INLINE +vec4s +glms_vec4_(swizzle)(vec4s v, int mask) { + vec4s dest; + glm_vec4_swizzle(v.raw, mask, dest.raw); + return dest; +} + +/*! + * @brief Create four dimensional vector from pointer + * + * @param[in] src pointer to an array of floats + * @returns constructed 4D vector from raw pointer + */ +CGLM_INLINE +vec4s +glms_vec4_(make)(const float * __restrict src) { + vec4s dest; + glm_vec4_make(src, dest.raw); + return dest; +} + +/*! + * @brief reflection vector using an incident ray and a surface normal + * + * @param[in] v incident vector + * @param[in] n normalized normal vector + * @returns reflection result + */ +CGLM_INLINE +vec4s +glms_vec4_(reflect)(vec4s v, vec4s n) { + vec4s dest; + glm_vec4_reflect(v.raw, n.raw, dest.raw); + return dest; +} + +/*! + * @brief computes refraction vector for an incident vector and a surface normal. + * + * calculates the refraction vector based on Snell's law. If total internal reflection + * occurs (angle too great given eta), dest is set to zero and returns false. + * Otherwise, computes refraction vector, stores it in dest, and returns true. + * + * this implementation does not explicitly preserve the 'w' component of the + * incident vector 'I' in the output 'dest', users requiring the preservation of + * the 'w' component should manually adjust 'dest' after calling this function. + * + * @param[in] v normalized incident vector + * @param[in] n normalized normal vector + * @param[in] eta ratio of indices of refraction (incident/transmitted) + * @param[out] dest refraction vector if refraction occurs; zero vector otherwise + * + * @returns true if refraction occurs; false if total internal reflection occurs. + */ +CGLM_INLINE +bool +glms_vec4_(refract)(vec4s v, vec4s n, float eta, vec4s * __restrict dest) { + return glm_vec4_refract(v.raw, n.raw, eta, dest->raw); +} + +#endif /* cglms_vec4s_h */ diff --git a/external/cglm/types-struct.h b/external/cglm/types-struct.h new file mode 100644 index 0000000..d93152e --- /dev/null +++ b/external/cglm/types-struct.h @@ -0,0 +1,303 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_types_struct_h +#define cglm_types_struct_h + +#include "types.h" + +/* + * Anonymous structs are available since C11, but we'd like to be compatible + * with C99 and C89 too. So let's figure out if we should be using them or not. + * It's simply a convenience feature, you can e.g. build the library with + * anonymous structs and your application without them and they'll still be + * compatible, cglm doesn't use the anonymous structs internally. + */ +#ifndef CGLM_USE_ANONYMOUS_STRUCT + /* If the user doesn't explicitly specify if they want anonymous structs or + * not, then we'll try to intuit an appropriate choice. */ +# if defined(CGLM_NO_ANONYMOUS_STRUCT) + /* The user has defined CGLM_NO_ANONYMOUS_STRUCT. This used to be the + * only #define governing the use of anonymous structs, so for backward + * compatibility, we still honor that choice and disable them. */ +# define CGLM_USE_ANONYMOUS_STRUCT 0 + /* Disable anonymous structs if strict ANSI mode is enabled for C89 or C99 */ +# elif defined(__STRICT_ANSI__) && \ + (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 201112L)) + /* __STRICT_ANSI__ is defined and we're in C89 + * or C99 mode (C11 or later not detected) */ +# define CGLM_USE_ANONYMOUS_STRUCT 0 +# elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \ + (defined(__cplusplus) && __cplusplus >= 201103L) + /* We're compiling for C11 or this is the MSVC compiler. In either + * case, anonymous structs are available, so use them. */ +# define CGLM_USE_ANONYMOUS_STRUCT 1 +# elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) + /* GCC 4.6 and onwards support anonymous structs as an extension */ +# define CGLM_USE_ANONYMOUS_STRUCT 1 +# elif defined(__clang__) && __clang_major__ >= 3 + /* Clang 3.0 and onwards support anonymous structs as an extension */ +# define CGLM_USE_ANONYMOUS_STRUCT 1 +# elif defined(_MSC_VER) && (_MSC_VER >= 1900) /* Visual Studio 2015 */ + /* We can support anonymous structs + * since Visual Studio 2015 or 2017 (1910) maybe? */ +# define CGLM_USE_ANONYMOUS_STRUCT 1 +# else + /* Otherwise, we're presumably building for C99 or C89 and can't rely + * on anonymous structs being available. Turn them off. */ +# define CGLM_USE_ANONYMOUS_STRUCT 0 +# endif +#endif + +typedef union vec2s { + vec2 raw; +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + float x; + float y; + }; + + struct { + float r; + float i; + }; + + struct { + float u; + float v; + }; + + struct { + float s; + float t; + }; +#endif +} vec2s; + +typedef union vec3s { + vec3 raw; +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + float x; + float y; + float z; + }; + + struct { + float r; + float g; + float b; + }; +#endif +} vec3s; + +typedef union ivec2s { + ivec2 raw; +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + int x; + int y; + }; + + struct { + int r; + int i; + }; + + struct { + int u; + int v; + }; + + struct { + int s; + int t; + }; +#endif +} ivec2s; + +typedef union ivec3s { + ivec3 raw; +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + int x; + int y; + int z; + }; + + struct { + int r; + int g; + int b; + }; +#endif +} ivec3s; + +typedef union ivec4s { + ivec4 raw; +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + int x; + int y; + int z; + int w; + }; + + struct { + int r; + int g; + int b; + int a; + }; +#endif +} ivec4s; + +typedef union CGLM_ALIGN_IF(16) vec4s { + vec4 raw; +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + float x; + float y; + float z; + float w; + }; + + struct { + float r; + float g; + float b; + float a; + }; +#endif +} vec4s; + +typedef union CGLM_ALIGN_IF(16) versors { + vec4 raw; +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + float x; + float y; + float z; + float w; + }; + + struct { + vec3s imag; + float real; + }; +#endif +} versors; + +typedef union mat2s { + mat2 raw; + vec2s col[2]; +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + float m00, m01; + float m10, m11; + }; +#endif +} mat2s; + +typedef union mat2x3s { + mat2x3 raw; + vec3s col[2]; /* [col (2), row (3)] */ +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + float m00, m01, m02; + float m10, m11, m12; + }; +#endif +} mat2x3s; + +typedef union mat2x4s { + mat2x4 raw; + vec4s col[2]; /* [col (2), row (4)] */ +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + float m00, m01, m02, m03; + float m10, m11, m12, m13; + }; +#endif +} mat2x4s; + +typedef union mat3s { + mat3 raw; + vec3s col[3]; +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + float m00, m01, m02; + float m10, m11, m12; + float m20, m21, m22; + }; +#endif +} mat3s; + +typedef union mat3x2s { + mat3x2 raw; + vec2s col[3]; /* [col (3), row (2)] */ +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + float m00, m01; + float m10, m11; + float m20, m21; + }; +#endif +} mat3x2s; + +typedef union mat3x4s { + mat3x4 raw; + vec4s col[3]; /* [col (3), row (4)] */ +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + float m00, m01, m02, m03; + float m10, m11, m12, m13; + float m20, m21, m22, m23; + }; +#endif +} mat3x4s; + +typedef union CGLM_ALIGN_MAT mat4s { + mat4 raw; + vec4s col[4]; +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + float m00, m01, m02, m03; + float m10, m11, m12, m13; + float m20, m21, m22, m23; + float m30, m31, m32, m33; + }; +#endif +} mat4s; + +typedef union mat4x2s { + mat4x2 raw; + vec2s col[4]; /* [col (4), row (2)] */ +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + float m00, m01; + float m10, m11; + float m20, m21; + float m30, m31; + }; +#endif +} mat4x2s; + +typedef union mat4x3s { + mat4x3 raw; + vec3s col[4]; /* [col (4), row (3)] */ +#if CGLM_USE_ANONYMOUS_STRUCT + struct { + float m00, m01, m02; + float m10, m11, m12; + float m20, m21, m22; + float m30, m31, m32; + }; +#endif +} mat4x3s; + +#endif /* cglm_types_struct_h */ diff --git a/external/cglm/types.h b/external/cglm/types.h new file mode 100644 index 0000000..7a482c0 --- /dev/null +++ b/external/cglm/types.h @@ -0,0 +1,144 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_types_h +#define cglm_types_h + +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) +# include +#endif + +#if defined(_MSC_VER) +/* do not use alignment for older visual studio versions */ +/* also ARM32 also causes similar error, disable it for now on ARM32 too */ +# if _MSC_VER < 1913 || _M_ARM /* Visual Studio 2017 version 15.6 */ +# define CGLM_ALL_UNALIGNED +# define CGLM_ALIGN(X) /* no alignment */ +# else +# define CGLM_ALIGN(X) __declspec(align(X)) +# endif +#else +# define CGLM_ALIGN(X) __attribute((aligned(X))) +#endif + +#ifndef CGLM_ALL_UNALIGNED +# define CGLM_ALIGN_IF(X) CGLM_ALIGN(X) +#else +# define CGLM_ALIGN_IF(X) /* no alignment */ +#endif + +#ifdef __AVX__ +# define CGLM_ALIGN_MAT CGLM_ALIGN(32) +#else +# define CGLM_ALIGN_MAT CGLM_ALIGN(16) +#endif + +#ifndef CGLM_HAVE_BUILTIN_ASSUME_ALIGNED + +# if defined(__has_builtin) +# if __has_builtin(__builtin_assume_aligned) +# define CGLM_HAVE_BUILTIN_ASSUME_ALIGNED 1 +# endif +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) +# if __GNUC__ >= 4 && __GNUC_MINOR__ >= 7 +# define CGLM_HAVE_BUILTIN_ASSUME_ALIGNED 1 +# endif +# endif + +# ifndef CGLM_HAVE_BUILTIN_ASSUME_ALIGNED +# define CGLM_HAVE_BUILTIN_ASSUME_ALIGNED 0 +# endif + +#endif + +#if CGLM_HAVE_BUILTIN_ASSUME_ALIGNED +# define CGLM_ASSUME_ALIGNED(expr, alignment) \ + __builtin_assume_aligned((expr), (alignment)) +#else +# define CGLM_ASSUME_ALIGNED(expr, alignment) (expr) +#endif + +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) +# define CGLM_CASTPTR_ASSUME_ALIGNED(expr, type) \ + ((type*)CGLM_ASSUME_ALIGNED((expr), alignof(type))) +#elif defined(_MSC_VER) +# define CGLM_CASTPTR_ASSUME_ALIGNED(expr, type) \ + ((type*)CGLM_ASSUME_ALIGNED((expr), __alignof(type))) +#else +# define CGLM_CASTPTR_ASSUME_ALIGNED(expr, type) \ + ((type*)CGLM_ASSUME_ALIGNED((expr), __alignof__(type))) +#endif + +typedef int ivec2[2]; +typedef int ivec3[3]; +typedef int ivec4[4]; + +typedef float vec2[2]; +typedef float vec3[3]; +typedef CGLM_ALIGN_IF(16) float vec4[4]; +typedef vec4 versor; /* |x, y, z, w| -> w is the last */ +typedef vec3 mat3[3]; +typedef vec2 mat3x2[3]; /* [col (3), row (2)] */ +typedef vec4 mat3x4[3]; /* [col (3), row (4)] */ +typedef CGLM_ALIGN_IF(16) vec2 mat2[2]; +typedef vec3 mat2x3[2]; /* [col (2), row (3)] */ +typedef vec4 mat2x4[2]; /* [col (2), row (4)] */ +typedef CGLM_ALIGN_MAT vec4 mat4[4]; +typedef vec2 mat4x2[4]; /* [col (4), row (2)] */ +typedef vec3 mat4x3[4]; /* [col (4), row (3)] */ + +/* + Important: cglm stores quaternion as [x, y, z, w] in memory since v0.4.0 + it was [w, x, y, z] before v0.4.0 ( v0.3.5 and earlier ). w is real part. +*/ + +#define GLM_E 2.71828182845904523536028747135266250 /* e */ +#define GLM_LOG2E 1.44269504088896340735992468100189214 /* log2(e) */ +#define GLM_LOG10E 0.434294481903251827651128918916605082 /* log10(e) */ +#define GLM_LN2 0.693147180559945309417232121458176568 /* loge(2) */ +#define GLM_LN10 2.30258509299404568401799145468436421 /* loge(10) */ +#define GLM_PI 3.14159265358979323846264338327950288 /* pi */ +#define GLM_PI_2 1.57079632679489661923132169163975144 /* pi/2 */ +#define GLM_PI_4 0.785398163397448309615660845819875721 /* pi/4 */ +#define GLM_1_PI 0.318309886183790671537767526745028724 /* 1/pi */ +#define GLM_2_PI 0.636619772367581343075535053490057448 /* 2/pi */ +#define GLM_TAU 6.283185307179586476925286766559005768 /* tau */ +#define GLM_TAU_2 GLM_PI /* tau/2 */ +#define GLM_TAU_4 GLM_PI_2 /* tau/4 */ +#define GLM_1_TAU 0.159154943091895335768883763372514362 /* 1/tau */ +#define GLM_2_TAU 0.318309886183790671537767526745028724 /* 2/tau */ +#define GLM_2_SQRTPI 1.12837916709551257389615890312154517 /* 2/sqrt(pi) */ +#define GLM_SQRTTAU 2.506628274631000502415765284811045253 /* sqrt(tau) */ +#define GLM_SQRT2 1.41421356237309504880168872420969808 /* sqrt(2) */ +#define GLM_SQRT1_2 0.707106781186547524400844362104849039 /* 1/sqrt(2) */ + +#define GLM_Ef ((float)GLM_E) +#define GLM_LOG2Ef ((float)GLM_LOG2E) +#define GLM_LOG10Ef ((float)GLM_LOG10E) +#define GLM_LN2f ((float)GLM_LN2) +#define GLM_LN10f ((float)GLM_LN10) +#define GLM_PIf ((float)GLM_PI) +#define GLM_PI_2f ((float)GLM_PI_2) +#define GLM_PI_4f ((float)GLM_PI_4) +#define GLM_1_PIf ((float)GLM_1_PI) +#define GLM_2_PIf ((float)GLM_2_PI) +#define GLM_TAUf ((float)GLM_TAU) +#define GLM_TAU_2f ((float)GLM_TAU_2) +#define GLM_TAU_4f ((float)GLM_TAU_4) +#define GLM_1_TAUf ((float)GLM_1_TAU) +#define GLM_2_TAUf ((float)GLM_2_TAU) +#define GLM_2_SQRTPIf ((float)GLM_2_SQRTPI) +#define GLM_2_SQRTTAUf ((float)GLM_SQRTTAU) +#define GLM_SQRT2f ((float)GLM_SQRT2) +#define GLM_SQRT1_2f ((float)GLM_SQRT1_2) + +/* DEPRECATED! use GLM_PI and friends */ +#define CGLM_PI GLM_PIf +#define CGLM_PI_2 GLM_PI_2f +#define CGLM_PI_4 GLM_PI_4f + +#endif /* cglm_types_h */ diff --git a/external/cglm/util.h b/external/cglm/util.h new file mode 100644 index 0000000..8c5f2cb --- /dev/null +++ b/external/cglm/util.h @@ -0,0 +1,375 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE int glm_sign(int val); + CGLM_INLINE float glm_signf(float val); + CGLM_INLINE float glm_rad(float deg); + CGLM_INLINE float glm_deg(float rad); + CGLM_INLINE void glm_make_rad(float *deg); + CGLM_INLINE void glm_make_deg(float *rad); + CGLM_INLINE float glm_pow2(float x); + CGLM_INLINE float glm_min(float a, float b); + CGLM_INLINE float glm_max(float a, float b); + CGLM_INLINE float glm_clamp(float val, float minVal, float maxVal); + CGLM_INLINE float glm_clamp_zo(float val, float minVal, float maxVal); + CGLM_INLINE float glm_lerp(float from, float to, float t); + CGLM_INLINE float glm_lerpc(float from, float to, float t); + CGLM_INLINE float glm_step(float edge, float x); + CGLM_INLINE float glm_smooth(float t); + CGLM_INLINE float glm_smoothstep(float edge0, float edge1, float x); + CGLM_INLINE float glm_smoothinterp(float from, float to, float t); + CGLM_INLINE float glm_smoothinterpc(float from, float to, float t); + CGLM_INLINE bool glm_eq(float a, float b); + CGLM_INLINE float glm_percent(float from, float to, float current); + CGLM_INLINE float glm_percentc(float from, float to, float current); + */ + +#ifndef cglm_util_h +#define cglm_util_h + +#include "common.h" + +#define GLM_MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) +#define GLM_MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) + +/*! + * @brief get sign of 32 bit integer as +1, -1, 0 + * + * Important: It returns 0 for zero input + * + * @param val integer value + */ +CGLM_INLINE +int +glm_sign(int val) { + return ((val >> 31) - (-val >> 31)); +} + +/*! + * @brief get sign of 32 bit float as +1, -1, 0 + * + * Important: It returns 0 for zero/NaN input + * + * @param val float value + */ +CGLM_INLINE +float +glm_signf(float val) { + return (float)((val > 0.0f) - (val < 0.0f)); +} + +/*! + * @brief convert degree to radians + * + * @param[in] deg angle in degrees + */ +CGLM_INLINE +float +glm_rad(float deg) { + return deg * GLM_PIf / 180.0f; +} + +/*! + * @brief convert radians to degree + * + * @param[in] rad angle in radians + */ +CGLM_INLINE +float +glm_deg(float rad) { + return rad * 180.0f / GLM_PIf; +} + +/*! + * @brief convert existing degree to radians. this will override degrees value + * + * @param[in, out] deg pointer to angle in degrees + */ +CGLM_INLINE +void +glm_make_rad(float *deg) { + *deg = *deg * GLM_PIf / 180.0f; +} + +/*! + * @brief convert existing radians to degree. this will override radians value + * + * @param[in, out] rad pointer to angle in radians + */ +CGLM_INLINE +void +glm_make_deg(float *rad) { + *rad = *rad * 180.0f / GLM_PIf; +} + +/*! + * @brief multiplies given parameter with itself = x * x or powf(x, 2) + * + * @param[in] x x + */ +CGLM_INLINE +float +glm_pow2(float x) { + return x * x; +} + +/*! + * @brief find minimum of given two values + * + * @param[in] a number 1 + * @param[in] b number 2 + */ +CGLM_INLINE +float +glm_min(float a, float b) { + if (a < b) + return a; + return b; +} + +/*! + * @brief find maximum of given two values + * + * @param[in] a number 1 + * @param[in] b number 2 + */ +CGLM_INLINE +float +glm_max(float a, float b) { + if (a > b) + return a; + return b; +} + +/*! + * @brief find minimum of given two values + * + * @param[in] a number 1 + * @param[in] b number 2 + * + * @return smallest of the two values + */ +CGLM_INLINE +int +glm_imin(int a, int b) { + if (a < b) + return a; + return b; +} + +/*! + * @brief find maximum of given two values + * + * @param[in] a number 1 + * @param[in] b number 2 + * + * @return largest of the two values + */ +CGLM_INLINE +int +glm_imax(int a, int b) { + if (a > b) + return a; + return b; +} + +/*! + * @brief clamp a number between min and max + * + * @param[in] val value to clamp + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + */ +CGLM_INLINE +float +glm_clamp(float val, float minVal, float maxVal) { + return glm_min(glm_max(val, minVal), maxVal); +} + +/*! + * @brief clamp a number to zero and one + * + * @param[in] val value to clamp + */ +CGLM_INLINE +float +glm_clamp_zo(float val) { + return glm_clamp(val, 0.0f, 1.0f); +} + +/*! + * @brief linear interpolation between two numbers + * + * formula: from + t * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + */ +CGLM_INLINE +float +glm_lerp(float from, float to, float t) { + return from + t * (to - from); +} + +/*! + * @brief clamped linear interpolation between two numbers + * + * formula: from + t * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + */ +CGLM_INLINE +float +glm_lerpc(float from, float to, float t) { + return glm_lerp(from, to, glm_clamp_zo(t)); +} + +/*! + * @brief threshold function + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @return returns 0.0 if x < edge, else 1.0 + */ +CGLM_INLINE +float +glm_step(float edge, float x) { + /* branching - no type conversion */ + return (x < edge) ? 0.0f : 1.0f; + /* + * An alternative implementation without branching + * but with type conversion could be: + * return !(x < edge); + */ +} + +/*! + * @brief smooth Hermite interpolation + * + * formula: t^2 * (3-2t) + * + * @param[in] t interpolant (amount) + */ +CGLM_INLINE +float +glm_smooth(float t) { + return t * t * (3.0f - 2.0f * t); +} + +/*! + * @brief threshold function with a smooth transition (according to OpenCL specs) + * + * formula: t^2 * (3-2t) + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x interpolant (amount) + */ +CGLM_INLINE +float +glm_smoothstep(float edge0, float edge1, float x) { + float t; + t = glm_clamp_zo((x - edge0) / (edge1 - edge0)); + return glm_smooth(t); +} + +/*! + * @brief smoothstep interpolation between two numbers + * + * formula: from + smoothstep(t) * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + */ +CGLM_INLINE +float +glm_smoothinterp(float from, float to, float t) { + return from + glm_smooth(t) * (to - from); +} + +/*! + * @brief clamped smoothstep interpolation between two numbers + * + * formula: from + smoothstep(t) * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + */ +CGLM_INLINE +float +glm_smoothinterpc(float from, float to, float t) { + return glm_smoothinterp(from, to, glm_clamp_zo(t)); +} + +/*! + * @brief check if two float equal with using EPSILON + * + * @param[in] a a + * @param[in] b b + */ +CGLM_INLINE +bool +glm_eq(float a, float b) { + return fabsf(a - b) <= GLM_FLT_EPSILON; +} + +/*! + * @brief percentage of current value between start and end value + * + * maybe fraction could be alternative name. + * + * @param[in] from from value + * @param[in] to to value + * @param[in] current current value + */ +CGLM_INLINE +float +glm_percent(float from, float to, float current) { + float t; + + if ((t = to - from) == 0.0f) + return 1.0f; + + return (current - from) / t; +} + +/*! + * @brief clamped percentage of current value between start and end value + * + * @param[in] from from value + * @param[in] to to value + * @param[in] current current value + */ +CGLM_INLINE +float +glm_percentc(float from, float to, float current) { + return glm_clamp_zo(glm_percent(from, to, current)); +} + +/*! +* @brief swap two float values +* +* @param[in] a float value 1 (pointer) +* @param[in] b float value 2 (pointer) +*/ +CGLM_INLINE +void +glm_swapf(float * __restrict a, float * __restrict b) { + float t; + t = *a; + *a = *b; + *b = t; +} + +#endif /* cglm_util_h */ diff --git a/external/cglm/vec2-ext.h b/external/cglm/vec2-ext.h new file mode 100644 index 0000000..6186f07 --- /dev/null +++ b/external/cglm/vec2-ext.h @@ -0,0 +1,337 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Functions: + CGLM_INLINE void glm_vec2_fill(vec2 v, float val) + CGLM_INLINE bool glm_vec2_eq(vec2 v, float val); + CGLM_INLINE bool glm_vec2_eq_eps(vec2 v, float val); + CGLM_INLINE bool glm_vec2_eq_all(vec2 v); + CGLM_INLINE bool glm_vec2_eqv(vec2 a, vec2 b); + CGLM_INLINE bool glm_vec2_eqv_eps(vec2 a, vec2 b); + CGLM_INLINE float glm_vec2_max(vec2 v); + CGLM_INLINE float glm_vec2_min(vec2 v); + CGLM_INLINE bool glm_vec2_isnan(vec2 v); + CGLM_INLINE bool glm_vec2_isinf(vec2 v); + CGLM_INLINE bool glm_vec2_isvalid(vec2 v); + CGLM_INLINE void glm_vec2_sign(vec2 v, vec2 dest); + CGLM_INLINE void glm_vec2_abs(vec2 v, vec2 dest); + CGLM_INLINE void glm_vec2_fract(vec2 v, vec2 dest); + CGLM_INLINE void glm_vec2_floor(vec2 v, vec2 dest); + CGLM_INLINE float glm_vec2_mods(vec2 v, float s, vec2 dest); + CGLM_INLINE float glm_vec2_steps(float edge, vec2 v, vec2 dest); + CGLM_INLINE void glm_vec2_stepr(vec2 edge, float v, vec2 dest); + CGLM_INLINE void glm_vec2_sqrt(vec2 v, vec2 dest); + CGLM_INLINE void glm_vec2_complex_mul(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_complex_div(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_complex_conjugate(vec2 a, vec2 dest) + */ + +#ifndef cglm_vec2_ext_h +#define cglm_vec2_ext_h + +#include "common.h" +#include "util.h" + +/*! + * @brief fill a vector with specified value + * + * @param[out] v dest + * @param[in] val value + */ +CGLM_INLINE +void +glm_vec2_fill(vec2 v, float val) { + v[0] = v[1] = val; +} + +/*! + * @brief check if vector is equal to value (without epsilon) + * + * @param[in] v vector + * @param[in] val value + */ +CGLM_INLINE +bool +glm_vec2_eq(vec2 v, float val) { + return v[0] == val && v[0] == v[1]; +} + +/*! + * @brief check if vector is equal to value (with epsilon) + * + * @param[in] v vector + * @param[in] val value + */ +CGLM_INLINE +bool +glm_vec2_eq_eps(vec2 v, float val) { + return fabsf(v[0] - val) <= GLM_FLT_EPSILON + && fabsf(v[1] - val) <= GLM_FLT_EPSILON; +} + +/*! + * @brief check if vector members are equal (without epsilon) + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec2_eq_all(vec2 v) { + return glm_vec2_eq_eps(v, v[0]); +} + +/*! + * @brief check if vector is equal to another (without epsilon) + * + * @param[in] a vector + * @param[in] b vector + */ +CGLM_INLINE +bool +glm_vec2_eqv(vec2 a, vec2 b) { + return a[0] == b[0] && a[1] == b[1]; +} + +/*! + * @brief check if vector is equal to another (with epsilon) + * + * @param[in] a vector + * @param[in] b vector + */ +CGLM_INLINE +bool +glm_vec2_eqv_eps(vec2 a, vec2 b) { + return fabsf(a[0] - b[0]) <= GLM_FLT_EPSILON + && fabsf(a[1] - b[1]) <= GLM_FLT_EPSILON; +} + +/*! + * @brief max value of vector + * + * @param[in] v vector + */ +CGLM_INLINE +float +glm_vec2_max(vec2 v) { + return glm_max(v[0], v[1]); +} + +/*! + * @brief min value of vector + * + * @param[in] v vector + */ +CGLM_INLINE +float +glm_vec2_min(vec2 v) { + return glm_min(v[0], v[1]); +} + +/*! + * @brief check if one of items is NaN (not a number) + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec2_isnan(vec2 v) { +#ifndef CGLM_FAST_MATH + return isnan(v[0]) || isnan(v[1]); +#else + return false; +#endif +} + +/*! + * @brief check if one of items is INFINITY + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec2_isinf(vec2 v) { +#ifndef CGLM_FAST_MATH + return isinf(v[0]) || isinf(v[1]); +#else + return false; +#endif +} + +/*! + * @brief check if all items are valid number + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec2_isvalid(vec2 v) { + return !glm_vec2_isnan(v) && !glm_vec2_isinf(v); +} + +/*! + * @brief get sign of 32 bit float as +1, -1, 0 + * + * Important: It returns 0 for zero/NaN input + * + * @param v vector + */ +CGLM_INLINE +void +glm_vec2_sign(vec2 v, vec2 dest) { + dest[0] = glm_signf(v[0]); + dest[1] = glm_signf(v[1]); +} + +/*! + * @brief absolute value of v + * + * @param[in] v vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2_abs(vec2 v, vec2 dest) { + dest[0] = fabsf(v[0]); + dest[1] = fabsf(v[1]); +} + +/*! + * @brief fractional part of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_fract(vec2 v, vec2 dest) { + dest[0] = fminf(v[0] - floorf(v[0]), 0.999999940395355224609375f); + dest[1] = fminf(v[1] - floorf(v[1]), 0.999999940395355224609375f); +} + +/*! + * @brief floor of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_floor(vec2 v, vec2 dest) { + dest[0] = floorf(v[0]); + dest[1] = floorf(v[1]); +} + +/*! + * @brief mod of each vector item, result is written to dest (dest = v % s) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_mods(vec2 v, float s, vec2 dest) { + dest[0] = fmodf(v[0], s); + dest[1] = fmodf(v[1], s); +} + +/*! + * @brief square root of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_sqrt(vec2 v, vec2 dest) { + dest[0] = sqrtf(v[0]); + dest[1] = sqrtf(v[1]); +} + +/*! + * @brief treat vectors as complex numbers and multiply them as such. + * + * @param[in] a left number + * @param[in] b right number + * @param[out] dest destination number + */ +CGLM_INLINE +void +glm_vec2_complex_mul(vec2 a, vec2 b, vec2 dest) { + float tr, ti; + tr = a[0] * b[0] - a[1] * b[1]; + ti = a[0] * b[1] + a[1] * b[0]; + dest[0] = tr; + dest[1] = ti; +} + +/*! + * @brief threshold each vector item with scalar + * condition is: (x[i] < edge) ? 0.0 : 1.0 + * + * @param[in] edge threshold + * @param[in] x vector to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2_steps(float edge, vec2 x, vec2 dest) { + dest[0] = glm_step(edge, x[0]); + dest[1] = glm_step(edge, x[1]); +} + +/*! + * @brief threshold a value with *vector* as the threshold + * condition is: (x < edge[i]) ? 0.0 : 1.0 + * + * @param[in] edge threshold vector + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2_stepr(vec2 edge, float x, vec2 dest) { + dest[0] = glm_step(edge[0], x); + dest[1] = glm_step(edge[1], x); +} + +/*! + * @brief treat vectors as complex numbers and divide them as such. + * + * @param[in] a left number (numerator) + * @param[in] b right number (denominator) + * @param[out] dest destination number + */ +CGLM_INLINE +void +glm_vec2_complex_div(vec2 a, vec2 b, vec2 dest) { + float tr, ti; + float const ibnorm2 = 1.0f / (b[0] * b[0] + b[1] * b[1]); + tr = ibnorm2 * (a[0] * b[0] + a[1] * b[1]); + ti = ibnorm2 * (a[1] * b[0] - a[0] * b[1]); + dest[0] = tr; + dest[1] = ti; +} + +/*! + * @brief treat the vector as a complex number and conjugate it as such. + * + * @param[in] a the number + * @param[out] dest destination number + */ +CGLM_INLINE +void +glm_vec2_complex_conjugate(vec2 a, vec2 dest) { + dest[0] = a[0]; + dest[1] = -a[1]; +} + +#endif /* cglm_vec2_ext_h */ diff --git a/external/cglm/vec2.h b/external/cglm/vec2.h new file mode 100644 index 0000000..655fb4b --- /dev/null +++ b/external/cglm/vec2.h @@ -0,0 +1,798 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_VEC2_ONE_INIT + GLM_VEC2_ZERO_INIT + GLM_VEC2_ONE + GLM_VEC2_ZERO + + Functions: + CGLM_INLINE void glm_vec2(float * __restrict v, vec2 dest) + CGLM_INLINE void glm_vec2_copy(vec2 a, vec2 dest) + CGLM_INLINE void glm_vec2_zero(vec2 v) + CGLM_INLINE void glm_vec2_one(vec2 v) + CGLM_INLINE float glm_vec2_dot(vec2 a, vec2 b) + CGLM_INLINE float glm_vec2_cross(vec2 a, vec2 b) + CGLM_INLINE float glm_vec2_norm2(vec2 v) + CGLM_INLINE float glm_vec2_norm(vec2 vec) + CGLM_INLINE void glm_vec2_add(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_adds(vec2 v, float s, vec2 dest) + CGLM_INLINE void glm_vec2_sub(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_subs(vec2 v, float s, vec2 dest) + CGLM_INLINE void glm_vec2_mul(vec2 a, vec2 b, vec2 d) + CGLM_INLINE void glm_vec2_scale(vec2 v, float s, vec2 dest) + CGLM_INLINE void glm_vec2_scale_as(vec2 v, float s, vec2 dest) + CGLM_INLINE void glm_vec2_div(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_divs(vec2 v, float s, vec2 dest) + CGLM_INLINE void glm_vec2_addadd(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_subadd(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_muladd(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_muladds(vec2 a, float s, vec2 dest) + CGLM_INLINE void glm_vec2_maxadd(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_minadd(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_subsub(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_addsub(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_mulsub(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_mulsubs(vec2 a, float s, vec2 dest) + CGLM_INLINE void glm_vec2_maxsub(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_minsub(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE void glm_vec2_negate_to(vec2 v, vec2 dest) + CGLM_INLINE void glm_vec2_negate(vec2 v) + CGLM_INLINE void glm_vec2_normalize(vec2 v) + CGLM_INLINE void glm_vec2_normalize_to(vec2 vec, vec2 dest) + CGLM_INLINE void glm_vec2_rotate(vec2 v, float angle, vec2 dest) + CGLM_INLINE void glm_vec2_center(vec2 a, vec2 b, vec2 dest) + CGLM_INLINE float glm_vec2_distance2(vec2 a, vec2 b) + CGLM_INLINE float glm_vec2_distance(vec2 a, vec2 b) + CGLM_INLINE void glm_vec2_maxv(vec2 v1, vec2 v2, vec2 dest) + CGLM_INLINE void glm_vec2_minv(vec2 v1, vec2 v2, vec2 dest) + CGLM_INLINE void glm_vec2_clamp(vec2 v, float minVal, float maxVal) + CGLM_INLINE void glm_vec2_swizzle(vec2 v, int mask, vec2 dest) + CGLM_INLINE void glm_vec2_lerp(vec2 from, vec2 to, float t, vec2 dest) + CGLM_INLINE void glm_vec2_step(vec2 edge, vec2 x, vec2 dest) + CGLM_INLINE void glm_vec2_make(float * restrict src, vec2 dest) + CGLM_INLINE void glm_vec2_reflect(vec2 v, vec2 n, vec2 dest) + CGLM_INLINE void glm_vec2_refract(vec2 v, vec2 n, float eta, vec2 dest) + */ + +#ifndef cglm_vec2_h +#define cglm_vec2_h + +#include "common.h" +#include "util.h" +#include "vec2-ext.h" + +#define GLM_VEC2_ONE_INIT {1.0f, 1.0f} +#define GLM_VEC2_ZERO_INIT {0.0f, 0.0f} + +#define GLM_VEC2_ONE ((vec2)GLM_VEC2_ONE_INIT) +#define GLM_VEC2_ZERO ((vec2)GLM_VEC2_ZERO_INIT) + +/*! + * @brief init vec2 using another vector + * + * @param[in] v a vector + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2(float * __restrict v, vec2 dest) { + dest[0] = v[0]; + dest[1] = v[1]; +} + +/*! + * @brief copy all members of [a] to [dest] + * + * @param[in] a source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2_copy(vec2 a, vec2 dest) { + dest[0] = a[0]; + dest[1] = a[1]; +} + +/*! + * @brief make vector zero + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec2_zero(vec2 v) { + v[0] = v[1] = 0.0f; +} + +/*! + * @brief make vector one + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec2_one(vec2 v) { + v[0] = v[1] = 1.0f; +} + +/*! + * @brief vec2 dot product + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return dot product + */ +CGLM_INLINE +float +glm_vec2_dot(vec2 a, vec2 b) { + return a[0] * b[0] + a[1] * b[1]; +} + +/*! + * @brief vec2 cross product + * + * REF: http://allenchou.net/2013/07/cross-product-of-2d-vectors/ + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return Z component of cross product + */ +CGLM_INLINE +float +glm_vec2_cross(vec2 a, vec2 b) { + /* just calculate the z-component */ + return a[0] * b[1] - a[1] * b[0]; +} + +/*! + * @brief norm * norm (magnitude) of vec + * + * we can use this func instead of calling norm * norm, because it would call + * sqrtf function twice but with this func we can avoid func call, maybe this is + * not good name for this func + * + * @param[in] v vector + * + * @return norm * norm + */ +CGLM_INLINE +float +glm_vec2_norm2(vec2 v) { + return glm_vec2_dot(v, v); +} + +/*! + * @brief norm (magnitude) of vec2 + * + * @param[in] vec vector + * + * @return norm + */ +CGLM_INLINE +float +glm_vec2_norm(vec2 vec) { + return sqrtf(glm_vec2_norm2(vec)); +} + +/*! + * @brief add a vector to b vector store result in dest + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_add(vec2 a, vec2 b, vec2 dest) { + dest[0] = a[0] + b[0]; + dest[1] = a[1] + b[1]; +} + +/*! + * @brief add scalar to v vector store result in dest (d = v + s) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_adds(vec2 v, float s, vec2 dest) { + dest[0] = v[0] + s; + dest[1] = v[1] + s; +} + +/*! + * @brief subtract b vector from a vector store result in dest + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_sub(vec2 a, vec2 b, vec2 dest) { + dest[0] = a[0] - b[0]; + dest[1] = a[1] - b[1]; +} + +/*! + * @brief subtract scalar from v vector store result in dest (d = v - s) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_subs(vec2 v, float s, vec2 dest) { + dest[0] = v[0] - s; + dest[1] = v[1] - s; +} + +/*! + * @brief multiply two vectors (component-wise multiplication) + * + * @param a v1 + * @param b v2 + * @param dest v3 = (a[0] * b[0], a[1] * b[1]) + */ +CGLM_INLINE +void +glm_vec2_mul(vec2 a, vec2 b, vec2 dest) { + dest[0] = a[0] * b[0]; + dest[1] = a[1] * b[1]; +} + +/*! + * @brief multiply/scale vector with scalar: result = v * s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_scale(vec2 v, float s, vec2 dest) { + dest[0] = v[0] * s; + dest[1] = v[1] * s; +} + +/*! + * @brief scale as vector specified: result = unit(v) * s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_scale_as(vec2 v, float s, vec2 dest) { + float norm; + norm = glm_vec2_norm(v); + + if (CGLM_UNLIKELY(norm < FLT_EPSILON)) { + glm_vec2_zero(dest); + return; + } + + glm_vec2_scale(v, s / norm, dest); +} + +/*! + * @brief div vector with another component-wise division: d = a / b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest result = (a[0]/b[0], a[1]/b[1]) + */ +CGLM_INLINE +void +glm_vec2_div(vec2 a, vec2 b, vec2 dest) { + dest[0] = a[0] / b[0]; + dest[1] = a[1] / b[1]; +} + +/*! + * @brief div vector with scalar: d = v / s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest result = (a[0]/s, a[1]/s) + */ +CGLM_INLINE +void +glm_vec2_divs(vec2 v, float s, vec2 dest) { + dest[0] = v[0] / s; + dest[1] = v[1] / s; +} + +/*! + * @brief add two vectors and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a + b) + */ +CGLM_INLINE +void +glm_vec2_addadd(vec2 a, vec2 b, vec2 dest) { + dest[0] += a[0] + b[0]; + dest[1] += a[1] + b[1]; +} + +/*! + * @brief sub two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a + b) + */ +CGLM_INLINE +void +glm_vec2_subadd(vec2 a, vec2 b, vec2 dest) { + dest[0] += a[0] - b[0]; + dest[1] += a[1] - b[1]; +} + +/*! + * @brief mul two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_vec2_muladd(vec2 a, vec2 b, vec2 dest) { + dest[0] += a[0] * b[0]; + dest[1] += a[1] * b[1]; +} + +/*! + * @brief mul vector with scalar and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_vec2_muladds(vec2 a, float s, vec2 dest) { + dest[0] += a[0] * s; + dest[1] += a[1] * s; +} + +/*! + * @brief add max of two vectors to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += max(a, b) + */ +CGLM_INLINE +void +glm_vec2_maxadd(vec2 a, vec2 b, vec2 dest) { + dest[0] += glm_max(a[0], b[0]); + dest[1] += glm_max(a[1], b[1]); +} + +/*! + * @brief add min of two vectors to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += min(a, b) + */ +CGLM_INLINE +void +glm_vec2_minadd(vec2 a, vec2 b, vec2 dest) { + dest[0] += glm_min(a[0], b[0]); + dest[1] += glm_min(a[1], b[1]); +} + +/*! + * @brief sub two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= (a - b) + */ +CGLM_INLINE +void +glm_vec2_subsub(vec2 a, vec2 b, vec2 dest) { + dest[0] -= a[0] - b[0]; + dest[1] -= a[1] - b[1]; +} + +/*! + * @brief add two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= (a + b) + */ +CGLM_INLINE +void +glm_vec2_addsub(vec2 a, vec2 b, vec2 dest) { + dest[0] -= a[0] + b[0]; + dest[1] -= a[1] + b[1]; +} + +/*! + * @brief mul two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= (a * b) + */ +CGLM_INLINE +void +glm_vec2_mulsub(vec2 a, vec2 b, vec2 dest) { + dest[0] -= a[0] * b[0]; + dest[1] -= a[1] * b[1]; +} + +/*! + * @brief mul vector with scalar and sub result to sum + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest -= (a * b) + */ +CGLM_INLINE +void +glm_vec2_mulsubs(vec2 a, float s, vec2 dest) { + dest[0] -= a[0] * s; + dest[1] -= a[1] * s; +} + +/*! + * @brief sub max of two vectors to result/dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= max(a, b) + */ +CGLM_INLINE +void +glm_vec2_maxsub(vec2 a, vec2 b, vec2 dest) { + dest[0] -= glm_max(a[0], b[0]); + dest[1] -= glm_max(a[1], b[1]); +} + +/*! + * @brief sub min of two vectors to result/dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= min(a, b) + */ +CGLM_INLINE +void +glm_vec2_minsub(vec2 a, vec2 b, vec2 dest) { + dest[0] -= glm_min(a[0], b[0]); + dest[1] -= glm_min(a[1], b[1]); +} + +/*! + * @brief negate vector components and store result in dest + * + * @param[in] v vector + * @param[out] dest result vector + */ +CGLM_INLINE +void +glm_vec2_negate_to(vec2 v, vec2 dest) { + dest[0] = -v[0]; + dest[1] = -v[1]; +} + +/*! + * @brief negate vector components + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec2_negate(vec2 v) { + glm_vec2_negate_to(v, v); +} + +/*! + * @brief normalize vector and store result in same vec + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec2_normalize(vec2 v) { + float norm; + + norm = glm_vec2_norm(v); + + if (CGLM_UNLIKELY(norm < FLT_EPSILON)) { + v[0] = v[1] = 0.0f; + return; + } + + glm_vec2_scale(v, 1.0f / norm, v); +} + +/*! + * @brief normalize vector to dest + * + * @param[in] v source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2_normalize_to(vec2 v, vec2 dest) { + float norm; + + norm = glm_vec2_norm(v); + + if (CGLM_UNLIKELY(norm < FLT_EPSILON)) { + glm_vec2_zero(dest); + return; + } + + glm_vec2_scale(v, 1.0f / norm, dest); +} + +/*! + * @brief rotate vec2 around origin by angle (CCW: counterclockwise) + * + * Formula: + * 𝑥2 = cos(a)𝑥1 − sin(a)𝑦1 + * 𝑦2 = sin(a)𝑥1 + cos(a)𝑦1 + * + * @param[in] v vector to rotate + * @param[in] angle angle by radians + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_rotate(vec2 v, float angle, vec2 dest) { + float c, s, x1, y1; + + c = cosf(angle); + s = sinf(angle); + + x1 = v[0]; + y1 = v[1]; + + dest[0] = c * x1 - s * y1; + dest[1] = s * x1 + c * y1; +} + +/** + * @brief find center point of two vector + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest center point + */ +CGLM_INLINE +void +glm_vec2_center(vec2 a, vec2 b, vec2 dest) { + glm_vec2_add(a, b, dest); + glm_vec2_scale(dest, 0.5f, dest); +} + +/** + * @brief squared distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return returns squared distance (distance * distance) + */ +CGLM_INLINE +float +glm_vec2_distance2(vec2 a, vec2 b) { + return glm_pow2(b[0] - a[0]) + glm_pow2(b[1] - a[1]); +} + +/** + * @brief distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return returns distance + */ +CGLM_INLINE +float +glm_vec2_distance(vec2 a, vec2 b) { + return sqrtf(glm_vec2_distance2(a, b)); +} + +/*! + * @brief max values of vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2_maxv(vec2 a, vec2 b, vec2 dest) { + dest[0] = glm_max(a[0], b[0]); + dest[1] = glm_max(a[1], b[1]); +} + +/*! + * @brief min values of vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2_minv(vec2 a, vec2 b, vec2 dest) { + dest[0] = glm_min(a[0], b[0]); + dest[1] = glm_min(a[1], b[1]); +} + +/*! + * @brief clamp vector's individual members between min and max values + * + * @param[in, out] v vector + * @param[in] minval minimum value + * @param[in] maxval maximum value + */ +CGLM_INLINE +void +glm_vec2_clamp(vec2 v, float minval, float maxval) { + v[0] = glm_clamp(v[0], minval, maxval); + v[1] = glm_clamp(v[1], minval, maxval); +} + +/*! + * @brief swizzle vector components + * + * @param[in] v source + * @param[in] mask mask + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2_swizzle(vec2 v, int mask, vec2 dest) { + vec2 t; + + t[0] = v[(mask & (3 << 0))]; + t[1] = v[(mask & (3 << 2)) >> 2]; + + glm_vec2_copy(t, dest); +} + +/*! + * @brief linear interpolation between two vector + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2_lerp(vec2 from, vec2 to, float t, vec2 dest) { + vec2 s, v; + + /* from + s * (to - from) */ + glm_vec2_fill(s, glm_clamp_zo(t)); + glm_vec2_sub(to, from, v); + glm_vec2_mul(s, v, v); + glm_vec2_add(from, v, dest); +} + +/*! + * @brief threshold function + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec2_step(vec2 edge, vec2 x, vec2 dest) { + dest[0] = glm_step(edge[0], x[0]); + dest[1] = glm_step(edge[1], x[1]); +} + +/*! + * @brief Create two dimensional vector from pointer + * + * @param[in] src pointer to an array of floats + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec2_make(const float * __restrict src, vec2 dest) { + dest[0] = src[0]; dest[1] = src[1]; +} + +/*! + * @brief reflection vector using an incident ray and a surface normal + * + * @param[in] v incident vector + * @param[in] n normalized normal vector + * @param[out] dest destination vector for the reflection result + */ +CGLM_INLINE +void +glm_vec2_reflect(vec2 v, vec2 n, vec2 dest) { + vec2 temp; + glm_vec2_scale(n, 2.0f * glm_vec2_dot(v, n), temp); + glm_vec2_sub(v, temp, dest); +} + +/*! + * @brief computes refraction vector for an incident vector and a surface normal. + * + * calculates the refraction vector based on Snell's law. If total internal reflection + * occurs (angle too great given eta), dest is set to zero and returns false. + * Otherwise, computes refraction vector, stores it in dest, and returns true. + * + * @param[in] v normalized incident vector + * @param[in] n normalized normal vector + * @param[in] eta ratio of indices of refraction (incident/transmitted) + * @param[out] dest refraction vector if refraction occurs; zero vector otherwise + * + * @returns true if refraction occurs; false if total internal reflection occurs. + */ +CGLM_INLINE +bool +glm_vec2_refract(vec2 v, vec2 n, float eta, vec2 dest) { + float ndi, eni, k; + + ndi = glm_vec2_dot(n, v); + eni = eta * ndi; + k = 1.0f - eta * eta + eni * eni; + + if (k < 0.0f) { + glm_vec2_zero(dest); + return false; + } + + glm_vec2_scale(v, eta, dest); + glm_vec2_mulsubs(n, eni + sqrtf(k), dest); + return true; +} + +#endif /* cglm_vec2_h */ diff --git a/external/cglm/vec3-ext.h b/external/cglm/vec3-ext.h new file mode 100644 index 0000000..4413cc2 --- /dev/null +++ b/external/cglm/vec3-ext.h @@ -0,0 +1,345 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/*! + * @brief SIMD like functions + */ + +/* + Functions: + CGLM_INLINE void glm_vec3_broadcast(float val, vec3 d); + CGLM_INLINE void glm_vec3_fill(vec3 v, float val); + CGLM_INLINE bool glm_vec3_eq(vec3 v, float val); + CGLM_INLINE bool glm_vec3_eq_eps(vec3 v, float val); + CGLM_INLINE bool glm_vec3_eq_all(vec3 v); + CGLM_INLINE bool glm_vec3_eqv(vec3 a, vec3 b); + CGLM_INLINE bool glm_vec3_eqv_eps(vec3 a, vec3 b); + CGLM_INLINE float glm_vec3_max(vec3 v); + CGLM_INLINE float glm_vec3_min(vec3 v); + CGLM_INLINE bool glm_vec3_isnan(vec3 v); + CGLM_INLINE bool glm_vec3_isinf(vec3 v); + CGLM_INLINE bool glm_vec3_isvalid(vec3 v); + CGLM_INLINE void glm_vec3_sign(vec3 v, vec3 dest); + CGLM_INLINE void glm_vec3_abs(vec3 v, vec3 dest); + CGLM_INLINE void glm_vec3_fract(vec3 v, vec3 dest); + CGLM_INLINE void glm_vec3_floor(vec3 v, vec3 dest); + CGLM_INLINE float glm_vec3_mods(vec3 v, float s, vec3 dest); + CGLM_INLINE float glm_vec3_steps(float edge, vec3 v, vec3 dest); + CGLM_INLINE void glm_vec3_stepr(vec3 edge, float v, vec3 dest); + CGLM_INLINE float glm_vec3_hadd(vec3 v); + CGLM_INLINE void glm_vec3_sqrt(vec3 v, vec3 dest); + */ + +#ifndef cglm_vec3_ext_h +#define cglm_vec3_ext_h + +#include "common.h" +#include "util.h" + +/*! + * @brief fill a vector with specified value + * + * @param[in] val value + * @param[out] d dest + */ +CGLM_INLINE +void +glm_vec3_broadcast(float val, vec3 d) { + d[0] = d[1] = d[2] = val; +} + +/*! + * @brief fill a vector with specified value + * + * @param[out] v dest + * @param[in] val value + */ +CGLM_INLINE +void +glm_vec3_fill(vec3 v, float val) { + v[0] = v[1] = v[2] = val; +} + +/*! + * @brief check if vector is equal to value (without epsilon) + * + * @param[in] v vector + * @param[in] val value + */ +CGLM_INLINE +bool +glm_vec3_eq(vec3 v, float val) { + return v[0] == val && v[0] == v[1] && v[0] == v[2]; +} + +/*! + * @brief check if vector is equal to value (with epsilon) + * + * @param[in] v vector + * @param[in] val value + */ +CGLM_INLINE +bool +glm_vec3_eq_eps(vec3 v, float val) { + return fabsf(v[0] - val) <= GLM_FLT_EPSILON + && fabsf(v[1] - val) <= GLM_FLT_EPSILON + && fabsf(v[2] - val) <= GLM_FLT_EPSILON; +} + +/*! + * @brief check if vector members are equal (without epsilon) + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec3_eq_all(vec3 v) { + return glm_vec3_eq_eps(v, v[0]); +} + +/*! + * @brief check if vector is equal to another (without epsilon) + * + * @param[in] a vector + * @param[in] b vector + */ +CGLM_INLINE +bool +glm_vec3_eqv(vec3 a, vec3 b) { + return a[0] == b[0] + && a[1] == b[1] + && a[2] == b[2]; +} + +/*! + * @brief check if vector is equal to another (with epsilon) + * + * @param[in] a vector + * @param[in] b vector + */ +CGLM_INLINE +bool +glm_vec3_eqv_eps(vec3 a, vec3 b) { + return fabsf(a[0] - b[0]) <= GLM_FLT_EPSILON + && fabsf(a[1] - b[1]) <= GLM_FLT_EPSILON + && fabsf(a[2] - b[2]) <= GLM_FLT_EPSILON; +} + +/*! + * @brief max value of vector + * + * @param[in] v vector + */ +CGLM_INLINE +float +glm_vec3_max(vec3 v) { + float max; + + max = v[0]; + if (v[1] > max) + max = v[1]; + if (v[2] > max) + max = v[2]; + + return max; +} + +/*! + * @brief min value of vector + * + * @param[in] v vector + */ +CGLM_INLINE +float +glm_vec3_min(vec3 v) { + float min; + + min = v[0]; + if (v[1] < min) + min = v[1]; + if (v[2] < min) + min = v[2]; + + return min; +} + +/*! + * @brief check if one of items is NaN (not a number) + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec3_isnan(vec3 v) { +#ifndef CGLM_FAST_MATH + return isnan(v[0]) || isnan(v[1]) || isnan(v[2]); +#else + return false; +#endif +} + +/*! + * @brief check if one of items is INFINITY + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec3_isinf(vec3 v) { +#ifndef CGLM_FAST_MATH + return isinf(v[0]) || isinf(v[1]) || isinf(v[2]); +#else + return false; +#endif +} + +/*! + * @brief check if all items are valid number + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec3_isvalid(vec3 v) { + return !glm_vec3_isnan(v) && !glm_vec3_isinf(v); +} + +/*! + * @brief get sign of 32 bit float as +1, -1, 0 + * + * Important: It returns 0 for zero/NaN input + * + * @param v vector + */ +CGLM_INLINE +void +glm_vec3_sign(vec3 v, vec3 dest) { + dest[0] = glm_signf(v[0]); + dest[1] = glm_signf(v[1]); + dest[2] = glm_signf(v[2]); +} + +/*! + * @brief absolute value of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec3_abs(vec3 v, vec3 dest) { + dest[0] = fabsf(v[0]); + dest[1] = fabsf(v[1]); + dest[2] = fabsf(v[2]); +} + +/*! + * @brief fractional part of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec3_fract(vec3 v, vec3 dest) { + dest[0] = fminf(v[0] - floorf(v[0]), 0.999999940395355224609375f); + dest[1] = fminf(v[1] - floorf(v[1]), 0.999999940395355224609375f); + dest[2] = fminf(v[2] - floorf(v[2]), 0.999999940395355224609375f); +} + +/*! + * @brief floor of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec3_floor(vec3 v, vec3 dest) { + dest[0] = floorf(v[0]); + dest[1] = floorf(v[1]); + dest[2] = floorf(v[2]); +} + +/*! + * @brief mod of each vector item, result is written to dest (dest = v % s) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec3_mods(vec3 v, float s, vec3 dest) { + dest[0] = fmodf(v[0], s); + dest[1] = fmodf(v[1], s); + dest[2] = fmodf(v[2], s); +} + +/*! + * @brief threshold each vector item with scalar + * condition is: (x[i] < edge) ? 0.0 : 1.0 + * + * @param[in] edge threshold + * @param[in] x vector to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_steps(float edge, vec3 x, vec3 dest) { + dest[0] = glm_step(edge, x[0]); + dest[1] = glm_step(edge, x[1]); + dest[2] = glm_step(edge, x[2]); +} + +/*! + * @brief threshold a value with *vector* as the threshold + * condition is: (x < edge[i]) ? 0.0 : 1.0 + * + * @param[in] edge threshold vector + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_stepr(vec3 edge, float x, vec3 dest) { + dest[0] = glm_step(edge[0], x); + dest[1] = glm_step(edge[1], x); + dest[2] = glm_step(edge[2], x); +} + +/*! + * @brief vector reduction by summation + * @warning could overflow + * + * @param[in] v vector + * @return sum of all vector's elements + */ +CGLM_INLINE +float +glm_vec3_hadd(vec3 v) { + return v[0] + v[1] + v[2]; +} + +/*! + * @brief square root of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec3_sqrt(vec3 v, vec3 dest) { + dest[0] = sqrtf(v[0]); + dest[1] = sqrtf(v[1]); + dest[2] = sqrtf(v[2]); +} + +#endif /* cglm_vec3_ext_h */ diff --git a/external/cglm/vec3.h b/external/cglm/vec3.h new file mode 100644 index 0000000..1350818 --- /dev/null +++ b/external/cglm/vec3.h @@ -0,0 +1,1264 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_VEC3_ONE_INIT + GLM_VEC3_ZERO_INIT + GLM_VEC3_ONE + GLM_VEC3_ZERO + GLM_YUP + GLM_ZUP + GLM_XUP + + Functions: + CGLM_INLINE void glm_vec3(vec4 v4, vec3 dest); + CGLM_INLINE void glm_vec3_copy(vec3 a, vec3 dest); + CGLM_INLINE void glm_vec3_zero(vec3 v); + CGLM_INLINE void glm_vec3_one(vec3 v); + CGLM_INLINE float glm_vec3_dot(vec3 a, vec3 b); + CGLM_INLINE float glm_vec3_norm2(vec3 v); + CGLM_INLINE float glm_vec3_norm(vec3 v); + CGLM_INLINE float glm_vec3_norm_one(vec3 v); + CGLM_INLINE float glm_vec3_norm_inf(vec3 v); + CGLM_INLINE void glm_vec3_add(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_adds(vec3 a, float s, vec3 dest); + CGLM_INLINE void glm_vec3_sub(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_subs(vec3 a, float s, vec3 dest); + CGLM_INLINE void glm_vec3_mul(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_scale(vec3 v, float s, vec3 dest); + CGLM_INLINE void glm_vec3_scale_as(vec3 v, float s, vec3 dest); + CGLM_INLINE void glm_vec3_div(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_divs(vec3 a, float s, vec3 dest); + CGLM_INLINE void glm_vec3_addadd(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_subadd(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_muladd(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_muladds(vec3 a, float s, vec3 dest); + CGLM_INLINE void glm_vec3_maxadd(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_minadd(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_subsub(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_addsub(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_mulsub(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_mulsubs(vec3 a, float s, vec3 dest); + CGLM_INLINE void glm_vec3_maxsub(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_minsub(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_flipsign(vec3 v); + CGLM_INLINE void glm_vec3_flipsign_to(vec3 v, vec3 dest); + CGLM_INLINE void glm_vec3_negate_to(vec3 v, vec3 dest); + CGLM_INLINE void glm_vec3_negate(vec3 v); + CGLM_INLINE void glm_vec3_inv(vec3 v); + CGLM_INLINE void glm_vec3_inv_to(vec3 v, vec3 dest); + CGLM_INLINE void glm_vec3_normalize(vec3 v); + CGLM_INLINE void glm_vec3_normalize_to(vec3 v, vec3 dest); + CGLM_INLINE void glm_vec3_cross(vec3 a, vec3 b, vec3 d); + CGLM_INLINE void glm_vec3_crossn(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE float glm_vec3_angle(vec3 a, vec3 b); + CGLM_INLINE void glm_vec3_rotate(vec3 v, float angle, vec3 axis); + CGLM_INLINE void glm_vec3_rotate_m4(mat4 m, vec3 v, vec3 dest); + CGLM_INLINE void glm_vec3_rotate_m3(mat3 m, vec3 v, vec3 dest); + CGLM_INLINE void glm_vec3_proj(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_center(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE float glm_vec3_distance(vec3 a, vec3 b); + CGLM_INLINE float glm_vec3_distance2(vec3 a, vec3 b); + CGLM_INLINE void glm_vec3_maxv(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_minv(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE void glm_vec3_ortho(vec3 v, vec3 dest); + CGLM_INLINE void glm_vec3_clamp(vec3 v, float minVal, float maxVal); + CGLM_INLINE void glm_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest); + CGLM_INLINE void glm_vec3_lerpc(vec3 from, vec3 to, float t, vec3 dest); + CGLM_INLINE void glm_vec3_mix(vec3 from, vec3 to, float t, vec3 dest); + CGLM_INLINE void glm_vec3_mixc(vec3 from, vec3 to, float t, vec3 dest); + CGLM_INLINE void glm_vec3_step(vec3 edge, vec3 x, vec3 dest); + CGLM_INLINE void glm_vec3_smoothstep_uni(float edge0, float edge1, vec3 x, vec3 dest); + CGLM_INLINE void glm_vec3_smoothstep(vec3 edge0, vec3 edge1, vec3 x, vec3 dest); + CGLM_INLINE void glm_vec3_smoothinterp(vec3 from, vec3 to, float t, vec3 dest); + CGLM_INLINE void glm_vec3_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest); + CGLM_INLINE void glm_vec3_swizzle(vec3 v, int mask, vec3 dest); + CGLM_INLINE void glm_vec3_make(float * restrict src, vec3 dest); + CGLM_INLINE void glm_vec3_faceforward(vec3 n, vec3 v, vec3 nref, vec3 dest); + CGLM_INLINE void glm_vec3_reflect(vec3 v, vec3 n, vec3 dest); + CGLM_INLINE void glm_vec3_refract(vec3 v, vec3 n, float eta, vec3 dest); + + Convenient: + CGLM_INLINE void glm_cross(vec3 a, vec3 b, vec3 d); + CGLM_INLINE float glm_dot(vec3 a, vec3 b); + CGLM_INLINE void glm_normalize(vec3 v); + CGLM_INLINE void glm_normalize_to(vec3 v, vec3 dest); + + DEPRECATED: + glm_vec3_dup + glm_vec3_flipsign + glm_vec3_flipsign_to + glm_vec3_inv + glm_vec3_inv_to + glm_vec3_mulv + glm_vec3_step_uni --> use glm_vec3_steps + */ + +#ifndef cglm_vec3_h +#define cglm_vec3_h + +#include "common.h" +#include "vec4.h" +#include "vec3-ext.h" +#include "util.h" + +/* DEPRECATED! use _copy, _ucopy versions */ +#define glm_vec3_dup(v, dest) glm_vec3_copy(v, dest) +#define glm_vec3_flipsign(v) glm_vec3_negate(v) +#define glm_vec3_flipsign_to(v, dest) glm_vec3_negate_to(v, dest) +#define glm_vec3_inv(v) glm_vec3_negate(v) +#define glm_vec3_inv_to(v, dest) glm_vec3_negate_to(v, dest) +#define glm_vec3_mulv(a, b, d) glm_vec3_mul(a, b, d) +#define glm_vec3_step_uni(edge, x, dest) glm_vec3_steps(edge, x, dest) + +#define GLM_VEC3_ONE_INIT {1.0f, 1.0f, 1.0f} +#define GLM_VEC3_ZERO_INIT {0.0f, 0.0f, 0.0f} + +#define GLM_VEC3_ONE ((vec3)GLM_VEC3_ONE_INIT) +#define GLM_VEC3_ZERO ((vec3)GLM_VEC3_ZERO_INIT) + +#define GLM_YUP ((vec3){0.0f, 1.0f, 0.0f}) +#define GLM_ZUP ((vec3){0.0f, 0.0f, 1.0f}) +#define GLM_XUP ((vec3){1.0f, 0.0f, 0.0f}) +#define GLM_FORWARD ((vec3){0.0f, 0.0f, -1.0f}) + +#define GLM_XXX GLM_SHUFFLE3(0, 0, 0) +#define GLM_YYY GLM_SHUFFLE3(1, 1, 1) +#define GLM_ZZZ GLM_SHUFFLE3(2, 2, 2) +#define GLM_ZYX GLM_SHUFFLE3(0, 1, 2) + +/*! + * @brief init vec3 using vec4 + * + * @param[in] v4 vector4 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3(vec4 v4, vec3 dest) { + dest[0] = v4[0]; + dest[1] = v4[1]; + dest[2] = v4[2]; +} + +/*! + * @brief copy all members of [a] to [dest] + * + * @param[in] a source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_copy(vec3 a, vec3 dest) { + dest[0] = a[0]; + dest[1] = a[1]; + dest[2] = a[2]; +} + +/*! + * @brief make vector zero + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec3_zero(vec3 v) { + v[0] = v[1] = v[2] = 0.0f; +} + +/*! + * @brief make vector one + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec3_one(vec3 v) { + v[0] = v[1] = v[2] = 1.0f; +} + +/*! + * @brief vec3 dot product + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return dot product + */ +CGLM_INLINE +float +glm_vec3_dot(vec3 a, vec3 b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} + +/*! + * @brief norm * norm (magnitude) of vec + * + * we can use this func instead of calling norm * norm, because it would call + * sqrtf function twice but with this func we can avoid func call, maybe this is + * not good name for this func + * + * @param[in] v vector + * + * @return norm * norm + */ +CGLM_INLINE +float +glm_vec3_norm2(vec3 v) { + return glm_vec3_dot(v, v); +} + +/*! + * @brief euclidean norm (magnitude), also called L2 norm + * this will give magnitude of vector in euclidean space + * + * @param[in] v vector + * + * @return norm + */ +CGLM_INLINE +float +glm_vec3_norm(vec3 v) { + return sqrtf(glm_vec3_norm2(v)); +} + +/*! + * @brief L1 norm of vec3 + * Also known as Manhattan Distance or Taxicab norm. + * L1 Norm is the sum of the magnitudes of the vectors in a space. + * It is calculated as the sum of the absolute values of the vector components. + * In this norm, all the components of the vector are weighted equally. + * + * This computes: + * R = |v[0]| + |v[1]| + |v[2]| + * + * @param[in] v vector + * + * @return L1 norm + */ +CGLM_INLINE +float +glm_vec3_norm_one(vec3 v) { + vec3 t; + glm_vec3_abs(v, t); + return glm_vec3_hadd(t); +} + +/*! + * @brief infinity norm of vec3 + * Also known as Maximum norm. + * Infinity Norm is the largest magnitude among each element of a vector. + * It is calculated as the maximum of the absolute values of the vector components. + * + * This computes: + * inf norm = max(|v[0]|, |v[1]|, |v[2]|) + * + * @param[in] v vector + * + * @return infinity norm + */ +CGLM_INLINE +float +glm_vec3_norm_inf(vec3 v) { + vec3 t; + glm_vec3_abs(v, t); + return glm_vec3_max(t); +} + +/*! + * @brief add a vector to b vector store result in dest + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec3_add(vec3 a, vec3 b, vec3 dest) { + dest[0] = a[0] + b[0]; + dest[1] = a[1] + b[1]; + dest[2] = a[2] + b[2]; +} + +/*! + * @brief add scalar to v vector store result in dest (d = v + s) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec3_adds(vec3 v, float s, vec3 dest) { + dest[0] = v[0] + s; + dest[1] = v[1] + s; + dest[2] = v[2] + s; +} + +/*! + * @brief subtract b vector from a vector store result in dest + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec3_sub(vec3 a, vec3 b, vec3 dest) { + dest[0] = a[0] - b[0]; + dest[1] = a[1] - b[1]; + dest[2] = a[2] - b[2]; +} + +/*! + * @brief subtract scalar from v vector store result in dest (d = v - s) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec3_subs(vec3 v, float s, vec3 dest) { + dest[0] = v[0] - s; + dest[1] = v[1] - s; + dest[2] = v[2] - s; +} + +/*! + * @brief multiply two vectors (component-wise multiplication) + * + * @param a vector1 + * @param b vector2 + * @param dest v3 = (a[0] * b[0], a[1] * b[1], a[2] * b[2]) + */ +CGLM_INLINE +void +glm_vec3_mul(vec3 a, vec3 b, vec3 dest) { + dest[0] = a[0] * b[0]; + dest[1] = a[1] * b[1]; + dest[2] = a[2] * b[2]; +} + +/*! + * @brief multiply/scale vec3 vector with scalar: result = v * s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec3_scale(vec3 v, float s, vec3 dest) { + dest[0] = v[0] * s; + dest[1] = v[1] * s; + dest[2] = v[2] * s; +} + +/*! + * @brief make vec3 vector scale as specified: result = unit(v) * s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec3_scale_as(vec3 v, float s, vec3 dest) { + float norm; + norm = glm_vec3_norm(v); + + if (CGLM_UNLIKELY(norm < FLT_EPSILON)) { + glm_vec3_zero(dest); + return; + } + + glm_vec3_scale(v, s / norm, dest); +} + +/*! + * @brief div vector with another component-wise division: d = a / b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest result = (a[0]/b[0], a[1]/b[1], a[2]/b[2]) + */ +CGLM_INLINE +void +glm_vec3_div(vec3 a, vec3 b, vec3 dest) { + dest[0] = a[0] / b[0]; + dest[1] = a[1] / b[1]; + dest[2] = a[2] / b[2]; +} + +/*! + * @brief div vector with scalar: d = v / s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest result = (a[0]/s, a[1]/s, a[2]/s) + */ +CGLM_INLINE +void +glm_vec3_divs(vec3 v, float s, vec3 dest) { + dest[0] = v[0] / s; + dest[1] = v[1] / s; + dest[2] = v[2] / s; +} + +/*! + * @brief add two vectors and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a + b) + */ +CGLM_INLINE +void +glm_vec3_addadd(vec3 a, vec3 b, vec3 dest) { + dest[0] += a[0] + b[0]; + dest[1] += a[1] + b[1]; + dest[2] += a[2] + b[2]; +} + +/*! + * @brief sub two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a + b) + */ +CGLM_INLINE +void +glm_vec3_subadd(vec3 a, vec3 b, vec3 dest) { + dest[0] += a[0] - b[0]; + dest[1] += a[1] - b[1]; + dest[2] += a[2] - b[2]; +} + +/*! + * @brief mul two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_vec3_muladd(vec3 a, vec3 b, vec3 dest) { + dest[0] += a[0] * b[0]; + dest[1] += a[1] * b[1]; + dest[2] += a[2] * b[2]; +} + +/*! + * @brief mul vector with scalar and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_vec3_muladds(vec3 a, float s, vec3 dest) { + dest[0] += a[0] * s; + dest[1] += a[1] * s; + dest[2] += a[2] * s; +} + +/*! + * @brief add max of two vectors to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += max(a, b) + */ +CGLM_INLINE +void +glm_vec3_maxadd(vec3 a, vec3 b, vec3 dest) { + dest[0] += glm_max(a[0], b[0]); + dest[1] += glm_max(a[1], b[1]); + dest[2] += glm_max(a[2], b[2]); +} + +/*! + * @brief add min of two vectors to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += min(a, b) + */ +CGLM_INLINE +void +glm_vec3_minadd(vec3 a, vec3 b, vec3 dest) { + dest[0] += glm_min(a[0], b[0]); + dest[1] += glm_min(a[1], b[1]); + dest[2] += glm_min(a[2], b[2]); +} + +/*! + * @brief sub two vectors and sub result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= (a - b) + */ +CGLM_INLINE +void +glm_vec3_subsub(vec3 a, vec3 b, vec3 dest) { + dest[0] -= a[0] - b[0]; + dest[1] -= a[1] - b[1]; + dest[2] -= a[2] - b[2]; +} + +/*! + * @brief add two vectors and sub result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= (a + b) + */ +CGLM_INLINE +void +glm_vec3_addsub(vec3 a, vec3 b, vec3 dest) { + dest[0] -= a[0] + b[0]; + dest[1] -= a[1] + b[1]; + dest[2] -= a[2] + b[2]; +} + +/*! + * @brief mul two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= (a * b) + */ +CGLM_INLINE +void +glm_vec3_mulsub(vec3 a, vec3 b, vec3 dest) { + dest[0] -= a[0] * b[0]; + dest[1] -= a[1] * b[1]; + dest[2] -= a[2] * b[2]; +} + +/*! + * @brief mul vector with scalar and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest -= (a * b) + */ +CGLM_INLINE +void +glm_vec3_mulsubs(vec3 a, float s, vec3 dest) { + dest[0] -= a[0] * s; + dest[1] -= a[1] * s; + dest[2] -= a[2] * s; +} + +/*! + * @brief sub max of two vectors to result/dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= max(a, b) + */ +CGLM_INLINE +void +glm_vec3_maxsub(vec3 a, vec3 b, vec3 dest) { + dest[0] -= glm_max(a[0], b[0]); + dest[1] -= glm_max(a[1], b[1]); + dest[2] -= glm_max(a[2], b[2]); +} + +/*! + * @brief sub min of two vectors to result/dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= min(a, b) + */ +CGLM_INLINE +void +glm_vec3_minsub(vec3 a, vec3 b, vec3 dest) { + dest[0] -= glm_min(a[0], b[0]); + dest[1] -= glm_min(a[1], b[1]); + dest[2] -= glm_min(a[2], b[2]); +} + +/*! + * @brief negate vector components and store result in dest + * + * @param[in] v vector + * @param[out] dest result vector + */ +CGLM_INLINE +void +glm_vec3_negate_to(vec3 v, vec3 dest) { + dest[0] = -v[0]; + dest[1] = -v[1]; + dest[2] = -v[2]; +} + +/*! + * @brief negate vector components + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec3_negate(vec3 v) { + glm_vec3_negate_to(v, v); +} + +/*! + * @brief normalize vec3 and store result in same vec + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec3_normalize(vec3 v) { + float norm; + + norm = glm_vec3_norm(v); + + if (CGLM_UNLIKELY(norm < FLT_EPSILON)) { + v[0] = v[1] = v[2] = 0.0f; + return; + } + + glm_vec3_scale(v, 1.0f / norm, v); +} + +/*! + * @brief normalize vec3 to dest + * + * @param[in] v source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_normalize_to(vec3 v, vec3 dest) { + float norm; + + norm = glm_vec3_norm(v); + + if (CGLM_UNLIKELY(norm < FLT_EPSILON)) { + glm_vec3_zero(dest); + return; + } + + glm_vec3_scale(v, 1.0f / norm, dest); +} + +/*! + * @brief cross product of two vector (RH) + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_cross(vec3 a, vec3 b, vec3 dest) { + vec3 c; + /* (u2.v3 - u3.v2, u3.v1 - u1.v3, u1.v2 - u2.v1) */ + c[0] = a[1] * b[2] - a[2] * b[1]; + c[1] = a[2] * b[0] - a[0] * b[2]; + c[2] = a[0] * b[1] - a[1] * b[0]; + glm_vec3_copy(c, dest); +} + +/*! + * @brief cross product of two vector (RH) and normalize the result + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_crossn(vec3 a, vec3 b, vec3 dest) { + glm_vec3_cross(a, b, dest); + glm_vec3_normalize(dest); +} + +/*! + * @brief angle between two vector + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return angle as radians + */ +CGLM_INLINE +float +glm_vec3_angle(vec3 a, vec3 b) { + float norm, dot; + + /* maybe compiler generate approximation instruction (rcp) */ + norm = 1.0f / (glm_vec3_norm(a) * glm_vec3_norm(b)); + dot = glm_vec3_dot(a, b) * norm; + + if (dot > 1.0f) + return 0.0f; + else if (dot < -1.0f) + return CGLM_PI; + + return acosf(dot); +} + +/*! + * @brief rotate vec3 around axis by angle using Rodrigues' rotation formula + * + * @param[in, out] v vector + * @param[in] axis axis vector (must be unit vector) + * @param[in] angle angle by radians + */ +CGLM_INLINE +void +glm_vec3_rotate(vec3 v, float angle, vec3 axis) { + vec3 v1, v2, k; + float c, s; + + c = cosf(angle); + s = sinf(angle); + + glm_vec3_normalize_to(axis, k); + + /* Right Hand, Rodrigues' rotation formula: + v = v*cos(t) + (kxv)sin(t) + k*(k.v)(1 - cos(t)) + */ + glm_vec3_scale(v, c, v1); + + glm_vec3_cross(k, v, v2); + glm_vec3_scale(v2, s, v2); + + glm_vec3_add(v1, v2, v1); + + glm_vec3_scale(k, glm_vec3_dot(k, v) * (1.0f - c), v2); + glm_vec3_add(v1, v2, v); +} + +/*! + * @brief apply rotation matrix to vector + * + * matrix format should be (no perspective): + * a b c x + * e f g y + * i j k z + * 0 0 0 w + * + * @param[in] m affine matrix or rot matrix + * @param[in] v vector + * @param[out] dest rotated vector + */ +CGLM_INLINE +void +glm_vec3_rotate_m4(mat4 m, vec3 v, vec3 dest) { + vec4 x, y, z, res; + + glm_vec4_normalize_to(m[0], x); + glm_vec4_normalize_to(m[1], y); + glm_vec4_normalize_to(m[2], z); + + glm_vec4_scale(x, v[0], res); + glm_vec4_muladds(y, v[1], res); + glm_vec4_muladds(z, v[2], res); + + glm_vec3(res, dest); +} + +/*! + * @brief apply rotation matrix to vector + * + * @param[in] m affine matrix or rot matrix + * @param[in] v vector + * @param[out] dest rotated vector + */ +CGLM_INLINE +void +glm_vec3_rotate_m3(mat3 m, vec3 v, vec3 dest) { + vec4 res, x, y, z; + + glm_vec4(m[0], 0.0f, x); + glm_vec4(m[1], 0.0f, y); + glm_vec4(m[2], 0.0f, z); + + glm_vec4_normalize(x); + glm_vec4_normalize(y); + glm_vec4_normalize(z); + + glm_vec4_scale(x, v[0], res); + glm_vec4_muladds(y, v[1], res); + glm_vec4_muladds(z, v[2], res); + + glm_vec3(res, dest); +} + +/*! + * @brief project a vector onto b vector + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest projected vector + */ +CGLM_INLINE +void +glm_vec3_proj(vec3 a, vec3 b, vec3 dest) { + glm_vec3_scale(b, + glm_vec3_dot(a, b) / glm_vec3_norm2(b), + dest); +} + +/** + * @brief find center point of two vector + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest center point + */ +CGLM_INLINE +void +glm_vec3_center(vec3 a, vec3 b, vec3 dest) { + glm_vec3_add(a, b, dest); + glm_vec3_scale(dest, 0.5f, dest); +} + +/** + * @brief squared distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return returns squared distance (distance * distance) + */ +CGLM_INLINE +float +glm_vec3_distance2(vec3 a, vec3 b) { + return glm_pow2(a[0] - b[0]) + + glm_pow2(a[1] - b[1]) + + glm_pow2(a[2] - b[2]); +} + +/** + * @brief distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return returns distance + */ +CGLM_INLINE +float +glm_vec3_distance(vec3 a, vec3 b) { + return sqrtf(glm_vec3_distance2(a, b)); +} + +/*! + * @brief max values of vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_maxv(vec3 a, vec3 b, vec3 dest) { + dest[0] = glm_max(a[0], b[0]); + dest[1] = glm_max(a[1], b[1]); + dest[2] = glm_max(a[2], b[2]); +} + +/*! + * @brief min values of vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_minv(vec3 a, vec3 b, vec3 dest) { + dest[0] = glm_min(a[0], b[0]); + dest[1] = glm_min(a[1], b[1]); + dest[2] = glm_min(a[2], b[2]); +} + +/*! + * @brief possible orthogonal/perpendicular vector + * + * @param[in] v vector + * @param[out] dest orthogonal/perpendicular vector + */ +CGLM_INLINE +void +glm_vec3_ortho(vec3 v, vec3 dest) { + float ignore; + float f = modff(fabsf(v[0]) + 0.5f, &ignore); + vec3 result = {-v[1], v[0] - f * v[2], f * v[1]}; + glm_vec3_copy(result, dest); +} + +/*! + * @brief clamp vector's individual members between min and max values + * + * @param[in, out] v vector + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + */ +CGLM_INLINE +void +glm_vec3_clamp(vec3 v, float minVal, float maxVal) { + v[0] = glm_clamp(v[0], minVal, maxVal); + v[1] = glm_clamp(v[1], minVal, maxVal); + v[2] = glm_clamp(v[2], minVal, maxVal); +} + +/*! + * @brief linear interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest) { + vec3 s, v; + + /* from + s * (to - from) */ + glm_vec3_broadcast(t, s); + glm_vec3_sub(to, from, v); + glm_vec3_mul(s, v, v); + glm_vec3_add(from, v, dest); +} + +/*! + * @brief linear interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_lerpc(vec3 from, vec3 to, float t, vec3 dest) { + glm_vec3_lerp(from, to, glm_clamp_zo(t), dest); +} + +/*! + * @brief linear interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_mix(vec3 from, vec3 to, float t, vec3 dest) { + glm_vec3_lerp(from, to, t, dest); +} + +/*! + * @brief linear interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_mixc(vec3 from, vec3 to, float t, vec3 dest) { + glm_vec3_lerpc(from, to, t, dest); +} + +/*! + * @brief threshold function + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_step(vec3 edge, vec3 x, vec3 dest) { + dest[0] = glm_step(edge[0], x[0]); + dest[1] = glm_step(edge[1], x[1]); + dest[2] = glm_step(edge[2], x[2]); +} + +/*! + * @brief threshold function with a smooth transition (unidimensional) + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_smoothstep_uni(float edge0, float edge1, vec3 x, vec3 dest) { + dest[0] = glm_smoothstep(edge0, edge1, x[0]); + dest[1] = glm_smoothstep(edge0, edge1, x[1]); + dest[2] = glm_smoothstep(edge0, edge1, x[2]); +} + +/*! + * @brief threshold function with a smooth transition + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_smoothstep(vec3 edge0, vec3 edge1, vec3 x, vec3 dest) { + dest[0] = glm_smoothstep(edge0[0], edge1[0], x[0]); + dest[1] = glm_smoothstep(edge0[1], edge1[1], x[1]); + dest[2] = glm_smoothstep(edge0[2], edge1[2], x[2]); +} + +/*! + * @brief smooth Hermite interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_smoothinterp(vec3 from, vec3 to, float t, vec3 dest) { + vec3 s, v; + + /* from + s * (to - from) */ + glm_vec3_broadcast(glm_smooth(t), s); + glm_vec3_sub(to, from, v); + glm_vec3_mul(s, v, v); + glm_vec3_add(from, v, dest); +} + +/*! + * @brief smooth Hermite interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest) { + glm_vec3_smoothinterp(from, to, glm_clamp_zo(t), dest); +} + +/*! + * @brief swizzle vector components + * + * you can use existing masks e.g. GLM_XXX, GLM_ZYX + * + * @param[in] v source + * @param[in] mask mask + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_swizzle(vec3 v, int mask, vec3 dest) { + vec3 t; + + t[0] = v[(mask & (3 << 0))]; + t[1] = v[(mask & (3 << 2)) >> 2]; + t[2] = v[(mask & (3 << 4)) >> 4]; + + glm_vec3_copy(t, dest); +} + +/*! + * @brief vec3 cross product + * + * this is just convenient wrapper + * + * @param[in] a source 1 + * @param[in] b source 2 + * @param[out] d destination + */ +CGLM_INLINE +void +glm_cross(vec3 a, vec3 b, vec3 d) { + glm_vec3_cross(a, b, d); +} + +/*! + * @brief vec3 dot product + * + * this is just convenient wrapper + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return dot product + */ +CGLM_INLINE +float +glm_dot(vec3 a, vec3 b) { + return glm_vec3_dot(a, b); +} + +/*! + * @brief normalize vec3 and store result in same vec + * + * this is just convenient wrapper + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_normalize(vec3 v) { + glm_vec3_normalize(v); +} + +/*! + * @brief normalize vec3 to dest + * + * this is just convenient wrapper + * + * @param[in] v source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_normalize_to(vec3 v, vec3 dest) { + glm_vec3_normalize_to(v, dest); +} + +/*! + * @brief Create three dimensional vector from pointer + * + * @param[in] src pointer to an array of floats + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec3_make(const float * __restrict src, vec3 dest) { + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; +} + +/*! + * @brief a vector pointing in the same direction as another + * + * orients a vector to point away from a surface as defined by its normal + * + * @param[in] n vector to orient + * @param[in] v incident vector + * @param[in] nref reference vector + * @param[out] dest oriented vector, pointing away from the surface + */ +CGLM_INLINE +void +glm_vec3_faceforward(vec3 n, vec3 v, vec3 nref, vec3 dest) { + if (glm_vec3_dot(v, nref) < 0.0f) { + /* N is facing away from I */ + glm_vec3_copy(n, dest); + } else { + /* N is facing towards I, negate it */ + glm_vec3_negate_to(n, dest); + } +} + +/*! + * @brief reflection vector using an incident ray and a surface normal + * + * @param[in] v incident vector + * @param[in] n normalized normal vector + * @param[out] dest reflection result + */ +CGLM_INLINE +void +glm_vec3_reflect(vec3 v, vec3 n, vec3 dest) { + vec3 temp; + glm_vec3_scale(n, 2.0f * glm_vec3_dot(v, n), temp); + glm_vec3_sub(v, temp, dest); +} + +/*! + * @brief computes refraction vector for an incident vector and a surface normal. + * + * calculates the refraction vector based on Snell's law. If total internal reflection + * occurs (angle too great given eta), dest is set to zero and returns false. + * Otherwise, computes refraction vector, stores it in dest, and returns true. + * + * @param[in] v normalized incident vector + * @param[in] n normalized normal vector + * @param[in] eta ratio of indices of refraction (incident/transmitted) + * @param[out] dest refraction vector if refraction occurs; zero vector otherwise + * + * @returns true if refraction occurs; false if total internal reflection occurs. + */ +CGLM_INLINE +bool +glm_vec3_refract(vec3 v, vec3 n, float eta, vec3 dest) { + float ndi, eni, k; + + ndi = glm_vec3_dot(n, v); + eni = eta * ndi; + k = 1.0f - eta * eta + eni * eni; + + if (k < 0.0f) { + glm_vec3_zero(dest); + return false; + } + + glm_vec3_scale(v, eta, dest); + glm_vec3_mulsubs(n, eni + sqrtf(k), dest); + return true; +} + +#endif /* cglm_vec3_h */ diff --git a/external/cglm/vec4-ext.h b/external/cglm/vec4-ext.h new file mode 100644 index 0000000..193a5e9 --- /dev/null +++ b/external/cglm/vec4-ext.h @@ -0,0 +1,400 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/*! + * @brief SIMD like functions + */ + +/* + Functions: + CGLM_INLINE void glm_vec4_broadcast(float val, vec4 d); + CGLM_INLINE void glm_vec4_fill(vec4 v, float val); + CGLM_INLINE bool glm_vec4_eq(vec4 v, float val); + CGLM_INLINE bool glm_vec4_eq_eps(vec4 v, float val); + CGLM_INLINE bool glm_vec4_eq_all(vec4 v); + CGLM_INLINE bool glm_vec4_eqv(vec4 a, vec4 b); + CGLM_INLINE bool glm_vec4_eqv_eps(vec4 a, vec4 b); + CGLM_INLINE float glm_vec4_max(vec4 v); + CGLM_INLINE float glm_vec4_min(vec4 v); + CGLM_INLINE bool glm_vec4_isnan(vec4 v); + CGLM_INLINE bool glm_vec4_isinf(vec4 v); + CGLM_INLINE bool glm_vec4_isvalid(vec4 v); + CGLM_INLINE void glm_vec4_sign(vec4 v, vec4 dest); + CGLM_INLINE void glm_vec4_abs(vec4 v, vec4 dest); + CGLM_INLINE void glm_vec4_fract(vec4 v, vec4 dest); + CGLM_INLINE void glm_vec4_floor(vec4 v, vec4 dest); + CGLM_INLINE float glm_vec4_mods(vec4 v, float s, vec4 dest); + CGLM_INLINE float glm_vec4_steps(float edge, vec4 v, vec4 dest); + CGLM_INLINE void glm_vec4_stepr(vec4 edge, float v, vec4 dest); + CGLM_INLINE float glm_vec4_hadd(vec4 v); + CGLM_INLINE void glm_vec4_sqrt(vec4 v, vec4 dest); + */ + +#ifndef cglm_vec4_ext_h +#define cglm_vec4_ext_h + +#include "common.h" +#include "vec3-ext.h" + +/*! + * @brief fill a vector with specified value + * + * @param val value + * @param d dest + */ +CGLM_INLINE +void +glm_vec4_broadcast(float val, vec4 d) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(d, wasm_f32x4_splat(val)); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(d, glmm_set1(val)); +#else + d[0] = d[1] = d[2] = d[3] = val; +#endif +} + +/*! + * @brief fill a vector with specified value + * + * @param v dest + * @param val value + */ +CGLM_INLINE +void +glm_vec4_fill(vec4 v, float val) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(v, wasm_f32x4_splat(val)); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(v, glmm_set1(val)); +#else + v[0] = v[1] = v[2] = v[3] = val; +#endif +} + +/*! + * @brief check if vector is equal to value (without epsilon) + * + * @param v vector + * @param val value + */ +CGLM_INLINE +bool +glm_vec4_eq(vec4 v, float val) { + return v[0] == val + && v[0] == v[1] + && v[0] == v[2] + && v[0] == v[3]; +} + +/*! + * @brief check if vector is equal to value (with epsilon) + * + * @param v vector + * @param val value + */ +CGLM_INLINE +bool +glm_vec4_eq_eps(vec4 v, float val) { + return fabsf(v[0] - val) <= GLM_FLT_EPSILON + && fabsf(v[1] - val) <= GLM_FLT_EPSILON + && fabsf(v[2] - val) <= GLM_FLT_EPSILON + && fabsf(v[3] - val) <= GLM_FLT_EPSILON; +} + +/*! + * @brief check if vector members are equal (without epsilon) + * + * @param v vector + */ +CGLM_INLINE +bool +glm_vec4_eq_all(vec4 v) { + return glm_vec4_eq_eps(v, v[0]); +} + +/*! + * @brief check if vector is equal to another (without epsilon) + * + * @param a vector + * @param b vector + */ +CGLM_INLINE +bool +glm_vec4_eqv(vec4 a, vec4 b) { + return a[0] == b[0] + && a[1] == b[1] + && a[2] == b[2] + && a[3] == b[3]; +} + +/*! + * @brief check if vector is equal to another (with epsilon) + * + * @param a vector + * @param b vector + */ +CGLM_INLINE +bool +glm_vec4_eqv_eps(vec4 a, vec4 b) { + return fabsf(a[0] - b[0]) <= GLM_FLT_EPSILON + && fabsf(a[1] - b[1]) <= GLM_FLT_EPSILON + && fabsf(a[2] - b[2]) <= GLM_FLT_EPSILON + && fabsf(a[3] - b[3]) <= GLM_FLT_EPSILON; +} + +/*! + * @brief max value of vector + * + * @param v vector + */ +CGLM_INLINE +float +glm_vec4_max(vec4 v) { + float max; + + max = glm_vec3_max(v); + if (v[3] > max) + max = v[3]; + + return max; +} + +/*! + * @brief min value of vector + * + * @param v vector + */ +CGLM_INLINE +float +glm_vec4_min(vec4 v) { + float min; + + min = glm_vec3_min(v); + if (v[3] < min) + min = v[3]; + + return min; +} + +/*! + * @brief check if one of items is NaN (not a number) + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec4_isnan(vec4 v) { +#ifndef CGLM_FAST_MATH + return isnan(v[0]) || isnan(v[1]) || isnan(v[2]) || isnan(v[3]); +#else + return false; +#endif +} + +/*! + * @brief check if one of items is INFINITY + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec4_isinf(vec4 v) { +#ifndef CGLM_FAST_MATH + return isinf(v[0]) || isinf(v[1]) || isinf(v[2]) || isinf(v[3]); +#else + return false; +#endif +} + +/*! + * @brief check if all items are valid number + * you should only use this in DEBUG mode or very critical asserts + * + * @param[in] v vector + */ +CGLM_INLINE +bool +glm_vec4_isvalid(vec4 v) { + return !glm_vec4_isnan(v) && !glm_vec4_isinf(v); +} + +/*! + * @brief get sign of 32 bit float as +1, -1, 0 + * + * Important: It returns 0 for zero/NaN input + * + * @param v vector + */ +CGLM_INLINE +void +glm_vec4_sign(vec4 v, vec4 dest) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + __m128 x0, x1, x2, x3, x4; + + x0 = glmm_load(v); + x1 = _mm_set_ps(0.0f, 0.0f, 1.0f, -1.0f); + x2 = glmm_splat(x1, 2); + + x3 = _mm_and_ps(_mm_cmpgt_ps(x0, x2), glmm_splat(x1, 1)); + x4 = _mm_and_ps(_mm_cmplt_ps(x0, x2), glmm_splat(x1, 0)); + + glmm_store(dest, _mm_or_ps(x3, x4)); +#else + dest[0] = glm_signf(v[0]); + dest[1] = glm_signf(v[1]); + dest[2] = glm_signf(v[2]); + dest[3] = glm_signf(v[3]); +#endif +} + +/*! + * @brief absolute value of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_abs(vec4 v, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, glmm_abs(glmm_load(v))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, glmm_abs(glmm_load(v))); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest, vabsq_f32(vld1q_f32(v))); +#else + dest[0] = fabsf(v[0]); + dest[1] = fabsf(v[1]); + dest[2] = fabsf(v[2]); + dest[3] = fabsf(v[3]); +#endif +} + +/*! + * @brief fractional part of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_fract(vec4 v, vec4 dest) { + dest[0] = fminf(v[0] - floorf(v[0]), 0.999999940395355224609375f); + dest[1] = fminf(v[1] - floorf(v[1]), 0.999999940395355224609375f); + dest[2] = fminf(v[2] - floorf(v[2]), 0.999999940395355224609375f); + dest[3] = fminf(v[3] - floorf(v[3]), 0.999999940395355224609375f); +} + +/*! + * @brief floor of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_floor(vec4 v, vec4 dest) { + dest[0] = floorf(v[0]); + dest[1] = floorf(v[1]); + dest[2] = floorf(v[2]); + dest[3] = floorf(v[3]); +} + +/*! + * @brief mod of each vector item, result is written to dest (dest = v % s) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_mods(vec4 v, float s, vec4 dest) { + dest[0] = fmodf(v[0], s); + dest[1] = fmodf(v[1], s); + dest[2] = fmodf(v[2], s); + dest[3] = fmodf(v[3], s); +} + +/*! + * @brief threshold each vector item with scalar + * condition is: (x[i] < edge) ? 0.0 : 1.0 + * + * @param[in] edge threshold + * @param[in] x vector to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_steps(float edge, vec4 x, vec4 dest) { + dest[0] = glm_step(edge, x[0]); + dest[1] = glm_step(edge, x[1]); + dest[2] = glm_step(edge, x[2]); + dest[3] = glm_step(edge, x[3]); +} + +/*! + * @brief threshold a value with *vector* as the threshold + * condition is: (x < edge[i]) ? 0.0 : 1.0 + * + * @param[in] edge threshold vector + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_stepr(vec4 edge, float x, vec4 dest) { + dest[0] = glm_step(edge[0], x); + dest[1] = glm_step(edge[1], x); + dest[2] = glm_step(edge[2], x); + dest[3] = glm_step(edge[3], x); +} + +/*! + * @brief vector reduction by summation + * @warning could overflow + * + * @param[in] v vector + * @return sum of all vector's elements + */ +CGLM_INLINE +float +glm_vec4_hadd(vec4 v) { +#if defined(__wasm__) && defined(__wasm_simd128__) + return glmm_hadd(glmm_load(v)); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + return glmm_hadd(glmm_load(v)); +#else + return v[0] + v[1] + v[2] + v[3]; +#endif +} + +/*! + * @brief square root of each vector item + * + * @param[in] v vector + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_sqrt(vec4 v, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_sqrt(glmm_load(v))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_sqrt_ps(glmm_load(v))); +#else + dest[0] = sqrtf(v[0]); + dest[1] = sqrtf(v[1]); + dest[2] = sqrtf(v[2]); + dest[3] = sqrtf(v[3]); +#endif +} + +#endif /* cglm_vec4_ext_h */ diff --git a/external/cglm/vec4.h b/external/cglm/vec4.h new file mode 100644 index 0000000..ded09c9 --- /dev/null +++ b/external/cglm/vec4.h @@ -0,0 +1,1348 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +/* + Macros: + GLM_VEC4_ONE_INIT + GLM_VEC4_BLACK_INIT + GLM_VEC4_ZERO_INIT + GLM_VEC4_ONE + GLM_VEC4_BLACK + GLM_VEC4_ZERO + + Functions: + CGLM_INLINE void glm_vec4(vec3 v3, float last, vec4 dest); + CGLM_INLINE void glm_vec4_copy3(vec4 a, vec3 dest); + CGLM_INLINE void glm_vec4_copy(vec4 v, vec4 dest); + CGLM_INLINE void glm_vec4_ucopy(vec4 v, vec4 dest); + CGLM_INLINE float glm_vec4_dot(vec4 a, vec4 b); + CGLM_INLINE float glm_vec4_norm2(vec4 v); + CGLM_INLINE float glm_vec4_norm(vec4 v); + CGLM_INLINE float glm_vec4_norm_one(vec4 v); + CGLM_INLINE float glm_vec4_norm_inf(vec4 v); + CGLM_INLINE void glm_vec4_add(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_adds(vec4 v, float s, vec4 dest); + CGLM_INLINE void glm_vec4_sub(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_subs(vec4 v, float s, vec4 dest); + CGLM_INLINE void glm_vec4_mul(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_scale(vec4 v, float s, vec4 dest); + CGLM_INLINE void glm_vec4_scale_as(vec4 v, float s, vec4 dest); + CGLM_INLINE void glm_vec4_div(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_divs(vec4 v, float s, vec4 dest); + CGLM_INLINE void glm_vec4_addadd(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_subadd(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_muladd(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_muladds(vec4 a, float s, vec4 dest); + CGLM_INLINE void glm_vec4_maxadd(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_minadd(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_subsub(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_addsub(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_mulsub(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_mulsubs(vec4 a, float s, vec4 dest); + CGLM_INLINE void glm_vec4_maxsub(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_minsub(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_negate(vec4 v); + CGLM_INLINE void glm_vec4_inv(vec4 v); + CGLM_INLINE void glm_vec4_inv_to(vec4 v, vec4 dest); + CGLM_INLINE void glm_vec4_normalize(vec4 v); + CGLM_INLINE void glm_vec4_normalize_to(vec4 vec, vec4 dest); + CGLM_INLINE float glm_vec4_distance(vec4 a, vec4 b); + CGLM_INLINE float glm_vec4_distance2(vec4 a, vec4 b); + CGLM_INLINE void glm_vec4_maxv(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_minv(vec4 a, vec4 b, vec4 dest); + CGLM_INLINE void glm_vec4_clamp(vec4 v, float minVal, float maxVal); + CGLM_INLINE void glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest); + CGLM_INLINE void glm_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest); + CGLM_INLINE void glm_vec4_step(vec4 edge, vec4 x, vec4 dest); + CGLM_INLINE void glm_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest); + CGLM_INLINE void glm_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest); + CGLM_INLINE void glm_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest); + CGLM_INLINE void glm_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest); + CGLM_INLINE void glm_vec4_swizzle(vec4 v, int mask, vec4 dest); + CGLM_INLINE void glm_vec4_make(float * restrict src, vec4 dest); + CGLM_INLINE void glm_vec4_reflect(vec4 v, vec4 n, vec4 dest); + CGLM_INLINE void glm_vec4_refract(vec4 v, vec4 n, float eta, vec4 dest); + + DEPRECATED: + glm_vec4_dup + glm_vec4_flipsign + glm_vec4_flipsign_to + glm_vec4_inv + glm_vec4_inv_to + glm_vec4_mulv + glm_vec4_step_uni --> use glm_vec4_steps + */ + +#ifndef cglm_vec4_h +#define cglm_vec4_h + +#include "common.h" +#include "vec4-ext.h" +#include "util.h" + +/* DEPRECATED! functions */ +#define glm_vec4_dup3(v, dest) glm_vec4_copy3(v, dest) +#define glm_vec4_dup(v, dest) glm_vec4_copy(v, dest) +#define glm_vec4_flipsign(v) glm_vec4_negate(v) +#define glm_vec4_flipsign_to(v, dest) glm_vec4_negate_to(v, dest) +#define glm_vec4_inv(v) glm_vec4_negate(v) +#define glm_vec4_inv_to(v, dest) glm_vec4_negate_to(v, dest) +#define glm_vec4_mulv(a, b, d) glm_vec4_mul(a, b, d) +#define glm_vec4_step_uni(edge, x, dest) glm_vec4_steps(edge, x, dest) + +#define GLM_VEC4_ONE_INIT {1.0f, 1.0f, 1.0f, 1.0f} +#define GLM_VEC4_BLACK_INIT {0.0f, 0.0f, 0.0f, 1.0f} +#define GLM_VEC4_ZERO_INIT {0.0f, 0.0f, 0.0f, 0.0f} + +#define GLM_VEC4_ONE ((vec4)GLM_VEC4_ONE_INIT) +#define GLM_VEC4_BLACK ((vec4)GLM_VEC4_BLACK_INIT) +#define GLM_VEC4_ZERO ((vec4)GLM_VEC4_ZERO_INIT) + +#define GLM_XXXX GLM_SHUFFLE4(0, 0, 0, 0) +#define GLM_YYYY GLM_SHUFFLE4(1, 1, 1, 1) +#define GLM_ZZZZ GLM_SHUFFLE4(2, 2, 2, 2) +#define GLM_WWWW GLM_SHUFFLE4(3, 3, 3, 3) +#define GLM_WZYX GLM_SHUFFLE4(0, 1, 2, 3) + +/*! + * @brief init vec4 using vec3 + * + * @param[in] v3 vector3 + * @param[in] last last item + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4(vec3 v3, float last, vec4 dest) { + dest[0] = v3[0]; + dest[1] = v3[1]; + dest[2] = v3[2]; + dest[3] = last; +} + +/*! + * @brief copy first 3 members of [a] to [dest] + * + * @param[in] a source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_copy3(vec4 a, vec3 dest) { + dest[0] = a[0]; + dest[1] = a[1]; + dest[2] = a[2]; +} + +/*! + * @brief copy all members of [a] to [dest] + * + * @param[in] v source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_copy(vec4 v, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, glmm_load(v)); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, glmm_load(v)); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest, vld1q_f32(v)); +#else + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = v[2]; + dest[3] = v[3]; +#endif +} + +/*! + * @brief copy all members of [a] to [dest] + * + * alignment is not required + * + * @param[in] v source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_ucopy(vec4 v, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + /* note here wasm v128.load/v128.store support unaligned loads and stores */ + wasm_v128_store(dest, wasm_v128_load(v)); +#else + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = v[2]; + dest[3] = v[3]; +#endif +} + +/*! + * @brief make vector zero + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec4_zero(vec4 v) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(v, wasm_f32x4_const_splat(0.f)); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(v, _mm_setzero_ps()); +#elif defined(CGLM_NEON_FP) + vst1q_f32(v, vdupq_n_f32(0.0f)); +#else + v[0] = 0.0f; + v[1] = 0.0f; + v[2] = 0.0f; + v[3] = 0.0f; +#endif +} + +/*! + * @brief make vector one + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec4_one(vec4 v) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(v, wasm_f32x4_const_splat(1.0f)); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(v, glmm_set1_rval(1.0f)); +#elif defined(CGLM_NEON_FP) + vst1q_f32(v, vdupq_n_f32(1.0f)); +#else + v[0] = 1.0f; + v[1] = 1.0f; + v[2] = 1.0f; + v[3] = 1.0f; +#endif +} + +/*! + * @brief vec4 dot product + * + * @param[in] a vector1 + * @param[in] b vector2 + * + * @return dot product + */ +CGLM_INLINE +float +glm_vec4_dot(vec4 a, vec4 b) { +#if defined(CGLM_SIMD) + return glmm_dot(glmm_load(a), glmm_load(b)); +#else + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; +#endif +} + +/*! + * @brief norm * norm (magnitude) of vec + * + * we can use this func instead of calling norm * norm, because it would call + * sqrtf function twice but with this func we can avoid func call, maybe this is + * not good name for this func + * + * @param[in] v vec4 + * + * @return norm * norm + */ +CGLM_INLINE +float +glm_vec4_norm2(vec4 v) { + return glm_vec4_dot(v, v); +} + +/*! + * @brief euclidean norm (magnitude), also called L2 norm + * this will give magnitude of vector in euclidean space + * + * @param[in] v vector + * + * @return norm + */ +CGLM_INLINE +float +glm_vec4_norm(vec4 v) { +#if defined(CGLM_SIMD) + return glmm_norm(glmm_load(v)); +#else + return sqrtf(glm_vec4_dot(v, v)); +#endif +} + +/*! + * @brief L1 norm of vec4 + * Also known as Manhattan Distance or Taxicab norm. + * L1 Norm is the sum of the magnitudes of the vectors in a space. + * It is calculated as the sum of the absolute values of the vector components. + * In this norm, all the components of the vector are weighted equally. + * + * This computes: + * L1 norm = |v[0]| + |v[1]| + |v[2]| + |v[3]| + * + * @param[in] v vector + * + * @return L1 norm + */ +CGLM_INLINE +float +glm_vec4_norm_one(vec4 v) { +#if defined(CGLM_SIMD) + return glmm_norm_one(glmm_load(v)); +#else + vec4 t; + glm_vec4_abs(v, t); + return glm_vec4_hadd(t); +#endif +} + +/*! + * @brief infinity norm of vec4 + * Also known as Maximum norm. + * Infinity Norm is the largest magnitude among each element of a vector. + * It is calculated as the maximum of the absolute values of the vector components. + * + * This computes: + * inf norm = max(|v[0]|, |v[1]|, |v[2]|, |v[3]|) + * + * @param[in] v vector + * + * @return infinity norm + */ +CGLM_INLINE +float +glm_vec4_norm_inf(vec4 v) { +#if defined(CGLM_SIMD) + return glmm_norm_inf(glmm_load(v)); +#else + vec4 t; + glm_vec4_abs(v, t); + return glm_vec4_max(t); +#endif +} + +/*! + * @brief add b vector to a vector store result in dest + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_add(vec4 a, vec4 b, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_add(glmm_load(a), glmm_load(b))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_add_ps(glmm_load(a), glmm_load(b))); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest, vaddq_f32(vld1q_f32(a), vld1q_f32(b))); +#else + dest[0] = a[0] + b[0]; + dest[1] = a[1] + b[1]; + dest[2] = a[2] + b[2]; + dest[3] = a[3] + b[3]; +#endif +} + +/*! + * @brief add scalar to v vector store result in dest (d = v + vec(s)) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_adds(vec4 v, float s, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_add(glmm_load(v), wasm_f32x4_splat(s))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_add_ps(glmm_load(v), glmm_set1(s))); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest, vaddq_f32(vld1q_f32(v), vdupq_n_f32(s))); +#else + dest[0] = v[0] + s; + dest[1] = v[1] + s; + dest[2] = v[2] + s; + dest[3] = v[3] + s; +#endif +} + +/*! + * @brief subtract b vector from a vector store result in dest (d = a - b) + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_sub(vec4 a, vec4 b, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_sub(glmm_load(a), glmm_load(b))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_sub_ps(glmm_load(a), glmm_load(b))); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest, vsubq_f32(vld1q_f32(a), vld1q_f32(b))); +#else + dest[0] = a[0] - b[0]; + dest[1] = a[1] - b[1]; + dest[2] = a[2] - b[2]; + dest[3] = a[3] - b[3]; +#endif +} + +/*! + * @brief subtract scalar from v vector store result in dest (d = v - vec(s)) + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_subs(vec4 v, float s, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_sub(glmm_load(v), wasm_f32x4_splat(s))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_sub_ps(glmm_load(v), glmm_set1(s))); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest, vsubq_f32(vld1q_f32(v), vdupq_n_f32(s))); +#else + dest[0] = v[0] - s; + dest[1] = v[1] - s; + dest[2] = v[2] - s; + dest[3] = v[3] - s; +#endif +} + +/*! + * @brief multiply two vectors (component-wise multiplication) + * + * @param a vector1 + * @param b vector2 + * @param dest dest = (a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3]) + */ +CGLM_INLINE +void +glm_vec4_mul(vec4 a, vec4 b, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_mul(glmm_load(a), glmm_load(b))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_mul_ps(glmm_load(a), glmm_load(b))); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest, vmulq_f32(vld1q_f32(a), vld1q_f32(b))); +#else + dest[0] = a[0] * b[0]; + dest[1] = a[1] * b[1]; + dest[2] = a[2] * b[2]; + dest[3] = a[3] * b[3]; +#endif +} + +/*! + * @brief multiply/scale vec4 vector with scalar: result = v * s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_scale(vec4 v, float s, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_mul(glmm_load(v), wasm_f32x4_splat(s))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_mul_ps(glmm_load(v), glmm_set1(s))); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest, vmulq_f32(vld1q_f32(v), vdupq_n_f32(s))); +#else + dest[0] = v[0] * s; + dest[1] = v[1] * s; + dest[2] = v[2] * s; + dest[3] = v[3] * s; +#endif +} + +/*! + * @brief make vec4 vector scale as specified: result = unit(v) * s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_scale_as(vec4 v, float s, vec4 dest) { + float norm; + norm = glm_vec4_norm(v); + + if (CGLM_UNLIKELY(norm < FLT_EPSILON)) { + glm_vec4_zero(dest); + return; + } + + glm_vec4_scale(v, s / norm, dest); +} + +/*! + * @brief div vector with another component-wise division: d = a / b + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest result = (a[0]/b[0], a[1]/b[1], a[2]/b[2], a[3]/b[3]) + */ +CGLM_INLINE +void +glm_vec4_div(vec4 a, vec4 b, vec4 dest) { +#if defined(CGLM_SIMD) + glmm_store(dest, glmm_div(glmm_load(a), glmm_load(b))); +#else + dest[0] = a[0] / b[0]; + dest[1] = a[1] / b[1]; + dest[2] = a[2] / b[2]; + dest[3] = a[3] / b[3]; +#endif +} + +/*! + * @brief div vec4 vector with scalar: d = v / s + * + * @param[in] v vector + * @param[in] s scalar + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_divs(vec4 v, float s, vec4 dest) { +#if defined(CGLM_SIMD) + glmm_store(dest, glmm_div(glmm_load(v), glmm_set1(s))); +#else + glm_vec4_scale(v, 1.0f / s, dest); +#endif +} + +/*! + * @brief add two vectors and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a + b) + */ +CGLM_INLINE +void +glm_vec4_addadd(vec4 a, vec4 b, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_add( + glmm_load(dest), + wasm_f32x4_add(glmm_load(a), glmm_load(b)))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_add_ps(glmm_load(dest), + _mm_add_ps(glmm_load(a), + glmm_load(b)))); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest, vaddq_f32(vld1q_f32(dest), + vaddq_f32(vld1q_f32(a), + vld1q_f32(b)))); +#else + dest[0] += a[0] + b[0]; + dest[1] += a[1] + b[1]; + dest[2] += a[2] + b[2]; + dest[3] += a[3] + b[3]; +#endif +} + +/*! + * @brief sub two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a - b) + */ +CGLM_INLINE +void +glm_vec4_subadd(vec4 a, vec4 b, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_add( + glmm_load(dest), + wasm_f32x4_sub(glmm_load(a), glmm_load(b)))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_add_ps(glmm_load(dest), + _mm_sub_ps(glmm_load(a), + glmm_load(b)))); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest, vaddq_f32(vld1q_f32(dest), + vsubq_f32(vld1q_f32(a), + vld1q_f32(b)))); +#else + dest[0] += a[0] - b[0]; + dest[1] += a[1] - b[1]; + dest[2] += a[2] - b[2]; + dest[3] += a[3] - b[3]; +#endif +} + +/*! + * @brief mul two vectors and add result to dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) { +#if defined(CGLM_SIMD) + glmm_store(dest, glmm_fmadd(glmm_load(a), glmm_load(b), glmm_load(dest))); +#else + dest[0] += a[0] * b[0]; + dest[1] += a[1] * b[1]; + dest[2] += a[2] * b[2]; + dest[3] += a[3] * b[3]; +#endif +} + +/*! + * @brief mul vector with scalar and add result to sum + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest += (a * b) + */ +CGLM_INLINE +void +glm_vec4_muladds(vec4 a, float s, vec4 dest) { +#if defined(CGLM_SIMD) + glmm_store(dest, glmm_fmadd(glmm_load(a), glmm_set1(s), glmm_load(dest))); +#else + dest[0] += a[0] * s; + dest[1] += a[1] * s; + dest[2] += a[2] * s; + dest[3] += a[3] * s; +#endif +} + +/*! + * @brief add max of two vectors to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += max(a, b) + */ +CGLM_INLINE +void +glm_vec4_maxadd(vec4 a, vec4 b, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_add(glmm_load(dest), + glmm_max(glmm_load(a), glmm_load(b)))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_add_ps(glmm_load(dest), + glmm_max(glmm_load(a), glmm_load(b)))); +#elif defined(CGLM_NEON_FP) + glmm_store(dest, vaddq_f32(glmm_load(dest), + glmm_max(glmm_load(a), glmm_load(b)))); +#else + dest[0] += glm_max(a[0], b[0]); + dest[1] += glm_max(a[1], b[1]); + dest[2] += glm_max(a[2], b[2]); + dest[3] += glm_max(a[3], b[3]); +#endif +} + +/*! + * @brief add min of two vectors to result/dest + * + * it applies += operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest += min(a, b) + */ +CGLM_INLINE +void +glm_vec4_minadd(vec4 a, vec4 b, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_add(glmm_load(dest), + glmm_min(glmm_load(a), glmm_load(b)))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_add_ps(glmm_load(dest), + glmm_min(glmm_load(a), glmm_load(b)))); +#elif defined(CGLM_NEON_FP) + glmm_store(dest, vaddq_f32(glmm_load(dest), + glmm_min(glmm_load(a), glmm_load(b)))); +#else + dest[0] += glm_min(a[0], b[0]); + dest[1] += glm_min(a[1], b[1]); + dest[2] += glm_min(a[2], b[2]); + dest[3] += glm_min(a[3], b[3]); +#endif +} + +/*! + * @brief sub two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= (a - b) + */ +CGLM_INLINE +void +glm_vec4_subsub(vec4 a, vec4 b, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_sub( + glmm_load(dest), + wasm_f32x4_sub(glmm_load(a), glmm_load(b)))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_sub_ps(glmm_load(dest), + _mm_sub_ps(glmm_load(a), + glmm_load(b)))); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest, vsubq_f32(vld1q_f32(dest), + vsubq_f32(vld1q_f32(a), + vld1q_f32(b)))); +#else + dest[0] -= a[0] - b[0]; + dest[1] -= a[1] - b[1]; + dest[2] -= a[2] - b[2]; + dest[3] -= a[3] - b[3]; +#endif +} + +/*! + * @brief add two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= (a + b) + */ +CGLM_INLINE +void +glm_vec4_addsub(vec4 a, vec4 b, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_sub( + glmm_load(dest), + wasm_f32x4_add(glmm_load(a), glmm_load(b)))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_sub_ps(glmm_load(dest), + _mm_add_ps(glmm_load(a), + glmm_load(b)))); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest, vsubq_f32(vld1q_f32(dest), + vaddq_f32(vld1q_f32(a), + vld1q_f32(b)))); +#else + dest[0] -= a[0] + b[0]; + dest[1] -= a[1] + b[1]; + dest[2] -= a[2] + b[2]; + dest[3] -= a[3] + b[3]; +#endif +} + +/*! + * @brief mul two vectors and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= (a * b) + */ +CGLM_INLINE +void +glm_vec4_mulsub(vec4 a, vec4 b, vec4 dest) { +#if defined(CGLM_SIMD) + glmm_store(dest, glmm_fnmadd(glmm_load(a), glmm_load(b), glmm_load(dest))); +#else + dest[0] -= a[0] * b[0]; + dest[1] -= a[1] * b[1]; + dest[2] -= a[2] * b[2]; + dest[3] -= a[3] * b[3]; +#endif +} + +/*! + * @brief mul vector with scalar and sub result to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector + * @param[in] s scalar + * @param[out] dest dest -= (a * b) + */ +CGLM_INLINE +void +glm_vec4_mulsubs(vec4 a, float s, vec4 dest) { +#if defined(CGLM_SIMD) + glmm_store(dest, glmm_fnmadd(glmm_load(a), glmm_set1(s), glmm_load(dest))); +#else + dest[0] -= a[0] * s; + dest[1] -= a[1] * s; + dest[2] -= a[2] * s; + dest[3] -= a[3] * s; +#endif +} + +/*! + * @brief sub max of two vectors to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= max(a, b) + */ +CGLM_INLINE +void +glm_vec4_maxsub(vec4 a, vec4 b, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_sub(glmm_load(dest), + glmm_max(glmm_load(a), glmm_load(b)))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_sub_ps(glmm_load(dest), + glmm_max(glmm_load(a), glmm_load(b)))); +#elif defined(CGLM_NEON_FP) + glmm_store(dest, vsubq_f32(glmm_load(dest), + glmm_max(glmm_load(a), glmm_load(b)))); +#else + dest[0] -= glm_max(a[0], b[0]); + dest[1] -= glm_max(a[1], b[1]); + dest[2] -= glm_max(a[2], b[2]); + dest[3] -= glm_max(a[3], b[3]); +#endif +} + +/*! + * @brief sub min of two vectors to dest + * + * it applies -= operator so dest must be initialized + * + * @param[in] a vector 1 + * @param[in] b vector 2 + * @param[out] dest dest -= min(a, b) + */ +CGLM_INLINE +void +glm_vec4_minsub(vec4 a, vec4 b, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_sub(glmm_load(dest), + glmm_min(glmm_load(a), glmm_load(b)))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_sub_ps(glmm_load(dest), + glmm_min(glmm_load(a), glmm_load(b)))); +#elif defined(CGLM_NEON_FP) + glmm_store(dest, vsubq_f32(vld1q_f32(dest), + glmm_min(glmm_load(a), glmm_load(b)))); +#else + dest[0] -= glm_min(a[0], b[0]); + dest[1] -= glm_min(a[1], b[1]); + dest[2] -= glm_min(a[2], b[2]); + dest[3] -= glm_min(a[3], b[3]); +#endif +} + +/*! + * @brief negate vector components and store result in dest + * + * @param[in] v vector + * @param[out] dest result vector + */ +CGLM_INLINE +void +glm_vec4_negate_to(vec4 v, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(dest, wasm_f32x4_neg(glmm_load(v))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(dest, _mm_xor_ps(glmm_load(v), glmm_float32x4_SIGNMASK_NEG)); +#elif defined(CGLM_NEON_FP) + vst1q_f32(dest, vnegq_f32(vld1q_f32(v))); +#else + dest[0] = -v[0]; + dest[1] = -v[1]; + dest[2] = -v[2]; + dest[3] = -v[3]; +#endif +} + +/*! + * @brief flip sign of all vec4 members + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec4_negate(vec4 v) { + glm_vec4_negate_to(v, v); +} + +/*! + * @brief normalize vec4 to dest + * + * @param[in] v source + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_normalize_to(vec4 v, vec4 dest) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_128 xdot, x0; + float dot; + + x0 = glmm_load(v); + xdot = glmm_vdot(x0, x0); + /* dot = _mm_cvtss_f32(xdot); */ + dot = wasm_f32x4_extract_lane(xdot, 0); + + if (CGLM_UNLIKELY(dot < FLT_EPSILON)) { + glmm_store(dest, wasm_f32x4_const_splat(0.f)); + return; + } + + glmm_store(dest, glmm_div(x0, wasm_f32x4_sqrt(xdot))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + __m128 xdot, x0; + float dot; + + x0 = glmm_load(v); + xdot = glmm_vdot(x0, x0); + dot = _mm_cvtss_f32(xdot); + + if (CGLM_UNLIKELY(dot < FLT_EPSILON)) { + glmm_store(dest, _mm_setzero_ps()); + return; + } + + glmm_store(dest, glmm_div(x0, _mm_sqrt_ps(xdot))); +#else + float norm; + + norm = glm_vec4_norm(v); + + if (CGLM_UNLIKELY(norm < FLT_EPSILON)) { + glm_vec4_zero(dest); + return; + } + + glm_vec4_scale(v, 1.0f / norm, dest); +#endif +} + +/*! + * @brief normalize vec4 and store result in same vec + * + * @param[in, out] v vector + */ +CGLM_INLINE +void +glm_vec4_normalize(vec4 v) { + glm_vec4_normalize_to(v, v); +} + +/** + * @brief distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return returns distance + */ +CGLM_INLINE +float +glm_vec4_distance(vec4 a, vec4 b) { +#if defined(__wasm__) && defined(__wasm_simd128__) + return glmm_norm(wasm_f32x4_sub(glmm_load(a), glmm_load(b))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + return glmm_norm(_mm_sub_ps(glmm_load(a), glmm_load(b))); +#elif defined(CGLM_NEON_FP) + return glmm_norm(vsubq_f32(glmm_load(a), glmm_load(b))); +#else + return sqrtf(glm_pow2(a[0] - b[0]) + + glm_pow2(a[1] - b[1]) + + glm_pow2(a[2] - b[2]) + + glm_pow2(a[3] - b[3])); +#endif +} + +/** + * @brief squared distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return returns squared distance + */ +CGLM_INLINE +float +glm_vec4_distance2(vec4 a, vec4 b) { +#if defined(__wasm__) && defined(__wasm_simd128__) + return glmm_norm2(wasm_f32x4_sub(glmm_load(a), glmm_load(b))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + return glmm_norm2(_mm_sub_ps(glmm_load(a), glmm_load(b))); +#elif defined(CGLM_NEON_FP) + return glmm_norm2(vsubq_f32(glmm_load(a), glmm_load(b))); +#else + return glm_pow2(a[0] - b[0]) + + glm_pow2(a[1] - b[1]) + + glm_pow2(a[2] - b[2]) + + glm_pow2(a[3] - b[3]); +#endif +} + +/*! + * @brief max values of vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_maxv(vec4 a, vec4 b, vec4 dest) { +#if defined(CGLM_SIMD) + glmm_store(dest, glmm_max(glmm_load(a), glmm_load(b))); +#else + dest[0] = glm_max(a[0], b[0]); + dest[1] = glm_max(a[1], b[1]); + dest[2] = glm_max(a[2], b[2]); + dest[3] = glm_max(a[3], b[3]); +#endif +} + +/*! + * @brief min values of vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_minv(vec4 a, vec4 b, vec4 dest) { +#if defined(CGLM_SIMD) + glmm_store(dest, glmm_min(glmm_load(a), glmm_load(b))); +#else + dest[0] = glm_min(a[0], b[0]); + dest[1] = glm_min(a[1], b[1]); + dest[2] = glm_min(a[2], b[2]); + dest[3] = glm_min(a[3], b[3]); +#endif +} + +/*! + * @brief clamp vector's individual members between min and max values + * + * @param[in, out] v vector + * @param[in] minVal minimum value + * @param[in] maxVal maximum value + */ +CGLM_INLINE +void +glm_vec4_clamp(vec4 v, float minVal, float maxVal) { +#if defined(__wasm__) && defined(__wasm_simd128__) + glmm_store(v, glmm_min(glmm_max(glmm_load(v), wasm_f32x4_splat(minVal)), + wasm_f32x4_splat(maxVal))); +#elif defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(v, glmm_min(glmm_max(glmm_load(v), glmm_set1(minVal)), + glmm_set1(maxVal))); +#elif defined(CGLM_NEON_FP) + glmm_store(v, glmm_min(glmm_max(vld1q_f32(v), vdupq_n_f32(minVal)), + vdupq_n_f32(maxVal))); +#else + v[0] = glm_clamp(v[0], minVal, maxVal); + v[1] = glm_clamp(v[1], minVal, maxVal); + v[2] = glm_clamp(v[2], minVal, maxVal); + v[3] = glm_clamp(v[3], minVal, maxVal); +#endif +} + +/*! + * @brief linear interpolation between two vectors + * + * formula: from + t * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest) { + vec4 s, v; + + /* from + s * (to - from) */ + glm_vec4_broadcast(t, s); + glm_vec4_sub(to, from, v); + glm_vec4_mul(s, v, v); + glm_vec4_add(from, v, dest); +} + +/*! + * @brief linear interpolation between two vectors (clamped) + * + * formula: from + t * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest) { + glm_vec4_lerp(from, to, glm_clamp_zo(t), dest); +} + +/*! + * @brief linear interpolation between two vectors + * + * formula: from + t * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_mix(vec4 from, vec4 to, float t, vec4 dest) { + glm_vec4_lerp(from, to, t, dest); +} + +/*! + * @brief linear interpolation between two vectors (clamped) + * + * formula: from + t * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_mixc(vec4 from, vec4 to, float t, vec4 dest) { + glm_vec4_lerpc(from, to, t, dest); +} + +/*! + * @brief threshold function + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_step(vec4 edge, vec4 x, vec4 dest) { + dest[0] = glm_step(edge[0], x[0]); + dest[1] = glm_step(edge[1], x[1]); + dest[2] = glm_step(edge[2], x[2]); + dest[3] = glm_step(edge[3], x[3]); +} + +/*! + * @brief threshold function with a smooth transition (unidimensional) + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest) { + dest[0] = glm_smoothstep(edge0, edge1, x[0]); + dest[1] = glm_smoothstep(edge0, edge1, x[1]); + dest[2] = glm_smoothstep(edge0, edge1, x[2]); + dest[3] = glm_smoothstep(edge0, edge1, x[3]); +} + +/*! + * @brief threshold function with a smooth transition + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest) { + dest[0] = glm_smoothstep(edge0[0], edge1[0], x[0]); + dest[1] = glm_smoothstep(edge0[1], edge1[1], x[1]); + dest[2] = glm_smoothstep(edge0[2], edge1[2], x[2]); + dest[3] = glm_smoothstep(edge0[3], edge1[3], x[3]); +} + +/*! + * @brief smooth Hermite interpolation between two vectors + * + * formula: t^2 * (3 - 2*t) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest) { + vec4 s, v; + + /* from + smoothstep * (to - from) */ + glm_vec4_broadcast(glm_smooth(t), s); + glm_vec4_sub(to, from, v); + glm_vec4_mul(s, v, v); + glm_vec4_add(from, v, dest); +} + +/*! + * @brief smooth Hermite interpolation between two vectors (clamped) + * + * formula: t^2 * (3 - 2*t) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest) { + glm_vec4_smoothinterp(from, to, glm_clamp_zo(t), dest); +} + +/*! + * @brief helper to fill vec4 as [S^3, S^2, S, 1] + * + * @param[in] s parameter + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_cubic(float s, vec4 dest) { + float ss; + + ss = s * s; + + dest[0] = ss * s; + dest[1] = ss; + dest[2] = s; + dest[3] = 1.0f; +} + +/*! + * @brief swizzle vector components + * + * you can use existing masks e.g. GLM_XXXX, GLM_WZYX + * + * @param[in] v source + * @param[in] mask mask + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_swizzle(vec4 v, int mask, vec4 dest) { + vec4 t; + + t[0] = v[(mask & (3 << 0))]; + t[1] = v[(mask & (3 << 2)) >> 2]; + t[2] = v[(mask & (3 << 4)) >> 4]; + t[3] = v[(mask & (3 << 6)) >> 6]; + + glm_vec4_copy(t, dest); +} + +/*! + * @brief Create four dimensional vector from pointer + * + * @param[in] src pointer to an array of floats + * @param[out] dest destination vector + */ +CGLM_INLINE +void +glm_vec4_make(const float * __restrict src, vec4 dest) { + dest[0] = src[0]; dest[1] = src[1]; + dest[2] = src[2]; dest[3] = src[3]; +} + +/*! + * @brief reflection vector using an incident ray and a surface normal + * + * @param[in] v incident vector + * @param[in] n normalized normal vector + * @param[out] dest destination vector for the reflection result + */ +CGLM_INLINE +void +glm_vec4_reflect(vec4 v, vec4 n, vec4 dest) { + vec4 temp; + + /* TODO: direct simd touch */ + glm_vec4_scale(n, 2.0f * glm_vec4_dot(v, n), temp); + glm_vec4_sub(v, temp, dest); + + dest[3] = v[3]; +} + +/*! + * @brief computes refraction vector for an incident vector and a surface normal. + * + * calculates the refraction vector based on Snell's law. If total internal reflection + * occurs (angle too great given eta), dest is set to zero and returns false. + * Otherwise, computes refraction vector, stores it in dest, and returns true. + * + * this implementation does not explicitly preserve the 'w' component of the + * incident vector 'I' in the output 'dest', users requiring the preservation of + * the 'w' component should manually adjust 'dest' after calling this function. + * + * @param[in] v normalized incident vector + * @param[in] n normalized normal vector + * @param[in] eta ratio of indices of refraction (incident/transmitted) + * @param[out] dest refraction vector if refraction occurs; zero vector otherwise + * + * @returns true if refraction occurs; false if total internal reflection occurs. + */ +CGLM_INLINE +bool +glm_vec4_refract(vec4 v, vec4 n, float eta, vec4 dest) { + float ndi, eni, k; + + ndi = glm_vec4_dot(n, v); + eni = eta * ndi; + k = 1.0f - eta * eta + eni * eni; + + if (k < 0.0f) { + glm_vec4_zero(dest); + return false; + } + + glm_vec4_scale(v, eta, dest); + glm_vec4_mulsubs(n, eni + sqrtf(k), dest); + return true; +} + +#endif /* cglm_vec4_h */ diff --git a/external/cglm/version.h b/external/cglm/version.h new file mode 100644 index 0000000..9e815d4 --- /dev/null +++ b/external/cglm/version.h @@ -0,0 +1,15 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_version_h +#define cglm_version_h + +#define CGLM_VERSION_MAJOR 0 +#define CGLM_VERSION_MINOR 9 +#define CGLM_VERSION_PATCH 6 + +#endif /* cglm_version_h */ diff --git a/src/gears/game.d b/src/gears/game.d index 4c317a4..79ad2ac 100644 --- a/src/gears/game.d +++ b/src/gears/game.d @@ -5,14 +5,9 @@ import renderer; import util; import platform; import math; +import core.stdc.math : cosf, sinf; -struct Camera -{ - Vec3 velocity = Vec3(0.0); - Vec3 pos = Vec3(0.0, 0.0, 0.0); - f32 yaw = 0.0; - f32 pitch = 0.0; -} +f32 g_DELTA; struct Game { @@ -28,7 +23,6 @@ struct Game GlobalUniforms globals; PushConst pc; - f32 delta; Timer timer; Camera camera; @@ -79,7 +73,7 @@ InitGame(PlatformWindow* window) { binding: 0, location: 2, format: FMT.RGB_F32, offset: Vertex.pos.offsetof }, { binding: 0, location: 3, format: FMT.RGB_F32, offset: Vertex.normal.offsetof }, { binding: 0, location: 4, format: FMT.RG_F32, offset: Vertex.uv.offsetof }, - ], + ] }; CompPipelineInfo gradient_info = { @@ -101,37 +95,24 @@ InitGame(PlatformWindow* window) void ProcessInputs(Game* g, Camera* cam) { - foreach(i; 0 .. g.window.input_count) - { - bool pressed = g.window.inputs[i].pressed; - switch(g.window.inputs[i].key) - { - case Input.W: cam.velocity.z = pressed ? -1.0 : 0.0; break; - case Input.S: cam.velocity.z = pressed ? +1.0 : 0.0; break; - case Input.A: cam.velocity.x = pressed ? -1.0 : 0.0; break; - case Input.D: cam.velocity.x = pressed ? +1.0 : 0.0; break; - case Input.MouseMotion: - { - // (0, 0) top left - cam.yaw -= cast(f32)(g.window.inputs[i].rel_x) / 200.0; - cam.pitch += cast(f32)(g.window.inputs[i].rel_y) / 200.0; - } break; - default: break; - } - } + HandleInputs(cam, &g.window.inputs); } +/* void Update(Game* g, Camera* cam) { Mat4 rotation = RotationMatrix(cam); - cam.pos += (rotation * Vec4(cam.velocity, 0.0)).xyz * g.delta; + Vec3 v = cam.velocity; + cam.pos += (rotation * Vec4(v.x, v.y, v.z, 0.0)).xyz * g.delta; + Logf("%s", rotation.v); Extent ext = GetExtent(&g.rd); g.globals.view_matrix = ViewMatrix(cam); Perspective(&g.globals.projection_matrix, Radians(90.0), cast(f32)(ext.x), cast(f32)(ext.y), 0.1, 10000.0); g.globals.projection_matrix[1, 1] *= -1.0; + //g.globals.projection_matrix[2, 2] *= -1.0; g.globals.view_projection = g.globals.projection_matrix * g.globals.view_matrix; @@ -157,20 +138,32 @@ ViewMatrix(Camera* cam) Mat4 rotation = RotationMatrix(cam); return Inverse(translation * rotation); } +*/ void Cycle(Game* g) { - g.delta = DeltaTime(&g.timer); + g_DELTA = DeltaTime(&g.timer); ProcessInputs(g, &g.camera); - Update(g, &g.camera); + //Update(g, &g.camera); + + Update(&g.camera); BeginFrame(&g.rd); Bind(&g.rd, &g.compute_pipeline); + + Extent ext = GetExtent(&g.rd); + f32 aspect = (cast(f32)ext.x) / (cast(f32)ext.y); + Mat4 projection = Perspective(90.0, aspect, 0.1, 100.0); + projection[1, 1] *= -1.0; + g.globals.projection_matrix = projection; + g.globals.view_matrix = Mat4Identity(); //g.camera.view; + g.globals.res.x = ext.x; + g.globals.res.y = ext.y; SetUniform(&g.rd, &g.globals); //DrawRect(&g.rd, 150.0, 300.0, 500.0, 700.0, Vec4(0.0, 0.0, 1.0, 1.0)); @@ -193,11 +186,7 @@ Cycle(Game* g) Bind(&g.rd, &g.pbr_pipeline); - Quat q; - static f32 angle = 0.0; - angle += 1.0 * g.delta; - QuatFromAxis(&q, angle, Vec3(0.0, 1.0, 0.0)); - g.pc.model_matrix = cast(Mat4)(q); + g.pc.model_matrix = Mat4Identity(); DrawModel(g, &g.model); FinishFrame(&g.rd); @@ -225,3 +214,95 @@ Destroy(Game* g) Destroy(&g.rd, &g.compute_pipeline); Destroy(&g.rd); } + +struct Camera +{ + Mat4 view = Mat4Identity(); + Vec3 pos = Vec3(0.0, 0.0, 2.0); + Vec3 front = Vec3(0.0, 0.0, -1.0); + Vec3 up = Vec3(0.0, 1.0, 0.0); + Vec3 right = Vec3(0.0); + Vec3 world_up = Vec3(0.0, 1.0, 0.0); + f32 speed = 5000.0; + f32 yaw = -90.0; + f32 pitch = 0.0; +} + +pragma(inline): void +HandleInputs(Camera* cam, Inputs* inputs) +{ + f32 velocity = cam.speed * g_DELTA; + + Logf("pos %s pitch %s yaw %s", cam.pos.v, cam.pitch, cam.yaw); + + foreach(i; 0 .. inputs.count) + { + InputEvent event = inputs.events[i]; + switch(event.key) + { + case Input.W: + { + if (!event.pressed) continue; + cam.pos += cam.front * velocity; + } break; + case Input.S: + { + if (!event.pressed) continue; + cam.pos -= cam.front * velocity; + } break; + case Input.A: + { + if (!event.pressed) continue; + cam.pos -= cam.right * velocity; + } break; + case Input.D: + { + if (!event.pressed) continue; + cam.pos += cam.right * velocity; + } break; + case Input.Space: + { + if (!event.pressed) continue; + cam.pos += cam.up * velocity; + } break; + case Input.LeftCtrl: + { + if (!event.pressed) continue; + cam.pos -= cam.up * velocity; + } break; + case Input.MouseMotion: + { + Logf("Mouse Motion"); + // (0, 0) top left + cam.yaw += cast(f32)(event.rel_x) / 20.0; + cam.pitch += cast(f32)(event.rel_y) / 20.0; + + if (cam.pitch > 90.0) + { + cam.pitch = 90.0; + } + if (cam.pitch < -90.0) + { + cam.pitch = -90.0; + } + } break; + default: break; + } + } +} + +pragma(inline): void +Update(Camera* cam) +{ + Vec3 front = Vec3(0.0); + + front.x = cosf(Radians(cam.yaw)) * cosf(Radians(cam.pitch)); + front.y = sinf(Radians(cam.pitch)); + front.z = sinf(Radians(cam.yaw)) * cosf(Radians(cam.pitch)); + cam.front = Normalize(front); + + cam.right = Normalize(Cross(cam.front, cam.world_up)); + cam.up = Normalize(Cross(cam.right, cam.front)); + + cam.view = LookAt(cam.pos, cam.pos + cam.front, cam.up); +} diff --git a/src/gears/platform.d b/src/gears/platform.d index 2b73b6d..1acc0cb 100644 --- a/src/gears/platform.d +++ b/src/gears/platform.d @@ -60,6 +60,12 @@ struct InputEvent }; } +struct Inputs +{ + InputEvent[10] events; + u32 count; +} + struct PlatformWindow { Display *display; @@ -74,8 +80,7 @@ struct PlatformWindow i32 mouse_prev_y; bool locked_cursor; bool close; - InputEvent[10] inputs; - u32 input_count; + Inputs inputs; }; struct Library @@ -287,7 +292,7 @@ FlushEvents(PlatformWindow* window) void HandleEvents(PlatformWindow* window) { - window.input_count = 0; + window.inputs.count = 0; xcb_generic_event_t* e; @@ -318,7 +323,7 @@ HandleEvents(PlatformWindow* window) case XCB_KEY_PRESS: { // TODO: definitely definitely need to rework this whole thing - if (window.input_count == window.inputs.length) + if (window.inputs.count == window.inputs.events.length) { continue; } @@ -332,9 +337,9 @@ HandleEvents(PlatformWindow* window) if (input != KBI.None) { - window.inputs[window.input_count].key = input; - window.inputs[window.input_count].pressed = pressed; - window.input_count += 1; + window.inputs.events[window.inputs.count].key = input; + window.inputs.events[window.inputs.count].pressed = pressed; + window.inputs.count += 1; if (input == KBI.F2) { @@ -349,7 +354,7 @@ HandleEvents(PlatformWindow* window) case XCB_BUTTON_PRESS: case XCB_BUTTON_RELEASE: { - if (window.input_count == window.inputs.length) continue; + if (window.inputs.count == window.inputs.events.length) continue; xcb_button_press_event_t* mouse_event = cast(xcb_button_press_event_t*)e; bool pressed = e.response_type == XCB_BUTTON_PRESS; @@ -365,15 +370,15 @@ HandleEvents(PlatformWindow* window) if (input != Input.None) { - window.inputs[window.input_count].key = input; - window.inputs[window.input_count].pressed = pressed; - window.input_count += 1; + window.inputs.events[window.inputs.count].key = input; + window.inputs.events[window.inputs.count].pressed = pressed; + window.inputs.count += 1; } } break; case XCB_MOTION_NOTIFY: { if (ignore_mouse_events) continue; - if (window.input_count == window.inputs.length) continue; + if (window.inputs.count == window.inputs.events.length) continue; xcb_motion_notify_event_t* move_event = cast(xcb_motion_notify_event_t*)e; @@ -390,12 +395,12 @@ HandleEvents(PlatformWindow* window) if (x > 0 || y > 0) { - window.inputs[window.input_count].key = Input.MouseMotion; - window.inputs[window.input_count].x = move_event.event_x; - window.inputs[window.input_count].y = move_event.event_y; - window.inputs[window.input_count].rel_x = window.mouse_prev_x - x; - window.inputs[window.input_count].rel_y = window.mouse_prev_y - y; - window.input_count += 1; + window.inputs.events[window.inputs.count].key = Input.MouseMotion; + window.inputs.events[window.inputs.count].x = move_event.event_x; + window.inputs.events[window.inputs.count].y = move_event.event_y; + window.inputs.events[window.inputs.count].rel_x = window.mouse_prev_x - x; + window.inputs.events[window.inputs.count].rel_y = window.mouse_prev_y - y; + window.inputs.count += 1; } window.mouse_prev_x = x; @@ -544,7 +549,7 @@ ConvertInput(u64 x_key) case XK_E: return KBI.E; case XK_f: case XK_F: return KBI.F; - case XK_g: +case XK_g: case XK_G: return KBI.G; case XK_h: case XK_H: return KBI.H; diff --git a/src/gears/renderer.d b/src/gears/renderer.d index 246ed4e..664dd6a 100644 --- a/src/gears/renderer.d +++ b/src/gears/renderer.d @@ -55,10 +55,11 @@ struct GlobalUniforms { Mat4 view_matrix = Mat4Identity(); Mat4 projection_matrix = Mat4Identity(); - Mat4 view_projection = Mat4Identity(); + Mat4 projection_view = Mat4Identity(); Vec4 light_color; Vec4 ambient_color; - align(16): Vec3 light_direction; + Vec3 light_direction; + f32 padding; Vec2 res; } @@ -186,6 +187,12 @@ GetExtent(Renderer* rd) return Extent(rd.vk.swapchain_extent.width, rd.vk.swapchain_extent.height); } +pragma(inline): f32 +GetAspect(Renderer* rd) +{ + return cast(f32)(rd.vk.swapchain_extent.width) / cast(f32)(rd.vk.swapchain_extent.height); +} + pragma(inline): void BeginFrame(Renderer* rd) { @@ -549,3 +556,4 @@ PrintShader(Renderer* rd, Pipeline* pipeline, VkShaderStageFlagBits stage) { PrintShaderDisassembly(&rd.vk, pipeline, stage); } + diff --git a/src/gears/vulkan.d b/src/gears/vulkan.d index b935e6c..24e53f9 100644 --- a/src/gears/vulkan.d +++ b/src/gears/vulkan.d @@ -1284,7 +1284,7 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info) VkPipelineRasterizationStateCreateInfo rasterization_info = { sType: VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - //cullMode: VK_CULL_MODE_BACK_BIT, + cullMode: VK_CULL_MODE_BACK_BIT, polygonMode: VK_POLYGON_MODE_FILL, lineWidth: 1.0, frontFace: VK_FRONT_FACE_COUNTER_CLOCKWISE, @@ -1303,7 +1303,7 @@ CreateGraphicsPipeline(Vulkan* vk, GfxPipelineInfo* build_info) depthTestEnable: VK_TRUE, depthWriteEnable: VK_TRUE, depthCompareOp: VK_COMPARE_OP_GREATER_OR_EQUAL, - depthBoundsTestEnable: VK_FALSE, + depthBoundsTestEnable: VK_TRUE, stencilTestEnable: VK_FALSE, minDepthBounds: 0.0, maxDepthBounds: 1.0, diff --git a/src/shaders/structures.layout b/src/shaders/structures.layout index 01a73e9..5def1fa 100644 --- a/src/shaders/structures.layout +++ b/src/shaders/structures.layout @@ -5,7 +5,7 @@ layout (set = 0, binding = 0) uniform GlobalUniforms { mat4 view_matrix; mat4 projection_matrix; - mat4 view_projection; + mat4 projection_view; vec4 light_color; vec4 ambient_color; vec3 light_direction; diff --git a/src/shared/includes.c b/src/shared/includes.c index 297b8ef..b32e952 100644 --- a/src/shared/includes.c +++ b/src/shared/includes.c @@ -32,3 +32,6 @@ #include "../../external/m3d/m3d.h" +#define CGLM_FORCE_DEPTH_ZERO_TO_ONE + +#include "../../external/cglm/cglm.h" diff --git a/src/shared/math.d b/src/shared/math.d index d8f09e5..93d1081 100644 --- a/src/shared/math.d +++ b/src/shared/math.d @@ -1,6 +1,7 @@ import aliases; import util; import std.math; +import std.math.algebraic; import core.stdc.math : tanf, cosf, sinf, sqrtf; import std.traits; import inteli; @@ -57,9 +58,9 @@ struct Vector(T, int N) } } - nothrow @nogc pure: + nothrow @nogc: - this(Vec3, f32)(Vec3 v3, f32 f) + this(Vec3, f32)(Vec3 v3, f32 f) if (N == 4 && is(T: f32)) { x = v3.x; y = v3.y; @@ -125,19 +126,13 @@ struct Vector(T, int N) return v.ptr; } - bool opEquals(U)(U other) if (IsConvertible!(U)) - { - Vector conv = other; - return opEquals(conv); - } - - Vector opEquals(U)(U other) if (is(U: Vector)) + bool opEquals(U)(U other) if (is(U: Vector!(T, N))) { bool result = true; - + foreach(i; 0 .. N) { - if (v[i] != other.v[i]) + if (fabs(v[i] - other.v[i]) > 0.0000009) { result = false; break; @@ -206,7 +201,7 @@ struct Vector(T, int N) f32* r = &operand.x; f32* res = &result.x; - asm pure @nogc nothrow + asm @nogc nothrow { mov R8, l; mov R9, r; @@ -214,11 +209,11 @@ struct Vector(T, int N) movups XMM0, x.offsetof[R8]; movups XMM1, operand.x.offsetof[R9]; } - static if (op == "*") asm pure @nogc nothrow { mulps XMM0, XMM1; } - else static if (op == "-") asm pure @nogc nothrow { subps XMM0, XMM1; } - else static if (op == "+") asm pure @nogc nothrow { addps XMM0, XMM1; } - else static if (op == "/") asm pure @nogc nothrow { divps XMM0, XMM1; } - asm pure @nogc nothrow + static if (op == "*") asm @nogc nothrow { mulps XMM0, XMM1; } + else static if (op == "-") asm @nogc nothrow { subps XMM0, XMM1; } + else static if (op == "+") asm @nogc nothrow { addps XMM0, XMM1; } + else static if (op == "/") asm @nogc nothrow { divps XMM0, XMM1; } + asm @nogc nothrow { movups result.x.offsetof[R10], XMM0; } @@ -234,7 +229,7 @@ struct Vector(T, int N) f32* r = &other.x; f32* res = &result.x; - asm pure @nogc nothrow + asm @nogc nothrow { mov R8, l; mov R9, r; @@ -242,11 +237,11 @@ struct Vector(T, int N) movups XMM0, x.offsetof[R8]; movups XMM1, other.x.offsetof[R9]; } - static if (op == "*") asm pure @nogc nothrow { mulps XMM0, XMM1; } - else static if (op == "-") asm pure @nogc nothrow { subps XMM0, XMM1; } - else static if (op == "+") asm pure @nogc nothrow { addps XMM0, XMM1; } - else static if (op == "/") asm pure @nogc nothrow { divps XMM0, XMM1; } - asm pure @nogc nothrow + static if (op == "*") asm @nogc nothrow { mulps XMM0, XMM1; } + else static if (op == "-") asm @nogc nothrow { subps XMM0, XMM1; } + else static if (op == "+") asm @nogc nothrow { addps XMM0, XMM1; } + else static if (op == "/") asm @nogc nothrow { divps XMM0, XMM1; } + asm @nogc nothrow { movups result.x.offsetof[R8], XMM0; } @@ -389,6 +384,7 @@ struct Matrix(T, int D) alias Vector!(T, D) MatrixVec; alias T _T; + alias T[4] Row; enum N = D*D; enum _D = D; @@ -396,6 +392,7 @@ struct Matrix(T, int D) union { T[N] v; + Row[D] rows; MatrixVec[D] vec; } @@ -470,6 +467,21 @@ struct Matrix(T, int D) return v[(i * D) + j] = x; } + bool opEquals(U)(U other) if (is(U: Matrix!(T, D))) + { + bool result = true; + + static foreach(i; 0 .. N) + { + if (fabs(this.v[i] - other.v[i]) > 0.0000009) + { + result = false; + } + } + + return result; + } + Matrix opBinary(string op)(T scalar) if (op == "*") { Matrix result; @@ -499,7 +511,7 @@ struct Matrix(T, int D) auto m = &this; auto v = &x; - asm pure @trusted @nogc nothrow + asm @trusted @nogc nothrow { mov R8, m; mov R9, v; @@ -534,131 +546,40 @@ struct Matrix(T, int D) return result; } - Matrix opBinary(string op, U)(U x) if (is(U: Matrix!(T, D)) && is(T: f32) && (op == "*")) + Matrix opBinary(string op, U)(U x) if (is(U: Matrix!(T, D)) && is(T: f32) && D == 4 && (op == "*")) { Matrix result; + MatZero(&result); - auto res = &result; - auto l = &this; - auto r = &x; + Row[D] m1 = rows; + Row[D] m2 = x.rows; + f32 a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], a03 = m1[0][3], + a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2], a13 = m1[1][3], + a20 = m1[2][0], a21 = m1[2][1], a22 = m1[2][2], a23 = m1[2][3], + a30 = m1[3][0], a31 = m1[3][1], a32 = m1[3][2], a33 = m1[3][3], - // TODO: Test assembly on windows - asm pure @trusted @nogc nothrow - { - mov R8, l; - mov R9, r; - mov R10, res; + b00 = m2[0][0], b01 = m2[0][1], b02 = m2[0][2], b03 = m2[0][3], + b10 = m2[1][0], b11 = m2[1][1], b12 = m2[1][2], b13 = m2[1][3], + b20 = m2[2][0], b21 = m2[2][1], b22 = m2[2][2], b23 = m2[2][3], + b30 = m2[3][0], b31 = m2[3][1], b32 = m2[3][2], b33 = m2[3][3]; - movups XMM0, vec.offsetof[R8]; - movups XMM1, x.vec.offsetof[R9]; - movups XMM2, x.vec.offsetof[R9]+16; - movups XMM3, x.vec.offsetof[R9]+32; - movups XMM4, x.vec.offsetof[R9]+48; - - movups XMM5, XMM1; - shufps XMM5, XMM5, 0; // XMM5 = vec.xxxx; - mulps XMM5, XMM0; - movups XMM6, XMM5; // XMM6 = col1; - - movups XMM5, XMM2; - shufps XMM5, XMM5, 0; - mulps XMM5, XMM0; - movups XMM7, XMM5; // XMM7 = col2; - - movups XMM5, XMM3; - shufps XMM5, XMM5, 0; - mulps XMM5, XMM0; - movups XMM8, XMM5; // XMM8 = col3; - - movups XMM5, XMM3; - shufps XMM5, XMM5, 0; - mulps XMM5, XMM0; - movups XMM9, XMM5; // XMM9 = col4; - - movups XMM0, vec.offsetof[R8]+16; - - movups XMM5, XMM1; - shufps XMM5, XMM5, 85; // XMM5 = vec.yyyy; - movups XMM10, XMM0; - mulps XMM10, XMM5; - addps XMM6, XMM10; - - movups XMM5, XMM2; - shufps XMM5, XMM5, 85; - movups XMM10, XMM0; - mulps XMM10, XMM5; - addps XMM7, XMM10; - - movups XMM5, XMM3; - shufps XMM5, XMM5, 85; - movups XMM10, XMM0; - mulps XMM10, XMM5; - addps XMM8, XMM10; - - movups XMM5, XMM4; - shufps XMM5, XMM5, 85; - movups XMM10, XMM0; - mulps XMM10, XMM5; - addps XMM9, XMM10; - - movups XMM0, vec.offsetof[R8]+32; - - movups XMM5, XMM1; - shufps XMM5, XMM5, 170; // XMM5 = vec.zzzz; - movups XMM10, XMM0; - mulps XMM10, XMM5; - addps XMM6, XMM10; - - movups XMM5, XMM2; - shufps XMM5, XMM5, 170; - movups XMM10, XMM0; - mulps XMM10, XMM5; - addps XMM7, XMM10; - - movups XMM5, XMM3; - shufps XMM5, XMM5, 170; - movups XMM10, XMM0; - mulps XMM10, XMM5; - addps XMM8, XMM10; - - movups XMM5, XMM4; - shufps XMM5, XMM5, 170; - movups XMM10, XMM0; - mulps XMM10, XMM5; - addps XMM9, XMM10; - - movups XMM0, vec.offsetof[R8]+48; - - movups XMM5, XMM1; - shufps XMM5, XMM5, 255; // XMM5 = vec.wwww; - movups XMM10, XMM0; - mulps XMM10, XMM5; - addps XMM6, XMM10; - - movups XMM5, XMM2; - shufps XMM5, XMM5, 255; - movups XMM10, XMM0; - mulps XMM10, XMM5; - addps XMM7, XMM10; - - movups XMM5, XMM3; - shufps XMM5, XMM5, 255; - movups XMM10, XMM0; - mulps XMM10, XMM5; - addps XMM8, XMM10; - - movups XMM5, XMM4; - shufps XMM5, XMM5, 255; - movups XMM10, XMM0; - mulps XMM10, XMM5; - addps XMM9, XMM10; - - movups result.vec.offsetof[R10]+00, XMM6; - movups result.vec.offsetof[R10]+16, XMM7; - movups result.vec.offsetof[R10]+32, XMM8; - movups result.vec.offsetof[R10]+48, XMM9; - } + result[0, 0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03; + result[0, 1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03; + result[0, 2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03; + result[0, 3] = a03 * b00 + a13 * b01 + a23 * b02 + a33 * b03; + result[1, 0] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13; + result[1, 1] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13; + result[1, 2] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13; + result[1, 3] = a03 * b10 + a13 * b11 + a23 * b12 + a33 * b13; + result[2, 0] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23; + result[2, 1] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23; + result[2, 2] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23; + result[2, 3] = a03 * b20 + a13 * b21 + a23 * b22 + a33 * b23; + result[3, 0] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33; + result[3, 1] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33; + result[3, 2] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33; + result[3, 3] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33; return result; } @@ -679,6 +600,8 @@ struct Matrix(T, int D) struct Quat { + @nogc nothrow: + union { f32[4] v; @@ -738,6 +661,131 @@ struct Quat return mat; } + + Quat opBinary(string op, U)(U r) if (op == "*" && is(U: Quat)) + { + Quat q; + + q.x = this.w * r.x + this.x * r.w + this.y * r.z - this.z * r.y; + q.y = this.w * r.y - this.x * r.z + this.y * r.w + this.z * r.x; + q.z = this.w * r.z + this.x * r.y - this.y * r.x + this.z * r.w; + q.w = this.w * r.w - this.x * r.x - this.y * r.y - this.z * r.z; + + return q; + } +} + +Mat4 +Mat4MulASM(Mat4 l, Mat4 r) +{ + Mat4 result; + + auto lp = &l; + auto rp = &r; + auto res = &result; + + // TODO: fix this + asm @trusted @nogc nothrow + { + mov R8, lp; + mov R9, rp; + mov R10, res; + + movups XMM0, [R8]; + movups XMM1, [R9+00]; + movups XMM2, [R9+16]; + movups XMM3, [R9+32]; + movups XMM4, [R9+48]; + + movups XMM6, XMM1; + shufps XMM6, XMM6, 0; // XMM5 = vec.xxxx; + mulps XMM6, XMM0; // XMM6 = col1; + + movups XMM7, XMM2; + shufps XMM7, XMM7, 0; + mulps XMM7, XMM0; // XMM7 = col2; + + movups XMM8, XMM3; + shufps XMM8, XMM8, 0; + mulps XMM8, XMM0; // XMM8 = col3; + + movups XMM9, XMM3; + shufps XMM9, XMM9, 0; + mulps XMM9, XMM0; // XMM9 = col4; + + movups XMM0, [R8+16]; + + movups XMM5, XMM1; + shufps XMM5, XMM5, 85; // XMM5 = vec.yyyy; + mulps XMM5, XMM0; + addps XMM6, XMM5; + + movups XMM5, XMM2; + shufps XMM5, XMM5, 85; + mulps XMM5, XMM0; + addps XMM7, XMM5; + + movups XMM5, XMM3; + shufps XMM5, XMM5, 85; + mulps XMM5, XMM0; + addps XMM8, XMM5; + + movups XMM5, XMM4; + shufps XMM5, XMM5, 85; + mulps XMM5, XMM0; + addps XMM9, XMM5; + + movups XMM0, [R8+32]; + + movups XMM5, XMM1; + shufps XMM5, XMM5, 170; // XMM5 = vec.zzzz; + mulps XMM5, XMM0; + addps XMM6, XMM5; + + movups XMM5, XMM2; + shufps XMM5, XMM5, 170; + mulps XMM5, XMM0; + addps XMM7, XMM5; + + movups XMM5, XMM3; + shufps XMM5, XMM5, 170; + mulps XMM5, XMM0; + addps XMM8, XMM5; + + movups XMM5, XMM4; + shufps XMM5, XMM5, 170; + mulps XMM5, XMM0; + addps XMM9, XMM5; + + movups XMM0, [R8+48]; + + movups XMM5, XMM1; + shufps XMM5, XMM5, 255; // XMM5 = vec.wwww; + mulps XMM5, XMM0; + addps XMM6, XMM5; + + movups XMM5, XMM2; + shufps XMM5, XMM5, 255; + mulps XMM5, XMM0; + addps XMM7, XMM5; + + movups XMM5, XMM3; + shufps XMM5, XMM5, 255; + mulps XMM5, XMM0; + addps XMM8, XMM5; + + movups XMM5, XMM4; + shufps XMM5, XMM5, 255; + mulps XMM5, XMM0; + addps XMM9, XMM5; + + movups [R10+00], XMM6; + movups [R10+16], XMM7; + movups [R10+32], XMM8; + movups [R10+48], XMM9; + } + + return result; } nothrow @nogc pragma(inline): Mat4 @@ -790,7 +838,7 @@ QuatFromAxis(Quat* q, f32 angle, Vec3 axis) f32 c = cosf(a); f32 s = sinf(a); - NormalizeTo(&axis, &k); + k = Normalize(axis); q.x = s * k.x; q.y = s * k.y; @@ -834,44 +882,128 @@ pragma(inline): void Normalize(T)(T* vec) if (is(T: Vec2) || is(T: Vec3) || is(T: Vec4)) { f32 length = Norm(vec); - mixin(GenerateLoop!("vec.v[@] /= length;", vec._N)()); + + if (length < f32.epsilon) + { + mixin(GenerateLoop!("vec.v[@] = 0.0;", vec._N)()); + } + else + { + mixin(GenerateLoop!("vec.v[@] *= (1.0 / length);", vec._N)()); + } } -pragma(inline): Vector +pragma(inline): T Normalize(T)(T vec) if (is(T: Vec2) || is(T: Vec3) || is(T: Vec4)) { Normalize(&vec); return vec; } -pragma(inline): void -NormalizeTo(Vec3* v, Vec3* dst) +pragma(inline): Quat +Normalize(Quat q) { - f32 norm = Norm(v); + f32 dot = Norm(&q.vec); + + if (dot <= 0.0) + { + q = Quat(1.0, 0.0, 0.0, 0.0); + } - if (norm < f32.epsilon) - { - dst.x = dst.y = dst.z = 0.0; - } - else - { - *dst = (*v) * (1.0 / norm); - } + q.vec *= 1.0 / sqrtf(dot); + + return q; } -pragma(inline): void -Perspective(Mat4* mat, f32 fov, f32 width, f32 height, f32 near, f32 far) +pragma(inline): Mat4 +Perspective(f32 fov, f32 aspect, f32 near, f32 far) { - MatZero(mat); + Mat4 mat; + MatZero(&mat); f32 f = 1.0 / tanf(fov * 0.5); f32 fn = 1.0 / (near - far); - (*mat)[0, 0] = f / (width / height); - (*mat)[1, 1] = f; - (*mat)[2, 2] = far * fn; - (*mat)[2, 3] = -1.0; - (*mat)[3, 2] = near * far * fn; + mat[0, 0] = f / aspect; + mat[1, 1] = f; + mat[2, 2] = far * fn; + mat[2, 3] = -1.0; + mat[3, 2] = near * far * fn; + + return mat; +} + +pragma(inline): Vec3 +Rotate(Quat q, Vec3 vec) +{ + Quat p = Normalize(q); + + Vec3 i = p.vec.xyz; + f32 r = p.vec.w; + + Vec3 v1 = i * (2.0 * Dot(&i, &vec)); + Vec3 v2 = i * (r * r - Dot(&i, &i)); + v1 += v2; + + v2 = i * vec; + v2 = v2 * (2.0 * r); + + return v1 + v2; +} + +pragma(inline): Mat4 +LookAt(Vec3 eye, Vec3 center, Vec3 up) +{ + Vec3 f = Normalize(center - eye); + Vec3 s = CrossN(f, up); + Vec3 u = Cross(s, f); + + Mat4 mat; + + return Mat4( + +s.x, +s.y, +s.z, -Dot(&s, &eye), + +u.x, +u.y, +u.z, -Dot(&u, &eye), + -f.x, -f.y, -f.z, -Dot(&f, &eye), + 0.0, 0.0, 0.0, 1.0, + ); +} + +pragma(inline): Mat4 +Look(Vec3 eye, Vec3 dir, Vec3 up) +{ + return LookAt(eye, eye + dir, up); +} + +pragma(inline): Vec3 +Cross(Vec3 a, Vec3 b) +{ + Vec3 c; + Cross(a, b, &c); + return c; +} + +pragma(inline): Vec3 +CrossN(Vec3 a, Vec3 b) +{ + Vec3 c; + Cross(a, b, &c); + Normalize(&c); + return c; +} + +pragma(inline): void +CrossN(Vec3 a, Vec3 b, Vec3* dst) +{ + Cross(a, b, dst); + Normalize(dst); +} + +pragma(inline): void +Cross(Vec3 a, Vec3 b, Vec3* dst) +{ + dst.x = a.y * b.z - a.z * b.y; + dst.y = a.z * b.x - a.x * b.z; + dst.z = a.x * b.y - a.y * b.x; } pragma(inline): void @@ -898,6 +1030,70 @@ Translate(Mat4* mat, Vec3 vec) (*mat)[3, 2] = vec[2]; } +pragma(inline): void +Rotate(Mat4* mat, f32 angle, Vec3 axis) +{ + Mat4 rot = Rotate(angle, axis); + MultiplyRotate(mat, &rot, mat); +} + +pragma(inline): void +MultiplyRotate(Mat4* m1, Mat4* m2, Mat4* dst) +{ + f32 a00 = (*m1)[0, 0], a01 = (*m1)[0, 1], a02 = (*m1)[0, 2], a03 = (*m1)[0, 3], + a10 = (*m1)[1, 0], a11 = (*m1)[1, 1], a12 = (*m1)[1, 2], a13 = (*m1)[1, 3], + a20 = (*m1)[2, 0], a21 = (*m1)[2, 1], a22 = (*m1)[2, 2], a23 = (*m1)[2, 3], + a30 = (*m1)[3, 0], a31 = (*m1)[3, 1], a32 = (*m1)[3, 2], a33 = (*m1)[3, 3], + + b00 = (*m2)[0, 0], b01 = (*m2)[0, 1], b02 = (*m2)[0, 2], + b10 = (*m2)[1, 0], b11 = (*m2)[1, 1], b12 = (*m2)[1, 2], + b20 = (*m2)[2, 0], b21 = (*m2)[2, 1], b22 = (*m2)[2, 2]; + + (*dst)[0, 0] = a00 * b00 + a10 * b01 + a20 * b02; + (*dst)[0, 1] = a01 * b00 + a11 * b01 + a21 * b02; + (*dst)[0, 2] = a02 * b00 + a12 * b01 + a22 * b02; + (*dst)[0, 3] = a03 * b00 + a13 * b01 + a23 * b02; + + (*dst)[1, 0] = a00 * b10 + a10 * b11 + a20 * b12; + (*dst)[1, 1] = a01 * b10 + a11 * b11 + a21 * b12; + (*dst)[1, 2] = a02 * b10 + a12 * b11 + a22 * b12; + (*dst)[1, 3] = a03 * b10 + a13 * b11 + a23 * b12; + + (*dst)[2, 0] = a00 * b20 + a10 * b21 + a20 * b22; + (*dst)[2, 1] = a01 * b20 + a11 * b21 + a21 * b22; + (*dst)[2, 2] = a02 * b20 + a12 * b21 + a22 * b22; + (*dst)[2, 3] = a03 * b20 + a13 * b21 + a23 * b22; + + (*dst)[3, 0] = a30; + (*dst)[3, 1] = a31; + (*dst)[3, 2] = a32; + (*dst)[3, 3] = a33; +} + +pragma(inline): Mat4 +Rotate(f32 angle, Vec3 axis) +{ + f32 c = cosf(angle); + + Vec3 axis_normal = Normalize(axis); + Vec3 v = axis_normal * (1.0 - c); + Vec3 vs = axis_normal * sinf(angle); + + Mat4 mat; + mat.vec[0].xyz = axis_normal * v.x; + mat.vec[1].xyz = axis_normal * v.y; + mat.vec[2].xyz = axis_normal * v.z; + + mat[0, 0] += c; mat[1, 0] -= vs.z; mat[2, 0] += vs.y; + mat[0, 1] += vs.z; mat[1, 1] += c; mat[2, 1] -= vs.x; + mat[0, 2] -= vs.y; mat[1, 2] += vs.x; mat[2, 2] += c; + + mat[0, 3] = mat[1, 3] = mat[3, 0] = mat[3, 2] = 0.0; + mat[3, 3] = 1.0; + + return mat; +} + pragma(inline): Mat4 Inverse(Mat4 mat) { @@ -939,6 +1135,25 @@ Inverse(Mat4 mat) return res; } +pragma(inline): f32 +Mix(f32 x, f32 y, f32 a) +{ + return x * (1 - a) + y * a; +} + +pragma(inline): f32 +InverseLerp(f32 v, f32 min, f32 max) +{ + return (v - min) / (max - min); +} + +pragma(inline): f32 +Remap(f32 v, f32 in_min, f32 in_max, f32 out_min, f32 out_max) +{ + f32 t = InverseLerp(v, in_min, in_max); + return Mix(out_min, out_max, t); +} + pragma(inline): T SquaredMagnitude(T)(T v) if (IsVector!(T)) { @@ -953,3 +1168,211 @@ SquaredDistTo(T)(T l, T r) if (IsVector!(T)) return SquaredMagnitude(r - l); } +unittest +{ + enum FLOAT_MAX = f32.max; + enum FLOAT_MIN = -f32.max; + + import core.stdc.stdio; + import core.stdc.stdlib; + import core.stdc.time; + import std.range : take; + import std.algorithm.iteration : sum; + + void PrintMatrix(Mat4 mat) + { + foreach(i; 0 .. mat.N) + { + if (i % 4 == 0) + { + printf("\n"); + } + printf("%.08f ", mat.v[i]); + } + printf("\n"); + } + + srand(cast(u32)time(null)); + + f32 RandomFloat() + { + return cast(f32)(rand())/cast(f32)(RAND_MAX + 1.0); + } + + Mat4 RandomMat4() + { + Mat4 mat; + Mat4Identity(&mat); + mat[3, 0] = RandomFloat(); + mat[3, 1] = RandomFloat(); + mat[3, 2] = RandomFloat(); + + Rotate(&mat, RandomFloat(), Vec3(RandomFloat(), RandomFloat(), RandomFloat())); + + return mat; + } + + { // Vec2 arithmetic + Vec2 v1 = Vec2(5.0, 10.0); + Vec2 v2 = Vec2(2.5, 5.0); + + Vec2 result = v1 * v2; + + assert(result == Vec2(12.5, 50.0), "Vec2 mul failure"); + + result = v1 + v2; + + assert(result == Vec2(7.5, 15.0), "Vec2 add failure"); + + result = v1 - v2; + + assert(result == Vec2(2.5, 5.0), "Vec2 sub failure"); + + result = v1 / v2; + + assert(result == Vec2(2.0), "Vec2 div failure"); + } + + { // Vec3 Arithmetic + Vec3 v1 = Vec3(5.0, 10.0, 15.0); + Vec3 v2 = Vec3(2.5, 5.0, 7.5); + + Vec3 result = v1 * v2; + + assert(result == Vec3(12.5, 50.0, 112.5), "Vec3 mul failure"); + + result = v1 + v2; + + assert(result == Vec3(7.5, 15.0, 22.5), "Vec3 add failure"); + + result = v1 - v2; + + assert(result == Vec3(2.5, 5.0, 7.5), "Vec3 sub failure"); + + result = v1 / v2; + + assert(result == Vec3(2.0), "Vec3 div failure"); + } + + { // Vec3 Arithmetic + Vec4 v1 = Vec4(5.0, 10.0, 15.0, 20.0); + Vec4 v2 = Vec4(2.5, 5.0, 7.5, 10.0); + + Vec4 result = v1 * v2; + + assert(result == Vec4(12.5, 50.0, 112.5, 200.0), "Vec4 mul failure"); + + result = v1 + v2; + + assert(result == Vec4(7.5, 15.0, 22.5, 30.0), "Vec4 add failure"); + + result = v1 - v2; + + assert(result == Vec4(2.5, 5.0, 7.5, 10.0), "Vec4 sub failure"); + + result = v1 / v2; + + assert(result == Vec4(2.0), "Vec4 div failure"); + } + + { // Mat4 Arithmetic + Mat4 m1 = RandomMat4(); + Mat4 m2 = RandomMat4(); + Mat4 m3 = m1 * m2; + Mat4 m4; + + MatZero(&m4); + + for(u32 i = 0; i < 4; i += 1) + { + for(u32 j = 0; j < 4; j += 1) + { + for(u32 k = 0; k < 4; k += 1) + { + m4.rows[i][j] += m1.rows[k][j] * m2.rows[i][k]; + } + } + } + + assert(m3 == m4, "Mat4 mul failure"); + } + + { // Translate + Mat4 mat = Mat4Identity(); + Vec4 vec = Vec4(1.0, 2.0, 3.0, 1.0); + + Translate(&mat, Vec3(13.0, 11.0, 7.0)); + Vec4 result = mat * vec; + + assert(result == Vec4(14.0, 13.0, 10.0, 1.0)); + + mat = Mat4Identity(); + Translate(&mat, Vec3(1.0, -1.0, -5.0)); + result = mat * result; + + assert(result == Vec4(15.0, 12.0, 5.0, 1.0)); + } + + { // Identity + Mat4 identity = Mat4( + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 + ); + Mat4 mat = Mat4Identity(); + + assert(identity == mat); + } + + + { // Inverse + foreach(i; 0 .. 1000) + { + Mat4 m1 = RandomMat4(); + + Mat4 m1_inv = Inverse(m1); + Mat4 m1_reinv = Inverse(m1_inv); + + assert(m1 == m1_reinv, "Inverse test failed"); + } + } + + { // Cross + Vec3 v1 = Vec3(2.0, -3.0, 4.0); + Vec3 v2 = Vec3(12.0, -31.0, 43.0); + + Vec3 v3 = Cross(v1, v2); + + Vec3 v4 = Vec3( + v1.y * v2.z - v1.z * v2.y, + v1.z * v2.x - v1.x * v2.z, + v1.x * v2.y - v1.y * v2.x + ); + + assert(v3 == v4, "Vec3 Cross failure"); + + v3 = CrossN(v1, v2); + + Normalize(&v4); + + assert(v3 == v4, "Vec3 CrossN failure"); + } + + { // LookAt + Vec3 eye = Vec3(0.024, 14.6, 67.04); + Vec3 dir = Vec3(0.0, 0.0, -1.0); + Vec3 up = Vec3(0.0, 1.0, 0.0); + + Vec3 center = eye + dir; + Mat4 view1 = LookAt(eye, center, up); + Mat4 view2 = Mat4( + 1.0, -0.0, 0.0, -0.024, + 0.0, 1.0, 0.0, -14.6, + -0.0, -0.0, 1.0, 67.04, + 0.0, 0.0, 0.0, 1.0 + ); + + assert(view1 == view2, "LookAt failure"); + } +}